Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: TEventFlag. порт под msp430
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
Sergey Bold
Здравствуйте.

Пробую использовать в проекте на msp430 scmRTOS.
Возник вопрос.
Использую событие TEventFlag, проверяю установленно или нет, ну и далее там.

======== Пример ==============
Код
extern OS::TEventFlag g_SF_Initialization;

OS_PROCESS void TTaskZonesDetection::Exec()
{
//    ждем пока наш модуль не будет сконфигурирован
      if( !g_SF_Initialization.IsSignaled() )
    {
        g_SF_Initialization.Wait();
    }

============================

Функция g_SF_Initialization.IsSignaled() всегда возвращает "false", даже если событие установлено.
Немного проясняет листинг, сперва идёт сравнение, потом восстанавливается регистр SR, где флаги после сравнения.
Естественно флаги портятся, и команда JEQ выполняется как душе угодно.

======== Листинг ==============
Код
26          OS_PROCESS void TTaskZonesDetection::Exec()
   \   __code __task void OS::process<OS::pr4, (word)56U>::Exec()
   \                     ??Exec:
     27          {
   \   000000   2183         SUB.W   #0x2, SP
     28          //    ждем пока наш модуль не будет сконфигурирован
     29                if( !g_SF_Initialization.IsSignaled() )
   \   000002   81420000     MOV.W   SR, 0x0(SP)
   \   000006   32C2         DINT
   \   000008   0343         NOP
   \   00000A   D293....     CMP.B   #0x1, &g_SF_Initialization + 2
   \   00000E   2241         MOV.W   0x0(SP), SR
   \   000010   0524         JEQ     ??Exec_3
     30              {
     31                  g_SF_Initialization.Wait();
   \   000012   0E43         MOV.W   #0x0, R14
   \   000014   3C40....     MOV.W   #g_SF_Initialization, R12
   \   000018   B012....     CALL    #??Wait
     32              }

==========================================

IAR пробовал и 3.41 и 4.20.1 - ведут себя одинаково.
Только если выключить всю оптимизацию, в листинге будет правильно работающий код,
но тогда scmRTOS не работает, нужны inline - функции.
Как заставить компилятор генерить работоспособный код?
Или что-то я не понимаю?
dxp
Цитата(Sergey Bold @ May 20 2009, 14:55) *
Пробую использовать в проекте на msp430 scmRTOS.
Возник вопрос.
Использую событие TEventFlag, проверяю установленно или нет, ну и далее там.

[...]

IAR пробовал и 3.41 и 4.20.1 - ведут себя одинаково.
Только если выключить всю оптимизацию, в листинге будет правильно работающий код,
но тогда scmRTOS не работает, нужны inline - функции.
Как заставить компилятор генерить работоспособный код?
Или что-то я не понимаю?

Странно. У меня иной результат:

Код
OS_PROCESS void TProc1::Exec()
{
    for(;;)
    {   
        if(!ef.IsSignaled())
            ef.Wait();
    }     
}



Результат:

Код
</P><P>############################################################################
###
#                                                                             #
#                                                       21/May/2009  12:27:53 #
# IAR C/C++ Compiler V4.20.1.20017/W32, Evaluation edition for MSP430         #
# Copyright 1996-2008 IAR Systems AB.                                         #</P><P></P><P>
          OS_PROCESS void TProc1::Exec()
__code __cc_version2 __task void OS::process<OS::pr0, (word)200U>::Exec()
                  ??Exec_4:
          {
000000   2183         SUB.W   #0x2, SP
000002   063C         JMP     ??Exec_6
              for(;;)
              {
                  if(!ef.IsSignaled())
                  ??Exec_5:
000004   2241         MOV.W   @SP, SR
                      ef.Wait();
000006   0D43         MOV.W   #0x0, R13
000008   3C40....     MOV.W   #ef, R12
00000C   B012....     CALL    #??Wait
                  ??Exec_6:
000010   81420000     MOV.W   SR, 0(SP)
000014   32C2         DINT
000016   0343         NOP
000018   D293....     CMP.B   #0x1, &ef + 1
00001C   F323         JNE     ??Exec_5
00001E   2241         MOV.W   @SP, SR
000020   F73F         JMP     ??Exec_6
              }



И я не понял, зачам там такое использование. Ведь если посмотреть внутрь TEventFlag::Wait(), то можно увидеть:


Код
    TCritSect cs;

    if(Value)                                           // if flag already signaled
    {                                                  
        Value = efOff;                                  // clear flag
        return true;
    }
    else
    {


т.е. эта проверка, что событие не "просигналено", выполняется внутри самой функции Wait, зачем его еще снаружи проверять?
IgorKossak
Цитата(dxp @ May 21 2009, 08:35) *
... проверка, что событие не "просигналено", выполняется внутри самой функции Wait, зачем его еще снаружи проверять?

Тем более, что эти две отдельные операции не атомарны, т. е. после проверки сигнал снова может быть просигнален в другом процессе.
Смысл этого (проверки на "не просигнален") может быть в том, чтобы в случае else делать какую-то другую работу, а не повисать в ожидании, но это не отменяет предыдущего утверждения.
Sergey Bold
Спасибо dxp за ответ.
Проверил, точно я поторопился. Для IAR 4.20 листинг таки правильный.
Не правильный код получился только у IAR 3.41a, проект весь собирался на нём.
Прийдется переезжать на IAR 4.20.

Цитата
И я не понял, зачам там такое использование. Ведь если посмотреть внутрь TEventFlag::Wait(), то можно увидеть:


Код
    TCritSect cs;

    if(Value)                                           // if flag already signaled
    {                                                  
       Value = efOff;                                  // clear flag
       return true;
    }
    else
    {


т.е. эта проверка, что событие не "просигналено", выполняется внутри самой функции Wait, зачем его еще снаружи проверять?


В проекте несколко задач ожидают это событие. Если событие установить ещё до вызова OS:Run(), т.е когда задачи ещё ни разу не вызывались, то первая же задача сбросит в Wait() событие. А другие задачи никогда из Wait() не выйдут. Если бы событие не сбрасывалось "автоматом", то в моём случае, конечно, так не писал бы.
dxp
Цитата(Sergey Bold @ May 21 2009, 13:52) *
В проекте несколко задач ожидают это событие. Если событие установить ещё до вызова OS:Run(), т.е когда задачи ещё ни разу не вызывались, то первая же задача сбросит в Wait() событие. А другие задачи никогда из Wait() не выйдут. Если бы событие не сбрасывалось "автоматом", то в моём случае, конечно, так не писал бы.


Тогда, может, лучше просто сбросить флаг в самом первом процессе до старта? Просто принудительно. Ну, и на второй недостаток (неатомарность этой связки) указал IgorKossak. А тут могут лежать весьма неприятные (труднообнаруживаемые) грабли.
Sergey Bold
Недостаток (неатомарность) в коде я понял. Это уже решаемые проблемы.
Благо с компилятором всё разъяснилось.
Спасибо dxp и IgorKossak за помощь.
IgorKossak
На мой взгляд тут есть ещё один чреватый багами нюанс. Это вызывать сервисы ОС до запуска OS::Run().
Sergey Bold
Я согласен, что вызывать сервисы оси до OS:Run() не корректно.
Хотя в тексте OS:Run() пока ничего не мешало мне установить событие до вызова OS:Run(),
при следуюющем развитии оси что-то может измениться.
Но,
у меня 10 процессов, 5 из них ожидает событие сразу при запуске процесса, то все равно сперва будут выполняться самые приоритетные процессы. И установка события, например в первом процессе, в объекте-событии никак не будет отмечено, что процессы "такие-то" ждут его (они ведь ещё ни разу не вызывались). Проснуться только те процессы, которые до установки события успели вызвать Wait().
А другие когда вызовут Wait(), событие уже будет сброшено. А оно устанавливается всего один раз.
Они будут "ждать" вечно.

Мне кажеться было бы удобно иметь 2 вида событий: со сбросом событий, и без сброса.
Я бы тогда применил второе.
dxp
Цитата(Sergey Bold @ May 21 2009, 16:59) *
Мне кажеться было бы удобно иметь 2 вида событий: со сбросом событий, и без сброса.
Я бы тогда применил второе.

Можно создать объект флага с установленными значениями карты ожидающих процессов. Посмотрите на определение конструктора - там можно передать аргумент. Этот аргумент соответствует карте процессов, находящихся в в ожидании. Попробуйте этот способ, возможно все остальные "пляски" и не понадобятся. 
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.