Jump to content

    
Sign in to follow this  
Zhorick

Задержка прерывания в uC/OS-II

Recommended Posts

Здравствуйте.

Никто не измерял задержку (латентность) прерываний в 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();                             /*И ТОЛЬКО ТУТ РАЗРЕШАЕМ ПРЕРЫВАНИЯ*/
        }

 

 

Share this post


Link to post
Share on other sites
Судя по исходникам, очень широко используются длинные критические секции, в которых прерывания запрещены. Это может довольно сильно увеличить время реакции на прерывание.

 

Это не запрещение прерываний, а запрещение вытеснения.

Как будет сделано это запрещение зависит от конкретной адаптации RTOS на платформе.

Поэтому этот кусок кода ничего не говорит о латентности именно прерываний.

 

Кстати, не думаете сделать EDF под uCOS?

Share this post


Link to post
Share on other sites

Да, критическая секция - это запрещение вытеснения.

Но для той платформы, для которой я смотрю (PowerPC), да и для многих других, я думаю, это именно запрет прерываний.

Получается, значительный вклад в задержку прерывания вносит как раз время работы с запрещенными прерываниями в критической секции.

Например, в eCos-е такие критические секции сведены к минимуму, как и положено. В высоконадежных ОСРВ (INTEGRITY, ThreadX) при оценке времени реакции на прерывание вообще учитывается время выполнения самой длинной инструкции процессора. А тут такое...

Интересно узнать, может, кто-нибудь делал замеры временных характеристик uCOS-а? Было бы интересно посмотреть. Может, есть какой-то стандартный тест от разработчика ОС (как, например, в eCos-е)?

 

Нет.. EDF пока для uCOS-а я делать не собираюсь, хотя планировщик в uCOS-е мне не особо понравился. Сразу видно, что изначально он создавался для 8-ми и 16-разрядных контроллеров. Для 32-разрядного процессора можно было бы сделать чего-нибудь получше.

 

Share this post


Link to post
Share on other sites
Но для той платформы, для которой я смотрю (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, вообще набор сервисов и как выполнен порт.

Share this post


Link to post
Share on other sites

Спасибо за ссылку. Надо будет эти тесты позапускать. И надо будет еще чего-нибудь погуглить на эту тему.

 

Я портировал 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

Пока оставлю так, но возможно, придется поменять по-своему.

Share this post


Link to post
Share on other sites

Интересно, что получится, если заменить конструкцию

 

#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() непосредственно на их код

Share this post


Link to post
Share on other sites
Смотрел порт 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)						\
)

 

Share this post


Link to post
Share on other sites
Интересно, что получится, если заменить конструкцию

 

#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)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this