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

TEventFlag. порт под msp430

Здравствуйте.

 

Пробую использовать в проекте на 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 - функции.

Как заставить компилятор генерить работоспособный код?

Или что-то я не понимаю?

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


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

Пробую использовать в проекте на 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, зачем его еще снаружи проверять?

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


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

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

Тем более, что эти две отдельные операции не атомарны, т. е. после проверки сигнал снова может быть просигнален в другом процессе.

Смысл этого (проверки на "не просигнален") может быть в том, чтобы в случае else делать какую-то другую работу, а не повисать в ожидании, но это не отменяет предыдущего утверждения.

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


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

Спасибо 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() не выйдут. Если бы событие не сбрасывалось "автоматом", то в моём случае, конечно, так не писал бы.

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


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

В проекте несколко задач ожидают это событие. Если событие установить ещё до вызова OS:Run(), т.е когда задачи ещё ни разу не вызывались, то первая же задача сбросит в Wait() событие. А другие задачи никогда из Wait() не выйдут. Если бы событие не сбрасывалось "автоматом", то в моём случае, конечно, так не писал бы.

 

Тогда, может, лучше просто сбросить флаг в самом первом процессе до старта? Просто принудительно. Ну, и на второй недостаток (неатомарность этой связки) указал IgorKossak. А тут могут лежать весьма неприятные (труднообнаруживаемые) грабли.

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


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

Недостаток (неатомарность) в коде я понял. Это уже решаемые проблемы.

Благо с компилятором всё разъяснилось.

Спасибо dxp и IgorKossak за помощь.

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


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

На мой взгляд тут есть ещё один чреватый багами нюанс. Это вызывать сервисы ОС до запуска OS::Run().

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


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

Я согласен, что вызывать сервисы оси до OS:Run() не корректно.

Хотя в тексте OS:Run() пока ничего не мешало мне установить событие до вызова OS:Run(),

при следуюющем развитии оси что-то может измениться.

Но,

у меня 10 процессов, 5 из них ожидает событие сразу при запуске процесса, то все равно сперва будут выполняться самые приоритетные процессы. И установка события, например в первом процессе, в объекте-событии никак не будет отмечено, что процессы "такие-то" ждут его (они ведь ещё ни разу не вызывались). Проснуться только те процессы, которые до установки события успели вызвать Wait().

А другие когда вызовут Wait(), событие уже будет сброшено. А оно устанавливается всего один раз.

Они будут "ждать" вечно.

 

Мне кажеться было бы удобно иметь 2 вида событий: со сбросом событий, и без сброса.

Я бы тогда применил второе.

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


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

Мне кажеться было бы удобно иметь 2 вида событий: со сбросом событий, и без сброса.

Я бы тогда применил второе.

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

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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