boldsa 0 20 мая, 2009 Опубликовано 20 мая, 2009 · Жалоба Здравствуйте. Пробую использовать в проекте на 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 34 21 мая, 2009 Опубликовано 21 мая, 2009 · Жалоба Пробую использовать в проекте на 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 0 21 мая, 2009 Опубликовано 21 мая, 2009 · Жалоба ... проверка, что событие не "просигналено", выполняется внутри самой функции Wait, зачем его еще снаружи проверять? Тем более, что эти две отдельные операции не атомарны, т. е. после проверки сигнал снова может быть просигнален в другом процессе. Смысл этого (проверки на "не просигнален") может быть в том, чтобы в случае else делать какую-то другую работу, а не повисать в ожидании, но это не отменяет предыдущего утверждения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
boldsa 0 21 мая, 2009 Опубликовано 21 мая, 2009 · Жалоба Спасибо 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 34 21 мая, 2009 Опубликовано 21 мая, 2009 · Жалоба В проекте несколко задач ожидают это событие. Если событие установить ещё до вызова OS:Run(), т.е когда задачи ещё ни разу не вызывались, то первая же задача сбросит в Wait() событие. А другие задачи никогда из Wait() не выйдут. Если бы событие не сбрасывалось "автоматом", то в моём случае, конечно, так не писал бы. Тогда, может, лучше просто сбросить флаг в самом первом процессе до старта? Просто принудительно. Ну, и на второй недостаток (неатомарность этой связки) указал IgorKossak. А тут могут лежать весьма неприятные (труднообнаруживаемые) грабли. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
boldsa 0 21 мая, 2009 Опубликовано 21 мая, 2009 · Жалоба Недостаток (неатомарность) в коде я понял. Это уже решаемые проблемы. Благо с компилятором всё разъяснилось. Спасибо dxp и IgorKossak за помощь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 21 мая, 2009 Опубликовано 21 мая, 2009 · Жалоба На мой взгляд тут есть ещё один чреватый багами нюанс. Это вызывать сервисы ОС до запуска OS::Run(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
boldsa 0 21 мая, 2009 Опубликовано 21 мая, 2009 · Жалоба Я согласен, что вызывать сервисы оси до OS:Run() не корректно. Хотя в тексте OS:Run() пока ничего не мешало мне установить событие до вызова OS:Run(), при следуюющем развитии оси что-то может измениться. Но, у меня 10 процессов, 5 из них ожидает событие сразу при запуске процесса, то все равно сперва будут выполняться самые приоритетные процессы. И установка события, например в первом процессе, в объекте-событии никак не будет отмечено, что процессы "такие-то" ждут его (они ведь ещё ни разу не вызывались). Проснуться только те процессы, которые до установки события успели вызвать Wait(). А другие когда вызовут Wait(), событие уже будет сброшено. А оно устанавливается всего один раз. Они будут "ждать" вечно. Мне кажеться было бы удобно иметь 2 вида событий: со сбросом событий, и без сброса. Я бы тогда применил второе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 34 21 мая, 2009 Опубликовано 21 мая, 2009 · Жалоба Мне кажеться было бы удобно иметь 2 вида событий: со сбросом событий, и без сброса. Я бы тогда применил второе. Можно создать объект флага с установленными значениями карты ожидающих процессов. Посмотрите на определение конструктора - там можно передать аргумент. Этот аргумент соответствует карте процессов, находящихся в в ожидании. Попробуйте этот способ, возможно все остальные "пляски" и не понадобятся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться