|
|
|
Задержка прерывания в uC/OS-II |
|
|
|
Feb 28 2011, 16:22
|
Группа: Участник
Сообщений: 11
Регистрация: 4-04-08
Пользователь №: 36 479
|
Здравствуйте. Никто не измерял задержку (латентность) прерываний в uCOS-е? По определению: Задержка прерывания = Максимальное время, которое прерывания запрещены + Время старта ISR Судя по исходникам, очень широко используются длинные критические секции, в которых прерывания запрещены. Это может довольно сильно увеличить время реакции на прерывание. Например, кусок кода из os_core.c: Код while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) { /* Go through all TCBs in TCB list */
OS_ENTER_CRITICAL(); /*ПРЕРЫВАНИЯ ЗАПРЕЩЕНЫ*/ if (ptcb->OSTCBDly != 0u) { /* No, Delayed or waiting for event with TO */ ptcb->OSTCBDly--; /* Decrement nbr of ticks to end of delay */ if (ptcb->OSTCBDly == 0u) { /* Check for timeout */
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_PEND_ANY; /* Yes, Clear status flag */ ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */ } else { ptcb->OSTCBStatPend = OS_STAT_PEND_OK; }
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */ OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */ OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; } } } ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */
OS_EXIT_CRITICAL(); /*И ТОЛЬКО ТУТ РАЗРЕШАЕМ ПРЕРЫВАНИЯ*/ }
|
|
|
|
|
Feb 28 2011, 16:46
|
Ally
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050
|
Цитата(Zhorick @ Feb 28 2011, 18:22) Судя по исходникам, очень широко используются длинные критические секции, в которых прерывания запрещены. Это может довольно сильно увеличить время реакции на прерывание. Это не запрещение прерываний, а запрещение вытеснения. Как будет сделано это запрещение зависит от конкретной адаптации RTOS на платформе. Поэтому этот кусок кода ничего не говорит о латентности именно прерываний. Кстати, не думаете сделать EDF под uCOS?
|
|
|
|
|
Feb 28 2011, 17:14
|
Группа: Участник
Сообщений: 11
Регистрация: 4-04-08
Пользователь №: 36 479
|
Да, критическая секция - это запрещение вытеснения. Но для той платформы, для которой я смотрю (PowerPC), да и для многих других, я думаю, это именно запрет прерываний. Получается, значительный вклад в задержку прерывания вносит как раз время работы с запрещенными прерываниями в критической секции. Например, в eCos-е такие критические секции сведены к минимуму, как и положено. В высоконадежных ОСРВ (INTEGRITY, ThreadX) при оценке времени реакции на прерывание вообще учитывается время выполнения самой длинной инструкции процессора. А тут такое... Интересно узнать, может, кто-нибудь делал замеры временных характеристик uCOS-а? Было бы интересно посмотреть. Может, есть какой-то стандартный тест от разработчика ОС (как, например, в eCos-е)?
Нет.. EDF пока для uCOS-а я делать не собираюсь, хотя планировщик в uCOS-е мне не особо понравился. Сразу видно, что изначально он создавался для 8-ми и 16-разрядных контроллеров. Для 32-разрядного процессора можно было бы сделать чего-нибудь получше.
|
|
|
|
|
Feb 28 2011, 18:50
|
Ally
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050
|
Цитата(Zhorick @ Feb 28 2011, 19:14) Но для той платформы, для которой я смотрю (PowerPC), да и для многих других, я думаю, это именно запрет прерываний.
Интересно узнать, может, кто-нибудь делал замеры временных характеристик uCOS-а? Было бы интересно посмотреть. Может, есть какой-то стандартный тест от разработчика ОС (как, например, в eCos-е)?
Для 32-разрядного процессора можно было бы сделать чего-нибудь получше. Я портировал uCOS на разные архитектуры: MSP430, M16, ST10, ARM7, ARM9 ... Везде находился способ не запрещать полностью прерывания в критических секциях. Как пример я всегда привожу вот эту разработку с использованием uCOS Система охраны на MSP430где при включенных сервисах оси проводилась выборка по прерываниям аудиосигналов и их же генерация с частотой сэмплирования 8 КГц. Если бы при этом был заметный джиттер в связи с запрещением прерываний, то разборчивые для внешних систем сигналы генерировать не удалось бы с таким сэмплированием. Программ для замеров RTOS конечно есть достаточно. Легко портируется во эта к примеру: http://rtos.com/downloads/articles_and_white_papers-1/ (искать под названием Thread-Metric Benchmark Suite) Еще раз скажу, что то как написано в ядре RTOS мало интересно, вся соль в порте. Поэтому хаять uCOS малопродуктивно. Важно как middleware работает с сервисами RTOS, вообще набор сервисов и как выполнен порт.
|
|
|
|
|
Mar 1 2011, 07:39
|
Группа: Участник
Сообщений: 11
Регистрация: 4-04-08
Пользователь №: 36 479
|
Спасибо за ссылку. Надо будет эти тесты позапускать. И надо будет еще чего-нибудь погуглить на эту тему. Цитата(AlexandrY @ Feb 28 2011, 21:50) Я портировал uCOS на разные архитектуры: MSP430, M16, ST10, ARM7, ARM9 ... Везде находился способ не запрещать полностью прерывания в критических секциях. А не подскажете, как Вы организовывали критические секции? Смотрел порт uCOS под PowerPC с их сайта micrium.com. Там сделано так: сначала сохраняется регистр MachineStateRegister, затем запрещаются прерывания...при выходе из критической секции MSR восстанавливается: Код #define OS_CRITICAL_METHOD 3
#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save(); #define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr);
OS_CPU_SR_Save:
addis 4, 0, 0xFFFD ori 4, 4, 0x7FFF mfmsr 3 and 4, 4, 3 /* Clear bits 14 and 16, corresponding to... */ mtmsr 4 /* ...critical and non-critical interrupts */ blr
OS_CPU_SR_Restore:
mtmsr 3 /* Restore the saved MSR */ blr Пока оставлю так, но возможно, придется поменять по-своему.
|
|
|
|
|
Mar 2 2011, 10:31
|
Участник
Группа: Участник
Сообщений: 21
Регистрация: 28-09-05
Пользователь №: 9 046
|
Интересно, что получится, если заменить конструкцию
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save(); \ OS_CPU_IntDisMeasStart();} #define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ OS_CPU_SR_Restore(cpu_sr);}
на
#define OS_ENTER_CRITICAL() {cpu_sr = OSSchedLock(); \ OS_CPU_IntDisMeasStart();} #define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ OSSchedUnlock(cpu_sr);}
забыл, конечно, в самих OSSchedLock и OSSchedUnlock заменить функции OS_ENTER_CRITICAL() и OS_EXIT_CRITICAL() непосредственно на их код
--------------------
он просто живет в мире, параллельном нашей скотской реальности, где главным мерилом исключительности является список Forbes
|
|
|
|
|
Mar 2 2011, 11:33
|
embarrassed systems engineer
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038
|
Цитата(Zhorick @ Mar 1 2011, 09:39) Смотрел порт uCOS под PowerPC с их сайта micrium.com. Там сделано так: сначала сохраняется регистр MachineStateRegister, затем запрещаются прерывания...при выходе из критической секции MSR восстанавливается: Вот Вам более быстрый инлайновый вариант (под GCC), делает то же самое CODE INLINE_FORCED DWORD tn_lock_interrupt(void) { DWORD ret, tmp;
asm volatile ( "mfmsr %0;" "rlwinm %1, %0, 0, 17, 15;" "mtmsr %1;" : "=r"(ret), "=r" (tmp) ); // // Дополнительная инструкция sync не нужна // если изменяются только флаги разрешения // прерываний // return ret; }
// // Восстановление состояния регистра MSR и флага прерываваний // #define tn_unlock_interrupt(sr) \ asm volatile \ ( \ "mtmsr %0;" \ : : "r"(sr) \ )
|
|
|
|
|
Mar 2 2011, 16:04
|
Группа: Участник
Сообщений: 11
Регистрация: 4-04-08
Пользователь №: 36 479
|
Цитата(bek @ Mar 2 2011, 13:31) Интересно, что получится, если заменить конструкцию
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save(); \ OS_CPU_IntDisMeasStart();} #define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ OS_CPU_SR_Restore(cpu_sr);}
на
#define OS_ENTER_CRITICAL() {cpu_sr = OSSchedLock(); \ OS_CPU_IntDisMeasStart();} #define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ OSSchedUnlock(cpu_sr);} Я, конечно, еще только начинаю с uCOS-ом работать, но, по-ходу, в этом случае заведомо планировщик никогда работать не будет, потоки переключаться ни будут: OSSchedLock инкрементирует переменную OSLockNesting. А теперь если посмотреть функцию OS_Sched(), то там сначала вызывается OS_ENTER_CRITICAL(), а потом проверяется OSLockNesting, и если она равна нулю, то выполняется планирование. То есть OSLockNesting нулю никогда равна не будет, и функция OS_Sched() просто завершит свою работу. Цитата(VslavX @ Mar 2 2011, 14:33) Вот Вам более быстрый инлайновый вариант (под GCC), делает то же самое Спасибо, надо будет так и сделать, быстрее работать будет. Только, может, для единообразия сделать обе функции или оба макроса. Хотя это и не принципиально. И вообще, в PowerPC через инструкции типа rlwin удобно очень с масками работать. Вот как, кстати, в том же eCos-е прерывания разрешаются/запрещаются: Код #define HAL_DISABLE_INTERRUPTS(_old_) \ CYG_MACRO_START \ cyg_uint32 tmp1, tmp2; \ asm volatile ( \ "mfmsr %0; \n \ mr %2,%0; \n \ li %1,0; \n \ rlwimi %2,%1,0,16,16; \n \ mtmsr %2; " \ : "=r"(_old_), "=r" (tmp1), "=r" (tmp2)); \ CYG_MACRO_END
#define HAL_ENABLE_INTERRUPTS() \ CYG_MACRO_START \ cyg_uint32 tmp1, tmp2; \ asm volatile ( \ "mfmsr %0; \n \ ori %1,%1,0x8000; \n \ rlwimi %0,%1,0,16,16; \n \ mtmsr %0;" \ : "=r" (tmp1), "=r" (tmp2)); \ CYG_MACRO_END где Код #define CYG_MACRO_START do { #define CYG_MACRO_END } while (0)
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|