Перейти к содержанию
    

Мне не нужны старые данные. Поэтому вариант с затиранием подходит. Интересовало насколько это корректно.

 

Отсылать самому себе сигнал очень удобно в следующей ситуации.

Есть два процесса. Процесс 1 производит опрос, Процесс 2 управляющий.

При старте системы Процесс 1 в начале цикла ожидает флаг, Процесс 2 устанавливает флаг тем самым разрешая опрос. После успешного опроса Процесс 1 выставляет сам для себя флаг, если опрос был не успешен то он отправляет месседж с ошибкой и не выставляет флаг. Тем самым Процесс 1 в случае ошибке уснет, пока Процесс 2 не решит, что с ним делать.

Интересовало насколько это корректно.

 

Насчет месседжей я спрашивал другое. Если я использую is_non_empty(), то при получении сообщения я не нашел места где флаг сбрасывается. А значит нужно вызывать сброс вручную?

 

А в случае с wait() как я понимаю флаг будет сброшен сам и вызове reset() нет необходимости? В документации не написано в каких ситуациях флаг сбрасывается. На этот вопрос уже нашел ответ. Флаг сбрасывается.

Изменено пользователем a9d

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Отсылать самому себе сигнал очень удобно в следующей ситуации.

Есть два процесса. Процесс 1 производит опрос, Процесс 2 управляющий.

При старте системы Процесс 1 в начале цикла ожидает флаг, Процесс 2 устанавливает флаг тем самым разрешая опрос. После успешного опроса Процесс 1 выставляет сам для себя флаг, если опрос был не успешен то он отправляет месседж с ошибкой и не выставляет флаг. Тем самым Процесс 1 в случае ошибке уснет, пока Процесс 2 не решит, что с ним делать.

Интересовало насколько это корректно.

Не очень понял, какой флаг имеется в виду. Флаг события (TEventFlag) или внутренняя переменная message NonEmpty? Лучше такие вещи пояснять на примере псевдокода.

 

Насчет месседжей я спрашивал другое. Если я использую is_non_empty(), то при получении сообщения я не нашел места где флаг сбрасывается. А значит нужно вызывать сброс вручную?

Получение сообщения производится в функции wait(). Там же и обрабатывается внутренняя переменная (NonEmpty). Эта переменная устанавливается при передаче только если в этот момент никто не ждёт сообщения (тогда при первой попытке встать на ожидание процесс "увидит", что сообщение уже лежит, и его можно использовать). Если же есть ожидающие процессы, то NonEmpty не устанавливается, т.к. в этом нет необходимости - просто процесс, который находился в ожидании, будет переведён в готовые к выполнению.

 

Следует иметь в виду, что внутренняя переменная NonEmpty - это не флаг-признак наличия сообщения. Это именно внутренняя переменная, используемая потрохами сервиса для своих служебных целей, поэтому ориентироваться на неё не следует. Работать нужно с интерфейсом - открытыми функциями-членами. Если приём сообщения осуществляется с помощью is_non_empty() (что правильнее назвать не приёмом, а проверкой наличия), то, конечно, и сброс состояния тоже придётся делать вручную.

 

А в случае с wait() как я понимаю флаг будет сброшен сам и вызове reset() нет необходимости? В документации не написано в каких ситуациях флаг сбрасывается. На этот вопрос уже нашел ответ. Флаг сбрасывается.

В документации описано функционирование с точки зрения интерфейса сервиса. А работа с NonEmpty - это уже детали реализации, они, конечно, как обычно, не являются предметом документирования. Детали реализации вообще могут меняться вполне произвольно, при сохранении интерфейса класса и логики его работы работы, поэтому ориентироваться на них не надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

OS::TEventFlag flg;
OS::message<char> err; 
....................
...................

Proc1              //управляющий
{ 

   flg.Signal();
   
   while(1)
   {
      err.wait();  //ждем сообщение об ошибке
      ............
      ............
   }
}


Proc2           //рабочий
{
     
    while(1)
    {
       flg.wait();
       
       if(Opros)
       {
          ..........
          flg.Signal();
          ..........
          Sleep(1);  
        }
        else
        {
          err=1;          //сообщаем номер ошибки
          err.send();    //отправляем месседж
                              //флаг не взведен и при следующем проходе процесс уснет
        }
                 
    }
}

 

Если требуется конечный автомат, то можно флаг заменить на месседж.

 

 

Теперь про месседжи.

У меня один процесс главный он через сообщения рассылает другим процессам команды. Процессы которые принимают команды не должны работать постоянно.

 

Это получается более корректно и правильно написать так

while(1)
{
    if(msg.wait(1)) 
    { 
       buf=msg; 
       .....................
    }
    
    ..........................
}

 

Чем так

 

while(1)
{
    if(msg.is_non_empty())
    { 
         buf=msg;
         msg.reset();
         ................
     }
   
   .................................
   Sleep(1);
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы сделал так.

OS::TEventFlag flg;
OS::message<char> err; 

Proc1              //управляющий
{ 

   flg.Signal();
   
   while(1)
   {
      err.wait();  //ждем сообщение об ошибке
      ............
      ............
   }
}


Proc2           //рабочий
{
    while(1)
    {
        flg.wait();
       
        while(1)
        {
            if(Opros)
            {
                ..........
                Sleep(1);  
            }
            else
            {
                err=1;        //сообщаем номер ошибки
                err.send();   //отправляем месседж
                break;
            }
        }
    }
}

 

 

Это получается более корректно и правильно написать так

while(1)
{
    if(msg.wait(1)) 
    { 
       buf=msg; 
       .....................
    }
    
    ..........................
}

Конечно. Это и есть штатный и основной способ использования. Ждём сообщения, дождались - обрабатываем. А is_non_empty(), reset() - это вспомогательные фукнции

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Proc2           //рабочий
{
    while(1)
    {
        flg.wait();
       
        while(1)
        {
            if(Opros)
            {
                ..........
                Sleep(1);  
            }
            else
            {
                err=1;        //сообщаем номер ошибки
                err.send();   //отправляем месседж
                break;
            }
        }
    }
}

 

Этот код получше. До такого я не додумался))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Через неделю планирую начать проект на STM32W

Под STM32 есть порт версии 3.10. А как обстоят дела с версией 4.0 ? Порт по идее есть, но он стабилен? Имеет смысл его использовать в проекте?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Через неделю планирую начать проект на STM32W

Под STM32 есть порт версии 3.10. А как обстоят дела с версией 4.0 ? Порт по идее есть, но он стабилен? Имеет смысл его использовать в проекте?

scmRTOS версии 4 и порт для Cortex-M3 (без разницы какой конкретно контроллер) под нее вполне стабильны.

Здесь можно скачать scmRTOS и порт версии 4.

Здесь и здесь документация.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

За доку на кортексы спасибо. О ее существовании даже не знал.

Изменено пользователем a9d

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заметил, что в 4 версии для cortex-m3 есть файлик startup.c. Хотя в тоже время имеется "\STM32\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm" тоже самое только на ассемблере.

Почему не используется ассемблерная версия?

 

Также в примерах содержаться файлы core_cm3.h и stm32f10x.h которые тоже содержаться STM32F10x_StdPeriph_Lib_V3.5.0.

Зачем их добавлять в примеры?

 

Настроил отладчик ST-Link (использую дисковери) как написано в статье http://we.easyelectronics.ru/STM32/otladka...eclipsegcc.html .

В проектах без ОС отладка работает.

А вот с ОС неработает. Зависает здесь

void Reset_Handler(void)
{
    __Init_Data();

    main();
}

 

или

 

void Default_Handler(void)
{
    for (;;);
}

 

Хотя проект рабочий и я вижу как плата мигает диодами.

Изменено пользователем a9d

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Заметил, что в 4 версии для cortex-m3 есть файлик startup.c. Хотя в тоже время имеется "\STM32\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm" тоже самое только на ассемблере.

Где "имеется"? :)

Дело в том, что в то время, когда создавался порт, в составе CMSIS не было ассемблерных стартапов. Да и нынешние - не будут работать с C++.

К тому же, версии библиотек от ST имеют нехорошую тенденцию меняться в самый неподходящий момент. Поэтому в состав примеров были включены нужные для работы примеров файлы. Обратите внимание, для собственно ОС эти файлы не нужны, порт - универсален для любых Cortex-M3.

 

Про отладку не подскажу, - не знаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну почему-же, будет работать. Там немного нужно поправить названия функций.

 

С вашей версией выходит

Invoking: ARM Sourcery Windows GNU Print Size
arm-none-eabi-size  --format=berkeley scmRTOS_stm32v3.elf
   text       data        bss        dec        hex    filename
   1872          4       1680       3556        de4    scmRTOS_stm32v3.elf
Finished building: scmRTOS_stm32v3.siz

 

с версией от STM

Invoking: ARM Sourcery Windows GNU Print Size
arm-none-eabi-size  --format=berkeley scmRTOS_stm32v3.elf
   text       data        bss        dec        hex    filename
   1912          4       1680       3596        e0c    scmRTOS_stm32v3.elf
Finished building: scmRTOS_stm32v3.siz

 

Но один фиг отладчик не работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Компилируется != работает:)

В том варианте startup_stm32f10x_xx.s, что есть у меня (V3.3.0), не вызываются конструкторы глобальных объектов. Хотя может сейчас уже поправили...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уже вышла версия 3.5.

 

Также нашел объяснение с отладкой

Brain13

Aug 12 2011, 08:23

StAlexy, у Вас в коде полная мешанина: разрешение прерывания SPI, инициализация TIM, разрешение прерывания TIM, инициализация SPI. Так делать нехорошо, когда проект вырастет сложно будет разобраться.

 

Если процессор зависает, но в обработчик не заходит, то скорее всего прерывание вызывается, но обработчика просто нет, поэтому он виснет в Default_Handler, которы по стандарту представляет из себя бесконечный цикл. Если у вас смесь С и С++. То необходимо добавить extern "C" при обьявлении обработчика, то есть:

Код

extern "C" void TIM2_IRQHandler(void);

Я на такое тоже натыкался, теперь все обработчики так описываю.

 

Посмотрите регистр статуса SPI, биты запроса прерывания выставлены? У Вас есть возможность узнать где зависла программа?

 

PS: уход от проблемы - не решение, разберитесь с прерываниями, без них - тяжко.

 

Сделал так но результата не дало.

#define OS_INTERRUPT extern "C"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Начал копаться в sysinit.cpp. Читабельность оставляет желать лучшего.

 

RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_HPRE | RCC_CFGR_PPRE2 | RCC_CFGR_PPRE1 | RCC_CFGR_ADCPRE)) |
            RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_ADCPRE_DIV6;

 

От таких конструкций мозг закипает. Такое намного проще и удобней разбить на несколько команд. При этом возрастет читабельность.

 

Также в этом файле нашел следующее

#if (!defined STM32F10X_LD_VL) && (!defined STM32F10X_MD_VL)
    // Enable Prefetch Buffer
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    // Flash 2 wait state (if freq in 24..48 MHz range - 1WS.)
    FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY) | FLASH_ACR_LATENCY_2;

#endif

 

Но в ACR есть всего один бит и эта конструкция его никак не трогает.

post-56532-1315857876_thumb.jpg

 

Также у value line потолок 24 Mhz. Отсюда вопрос. Что это такое?

Изменено пользователем a9d

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уже вышла версия 3.5.

И? Есть там вызов конструкторов?

#define OS_INTERRUPT extern "C"

Попробуйте просто написать extern "C" перед функцией обработчика прерывания.

От таких конструкций мозг закипает. Такое намного проще и удобней разбить на несколько команд. При этом возрастет читабельность.

Так разбейте, какие проблемы? Примеры - это же не догма, а лишь руководство к действию :)

Также в этом файле нашел следующее

#if (!defined STM32F10X_LD_VL) && (!defined STM32F10X_MD_VL)

...

Также у value line потолок 24 Mhz. Отсюда вопрос. Что это такое?

Видите первую строчку? Эта часть - не для value line.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...