|
|
  |
TEventFlag. порт под msp430, возвращаемое значение IsSignaled() |
|
|
|
May 20 2009, 07:55
|
Группа: Участник
Сообщений: 7
Регистрация: 20-05-09
Из: Харьков
Пользователь №: 49 299

|
Здравствуйте. Пробую использовать в проекте на 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 - функции. Как заставить компилятор генерить работоспособный код? Или что-то я не понимаю?
|
|
|
|
|
May 21 2009, 05:35
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(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, зачем его еще снаружи проверять?
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
May 21 2009, 06:40
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(dxp @ May 21 2009, 08:35)  ... проверка, что событие не "просигналено", выполняется внутри самой функции Wait, зачем его еще снаружи проверять? Тем более, что эти две отдельные операции не атомарны, т. е. после проверки сигнал снова может быть просигнален в другом процессе. Смысл этого (проверки на "не просигнален") может быть в том, чтобы в случае else делать какую-то другую работу, а не повисать в ожидании, но это не отменяет предыдущего утверждения.
|
|
|
|
|
May 21 2009, 06:52
|
Группа: Участник
Сообщений: 7
Регистрация: 20-05-09
Из: Харьков
Пользователь №: 49 299

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

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(Sergey Bold @ May 21 2009, 13:52)  В проекте несколко задач ожидают это событие. Если событие установить ещё до вызова OS:Run(), т.е когда задачи ещё ни разу не вызывались, то первая же задача сбросит в Wait() событие. А другие задачи никогда из Wait() не выйдут. Если бы событие не сбрасывалось "автоматом", то в моём случае, конечно, так не писал бы. Тогда, может, лучше просто сбросить флаг в самом первом процессе до старта? Просто принудительно. Ну, и на второй недостаток (неатомарность этой связки) указал IgorKossak. А тут могут лежать весьма неприятные (труднообнаруживаемые) грабли.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
May 21 2009, 07:28
|
Группа: Участник
Сообщений: 7
Регистрация: 20-05-09
Из: Харьков
Пользователь №: 49 299

|
Недостаток (неатомарность) в коде я понял. Это уже решаемые проблемы. Благо с компилятором всё разъяснилось. Спасибо dxp и IgorKossak за помощь.
|
|
|
|
|
May 21 2009, 09:59
|
Группа: Участник
Сообщений: 7
Регистрация: 20-05-09
Из: Харьков
Пользователь №: 49 299

|
Я согласен, что вызывать сервисы оси до OS:Run() не корректно. Хотя в тексте OS:Run() пока ничего не мешало мне установить событие до вызова OS:Run(), при следуюющем развитии оси что-то может измениться. Но, у меня 10 процессов, 5 из них ожидает событие сразу при запуске процесса, то все равно сперва будут выполняться самые приоритетные процессы. И установка события, например в первом процессе, в объекте-событии никак не будет отмечено, что процессы "такие-то" ждут его (они ведь ещё ни разу не вызывались). Проснуться только те процессы, которые до установки события успели вызвать Wait(). А другие когда вызовут Wait(), событие уже будет сброшено. А оно устанавливается всего один раз. Они будут "ждать" вечно.
Мне кажеться было бы удобно иметь 2 вида событий: со сбросом событий, и без сброса. Я бы тогда применил второе.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|