реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Задержка прерывания в uC/OS-II
Zhorick
сообщение Feb 28 2011, 16:22
Сообщение #1





Группа: Участник
Сообщений: 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();                             /*И ТОЛЬКО ТУТ РАЗРЕШАЕМ ПРЕРЫВАНИЯ*/
        }


Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Feb 28 2011, 16:46
Сообщение #2


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(Zhorick @ Feb 28 2011, 18:22) *
Судя по исходникам, очень широко используются длинные критические секции, в которых прерывания запрещены. Это может довольно сильно увеличить время реакции на прерывание.


Это не запрещение прерываний, а запрещение вытеснения.
Как будет сделано это запрещение зависит от конкретной адаптации RTOS на платформе.
Поэтому этот кусок кода ничего не говорит о латентности именно прерываний.

Кстати, не думаете сделать EDF под uCOS?
Go to the top of the page
 
+Quote Post
Zhorick
сообщение Feb 28 2011, 17:14
Сообщение #3





Группа: Участник
Сообщений: 11
Регистрация: 4-04-08
Пользователь №: 36 479



Да, критическая секция - это запрещение вытеснения.
Но для той платформы, для которой я смотрю (PowerPC), да и для многих других, я думаю, это именно запрет прерываний.
Получается, значительный вклад в задержку прерывания вносит как раз время работы с запрещенными прерываниями в критической секции.
Например, в eCos-е такие критические секции сведены к минимуму, как и положено. В высоконадежных ОСРВ (INTEGRITY, ThreadX) при оценке времени реакции на прерывание вообще учитывается время выполнения самой длинной инструкции процессора. А тут такое...
Интересно узнать, может, кто-нибудь делал замеры временных характеристик uCOS-а? Было бы интересно посмотреть. Может, есть какой-то стандартный тест от разработчика ОС (как, например, в eCos-е)?

Нет.. EDF пока для uCOS-а я делать не собираюсь, хотя планировщик в uCOS-е мне не особо понравился. Сразу видно, что изначально он создавался для 8-ми и 16-разрядных контроллеров. Для 32-разрядного процессора можно было бы сделать чего-нибудь получше.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Feb 28 2011, 18:50
Сообщение #4


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, вообще набор сервисов и как выполнен порт.
Go to the top of the page
 
+Quote Post
Zhorick
сообщение Mar 1 2011, 07:39
Сообщение #5





Группа: Участник
Сообщений: 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

Пока оставлю так, но возможно, придется поменять по-своему.
Go to the top of the page
 
+Quote Post
bek
сообщение Mar 2 2011, 10:31
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
VslavX
сообщение Mar 2 2011, 11:33
Сообщение #7


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

Go to the top of the page
 
+Quote Post
Zhorick
сообщение Mar 2 2011, 16:04
Сообщение #8





Группа: Участник
Сообщений: 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)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th April 2024 - 11:41
Рейтинг@Mail.ru


Страница сгенерированна за 0.01441 секунд с 7
ELECTRONIX ©2004-2016