megajohn 3 25 июля, 2012 Опубликовано 25 июля, 2012 · Жалоба собтсвенно сабж. Интересует правильная реализация. Кстати, сообщество не созрело создать подфорум по этой RTOS ?! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 25 июля, 2012 Опубликовано 25 июля, 2012 · Жалоба собтсвенно сабж. Интересует правильная реализация. Что именно понимается под critical sections? tn_disable_interrupt() и tn_enable_interrupt() недостаточно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 25 июля, 2012 Опубликовано 25 июля, 2012 · Жалоба Что именно понимается под critical sections? tn_disable_interrupt() и tn_enable_interrupt() недостаточно? Странная секция какая-то: если она вложенная, то как тогда? Правильней так (пример от IAR-а) oldState = __save_interrupt(); __disable_interrupt(); /* Critical section goes here */ __restore_interrupt(oldState); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 25 июля, 2012 Опубликовано 25 июля, 2012 · Жалоба Правильней так (пример от IAR-а) Ну насколько я знаю - в оригинальном порте TNKernel так и сделано, только переменная OldState спрятана внутри макроса. В своей модификации RTOSе я использую идеологию IAR-овского примера - с явным сохранением состояния. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 26 июля, 2012 Опубликовано 26 июля, 2012 · Жалоба TN_INTSAVE_DATA tn_disable_interrupt(); ... { // Вложенная TN_INTSAVE_DATA tn_disable_interrupt(); ... tn_enable_interrupt(); } ... tn_enable_interrupt(); Всё потому что #define TN_INTSAVE_DATA_INT unsigned int tn_save_status_reg = 0; #define TN_INTSAVE_DATA unsigned int tn_save_status_reg = 0; #define tn_disable_interrupt() tn_save_status_reg = tn_cpu_save_sr() #define tn_enable_interrupt() tn_cpu_restore_sr(tn_save_status_reg) #define tn_idisable_interrupt() tn_save_status_reg = tn_icpu_save_sr() #define tn_ienable_interrupt() tn_icpu_restore_sr(tn_save_status_reg) tn_cpu_save_sr() - запрещает прерывания и возвращает статус разрешения прерываний до запрещения tn_cpu_restore_sr() - разрешает прерывания если параметр != 0 и запрещает, если == 0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 3 26 июля, 2012 Опубликовано 26 июля, 2012 · Жалоба чой та не понимаю. Зачем отключать вообще прерывания ? Нужно всего лишь дать знать шедуллеру чтобы покамест не переключал задачи. А блокировать ВСЕ - это уже блокировка и на уровне драйверов, которые входящие данные складывают в циклический буфер. или мои представления о РТОС ошибочны ?! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 26 июля, 2012 Опубликовано 26 июля, 2012 · Жалоба чой та не понимаю. Зачем отключать вообще прерывания ? Нужно всего лишь дать знать шедуллеру чтобы покамест не переключал задачи. А блокировать ВСЕ - это уже блокировка и на уровне драйверов, которые входящие данные складывают в циклический буфер. или мои представления о РТОС ошибочны ?! Так как переключение контекста происходит в прерывании с наименьшим возможным приоритетом (PendSV с приоритетом 0xFF), то можно не запрещать прерывания, а поднять нижнюю границу обслуживаемых прерываний. Тем самым оставив прерывания включёнными, но запретив переключение контекста. Как это делается для Cortex-M3, увы не скажу. Будет что-то типа: int tn_disable_context_switch(void) { int state = get_priority_level(); if (state == 0xFF) // all interrupt are accepted { set_priority_level(0xFF - 1); // accept all, except PendSV } // else - do nothing, since PendSV is not acceptable already return state; } void tn_enable_context_switch(int state) { set_priority_level(state); } На счёт представлений ничего не скажу :( Сам бы хотел получить ответ на этот вопрос. По крайней мере внутри системных вызовов ОСи используется именно запрещение прерываний, для исключения проблем с реентерабельностью, судя по всему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 26 июля, 2012 Опубликовано 26 июля, 2012 · Жалоба По крайней мере внутри системных вызовов ОСи используется именно запрещение прерываний, для исключения проблем с реентерабельностью, судя по всему. А реентерабельность тут причём? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 26 июля, 2012 Опубликовано 26 июля, 2012 · Жалоба А реентерабельность тут причём? Реентерабельность системных вызовов конечно. Ведь они могут вызываться как из задач, так и из прерываний, и работа в них ведётся с одними и теми же внутренними структурами ОС. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 26 июля, 2012 Опубликовано 26 июля, 2012 · Жалоба Так как переключение контекста происходит в прерывании с наименьшим возможным приоритетом (PendSV с приоритетом 0xFF), то можно не запрещать прерывания, а поднять нижнюю границу обслуживаемых прерываний. Дело в том что часто критическая секция именно организуется для защиты данных разделяемых с обработчиком прерываний - тут только запрет прерываний и поможет. Если данные в критической секции разделяются только между задачами - то лучше уже использовать синхрообъекты RTOS - мутексы, семафоры или события. Еще, иногда, если код в критической секции очень быстрый и короткий, то из соображений быстродействия вполне можно критическую секцию организовать на tn_interrupt_xxxx(). Пример (не самый удачный для Cortex с его ldrex/strex): HAL_SYSTEM_CALL DWORD HAL_CALL_OPTION hal_interlocked_inc( PDWORD var) { DWORD lock, ret; lock = hal_lock_interrupt(); ret = *var + 1; *var = ret; hal_unlock_interrupt(lock); return ret; } Запрет переключения между задачами тоже можно реализовать независимо от порта - через tn_task_change_priority() (банально задрать приритет до максимального в системе), но оверхед обычно больше чем на мутексе, например. Не говоря уже о interrupt_xxxx(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться