Zhorick 0 28 февраля, 2011 Опубликовано 28 февраля, 2011 · Жалоба Здравствуйте. Никто не измерял задержку (латентность) прерываний в 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(); /*И ТОЛЬКО ТУТ РАЗРЕШАЕМ ПРЕРЫВАНИЯ*/ } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 28 февраля, 2011 Опубликовано 28 февраля, 2011 · Жалоба Судя по исходникам, очень широко используются длинные критические секции, в которых прерывания запрещены. Это может довольно сильно увеличить время реакции на прерывание. Это не запрещение прерываний, а запрещение вытеснения. Как будет сделано это запрещение зависит от конкретной адаптации RTOS на платформе. Поэтому этот кусок кода ничего не говорит о латентности именно прерываний. Кстати, не думаете сделать EDF под uCOS? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zhorick 0 28 февраля, 2011 Опубликовано 28 февраля, 2011 · Жалоба Да, критическая секция - это запрещение вытеснения. Но для той платформы, для которой я смотрю (PowerPC), да и для многих других, я думаю, это именно запрет прерываний. Получается, значительный вклад в задержку прерывания вносит как раз время работы с запрещенными прерываниями в критической секции. Например, в eCos-е такие критические секции сведены к минимуму, как и положено. В высоконадежных ОСРВ (INTEGRITY, ThreadX) при оценке времени реакции на прерывание вообще учитывается время выполнения самой длинной инструкции процессора. А тут такое... Интересно узнать, может, кто-нибудь делал замеры временных характеристик uCOS-а? Было бы интересно посмотреть. Может, есть какой-то стандартный тест от разработчика ОС (как, например, в eCos-е)? Нет.. EDF пока для uCOS-а я делать не собираюсь, хотя планировщик в uCOS-е мне не особо понравился. Сразу видно, что изначально он создавался для 8-ми и 16-разрядных контроллеров. Для 32-разрядного процессора можно было бы сделать чего-нибудь получше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 28 февраля, 2011 Опубликовано 28 февраля, 2011 · Жалоба Но для той платформы, для которой я смотрю (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, вообще набор сервисов и как выполнен порт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zhorick 0 1 марта, 2011 Опубликовано 1 марта, 2011 · Жалоба Спасибо за ссылку. Надо будет эти тесты позапускать. И надо будет еще чего-нибудь погуглить на эту тему. Я портировал 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 Пока оставлю так, но возможно, придется поменять по-своему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bek 0 2 марта, 2011 Опубликовано 2 марта, 2011 · Жалоба Интересно, что получится, если заменить конструкцию #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() непосредственно на их код Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 2 марта, 2011 Опубликовано 2 марта, 2011 · Жалоба Смотрел порт uCOS под PowerPC с их сайта micrium.com. Там сделано так: сначала сохраняется регистр MachineStateRegister, затем запрещаются прерывания...при выходе из критической секции MSR восстанавливается: Вот Вам более быстрый инлайновый вариант (под GCC), делает то же самое 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) \ ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Zhorick 0 2 марта, 2011 Опубликовано 2 марта, 2011 · Жалоба Интересно, что получится, если заменить конструкцию #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() просто завершит свою работу. Вот Вам более быстрый инлайновый вариант (под 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) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться