Jump to content

    

Zhorick

Участник
  • Content Count

    11
  • Joined

  • Last visited

Community Reputation

0 Обычный
  1. Цитата(forth@km.ru @ Jun 3 2011, 23:48) Поискав RTOS для i386 (в перспективе - переход на ARMы) остановился на eCos. Сейчас продираюсь через "Embedded Software Development with eCos", но оно как-то не tutorial явно, требует 3хпроходного чтения. Хотелось бы уже что-то пощщупать на железе (обычный PC, и PC104 платка на Zf86). Посмотрите plz у себя в ссылках -- не завалялась ли ссылка на какой-нибудь tutorial по сборке hello world для raw 386 ? Или можно сразу готовиться читать "eCos porting guide" ? Вот есть пример сборки примеров для eCos-а под ARM: http://www.kit-e.ru/articles/circuit/2000_07_70.php Только не знаю, поможет ли. Про портирование сразу читать не надо, для i386 же все есть...надо только с конфигурированием разобраться. А так рекомендую сначала для какого-нибудь симулятора собрать (все настройки конфигурирования по умолчанию). Я для симулятора PSIM (PowerPC) делал, на него есть портированный eCos. Еще можно под Synthetic Linux platform собрать. Собирается обычным компилятором gcc для i386, и в результате получается приложение eCos, которое можно как обычное приложение Linux запускать. Для начала можно стандартные тесты собрать и позапускать (Build/Tests в Configuration Tool).
  2. Добрый день! Недавно услышал про новую операционку - Embox: http://code.google.com/p/embox/wiki/ProjectDescription?tm=6 Разработка ведется силами кафедры системного программирования СПбГУ. Интересно узнать, кто-нибудь использовал ее в своих проектах?
  3. В продолжение темы... Написал тест, который показывает, чем планировщик EDF лучше приоритетных планировщиков. Вкратце алгоритм тестирования: Создается 3 потока, в которых в течении заданного времени производится какая-либо обработка (у меня - просто опрашивает системный таймер). После завершения обработки поток блокируется. Разблокировка потоков (по-сути, активация задачи; в реальной системе может выполняться в обработчике ISR внешнего прерывания) осуществляется в функции-обработчике сигнальных часов (Alarm). При инициализации указывается периодичность вызова функции (и, соответственно, активации задачи). Получается, что: поток 0 запускается с периодом 29 тиков и выполняется 16 тиков поток 1 запускается с периодом 38 тиков и выполняется 13 тиков поток 2 запускается с периодом 49 тиков и выполняется 5 тиков Коэффициент загрузки процессора = 16/29+13/38+5/49=0.995 В приложении - 2 примера: 1 случай - для ecos-а со статическим приоритетным планировщиком Bitmap Приоритеты потоков: 10, 20, 30. Чем меньше значение, тем выше приоритет (10 - самый приоритетный) 2 случай - для ecos-а с планировщиком EDF. Различия исходников минимально (в EDF вместо приоритета у потока задаются 3 параметра: время выполнения задачи, период появления и время, к которому задача должна быть обработана). В итоге получаем, что приоритетный планировщик с высокой загрузкой уже не справляется (не успевает обработать все потоки), тогда как EDF может обеспечивать практически 100% загрузку процессора. Если посмотреть выводы теста, то и количество переключений контекста при использовании EDF-планировщика меньше. Исходник теста с EDF. В приложении - исходники и результаты тестов. [attachment=54575:src.tar.gz] [attachment=54576:log.tar.gz] Код/* ************************************************************************* * Файл: edftest.c * Тест дедлайнов планировщика EDF * Коэффициент использования процессора = 16/29+13/38+5/49=0.995 * *************************************************************************/ #include <cyg/kernel/kapi.h> cyg_thread thread_obj[3];       char stack[3][2048];   cyg_handle_t simple_thread[3];          // массив дескрипторов потоков cyg_thread_entry_t entry0; cyg_handle_t    counter_hdl,                 sys_clk,                 alarm_hdl[3]; cyg_tick_count_t ticks; cyg_alarm_t alarm_handler; cyg_alarm   alarm_obj[3]; int in_process[3] = {1, 1, 1}; // Период появления задачи #define PERIOD0 29 #define PERIOD1 38 #define PERIOD2 49 cyg_tick_count_t periods[3] = { PERIOD0, PERIOD1, PERIOD2 }; // Время обработки задачи в худшем случае #define CTIME0 16 #define CTIME1 13 #define CTIME2 5 cyg_tick_count_t ctimes[3] = { CTIME0, CTIME1, CTIME2 }; // Параметры потоков для планировщика EDF // Формат: <Дедлайн> <Время выполнения> <Период> cyg_edf_sched_info_t edf_info[3] = {     { PERIOD0, CTIME0, PERIOD0 },     { PERIOD1, CTIME1, PERIOD1 },     { PERIOD2, CTIME2, PERIOD2 }, }; // --------------------------------------------------------------------- // externC void cyg_start(void) {     // Создаем потоки задач     cyg_thread_create((cyg_addrword_t)edf_info, entry0, (cyg_addrword_t) 0,             "Thread A", (void *) stack[0], 2048,             &simple_thread[0], &thread_obj[0]);        cyg_thread_create((cyg_addrword_t)(edf_info + 1), entry0, (cyg_addrword_t) 1,             "Thread B", (void *) stack[1], 2048,             &simple_thread[1], &thread_obj[1]);        cyg_thread_create((cyg_addrword_t)(edf_info + 2), entry0, (cyg_addrword_t) 2,             "Thread C", (void *) stack[2], 2048,             &simple_thread[2], &thread_obj[2]);         sys_clk = cyg_real_time_clock();   cyg_clock_to_counter (sys_clk, &counter_hdl);   cyg_alarm_create(counter_hdl, alarm_handler, 0, &alarm_hdl[0], &alarm_obj[0]);   cyg_alarm_create(counter_hdl, alarm_handler, 1, &alarm_hdl[1], &alarm_obj[1]);   cyg_alarm_create(counter_hdl, alarm_handler, 2, &alarm_hdl[2], &alarm_obj[2]);   // Задаем периоды для активации задач   cyg_alarm_initialize(alarm_hdl[0], cyg_current_time() + PERIOD0, PERIOD0);   cyg_alarm_initialize(alarm_hdl[1], cyg_current_time() + PERIOD1, PERIOD1);   cyg_alarm_initialize(alarm_hdl[2], cyg_current_time() + PERIOD2, PERIOD2);            // Переводим потоки в состояние готовности   cyg_thread_resume(simple_thread[0]);   cyg_thread_resume(simple_thread[1]);   cyg_thread_resume(simple_thread[2]);   in_process[0] = in_process[1] = in_process[2] = 1;   cyg_scheduler_start(); } // --------------------------------------------------------------------- // Точка входа в поток обработки // Для всех 3-х потоков используется одна функция // cyg_addrword_t data - номер потока void entry0(volatile cyg_addrword_t data) {     cyg_tick_count_t ticks;     int tnum;     while(1)     {         ticks = cyg_current_time();         tnum = (int)data;         diag_printf ("\n    Thread %d start at time %llu \n", tnum, ticks);         in_process[tnum] = 1;         while (cyg_current_time() < ticks + ctimes[tnum])         {             // Обработка в течение CTIMES тиков         }         diag_printf ("    Thread %d end at time %llu \n", tnum, cyg_current_time());         in_process[tnum] = 0;         // Блокируем поток         cyg_thread_suspend(simple_thread[tnum]);     } } // --------------------------------------------------------------------- // Функция активации задачи void alarm_handler (cyg_handle_t alarm_handle, cyg_addrword_t data) {     int tnum = (int)data;     diag_printf ("\nActivation of thread %d at time %llu \n", tnum, cyg_current_time());     if (in_process[tnum] == 1)              // Поток не обработан         diag_printf("\n\n!!! Thread %d DEADLINE \n", tnum);        // Устанавливаем новое время дедлайна     cyg_thread_set_edf_deadline(simple_thread[tnum], cyg_current_time() + periods[tnum]);     // Разблокируем поток     cyg_thread_resume (simple_thread[tnum]); } // end of edftest.c
  4. стоимость uC/OS-II

    Цитата(atel @ Feb 24 2010, 18:08) На их сайте был. Но не смог до конца понять, что есть из открытых исходников. В какой конфигурации uC/OS-II может быть получена бесплатно и в исходниках с целью предварительного ознакомления и освоения. Да Вы зарегистрируйтесь и попробуйте скачать что получится =) Скачать можно ядро uCOS-II и BSP для некоторых процессоров и платформ. Бесплатно можно использовать для ознакомления/изучения и в образовательных целях, вроде еще в некоммерческих проектах. Для коммерческого использования придется лицензию покупать. Есть еще uCOS-III, но его скачивать пока не дают.
  5. Задержка прерывания в uC/OS-II

    Цитата(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)
  6. Задержка прерывания в uC/OS-II

    Спасибо за ссылку. Надо будет эти тесты позапускать. И надо будет еще чего-нибудь погуглить на эту тему. Цитата(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 Пока оставлю так, но возможно, придется поменять по-своему.
  7. Задержка прерывания в uC/OS-II

    Да, критическая секция - это запрещение вытеснения. Но для той платформы, для которой я смотрю (PowerPC), да и для многих других, я думаю, это именно запрет прерываний. Получается, значительный вклад в задержку прерывания вносит как раз время работы с запрещенными прерываниями в критической секции. Например, в eCos-е такие критические секции сведены к минимуму, как и положено. В высоконадежных ОСРВ (INTEGRITY, ThreadX) при оценке времени реакции на прерывание вообще учитывается время выполнения самой длинной инструкции процессора. А тут такое... Интересно узнать, может, кто-нибудь делал замеры временных характеристик uCOS-а? Было бы интересно посмотреть. Может, есть какой-то стандартный тест от разработчика ОС (как, например, в eCos-е)? Нет.. EDF пока для uCOS-а я делать не собираюсь, хотя планировщик в uCOS-е мне не особо понравился. Сразу видно, что изначально он создавался для 8-ми и 16-разрядных контроллеров. Для 32-разрядного процессора можно было бы сделать чего-нибудь получше.
  8. Здравствуйте. Никто не измерял задержку (латентность) прерываний в 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();                             /*И ТОЛЬКО ТУТ РАЗРЕШАЕМ ПРЕРЫВАНИЯ*/         }
  9. Да, возможно, Вы правы. Но в то же время, мультимедийные системы тоже, по-сути, являются системами реального (пусть и мягкого) времени. Почему те же принципы нельзя применять для систем управления? Или там все приоритеты жестко заданы при проектировании? Можно ли динамическое планирование использовать в сетевых устройствах? И, раз зашел разговор..какие ОС лучше применять для мультимедийных систем? Почему не стоит использовать eCos? Если посмотреть на список проектов с eCos-ом: http://ecoscentric.com/ecos/examples.shtml то где его только не применяют.
  10. Здравствуйте еще раз! На этой неделе доделал первую версию EDF планировщика для eCos-а. Общая идея в том, что для хранения потоков у меня используется не в двусвязный список (или массив массив указателей), как в существущих планировщиках, а красно-черное дерево: http://ru.wikipedia.org/wiki/Красно-чёрное_дерево По-сути, это то же самое бинарное дерево, у которого длина всех ветвей равна (если говорить точнее, отличается не больше, чем на 1). Вычислительная сложность для всех операций с деревом - О(log n). Кстати, идея эта не новая. Красно-черные деревья уже используют в RTAI. Хотя, довольно спорный вопрос, стоит ли их применять во встраиваемых системах =). Потоки в дереве отсортированы по абсолютному времени крайнего срока завершения (дедлайна), и при планировании управление передается тому потоку, у которого это время наименьшее. Для этого пришлось в исходники eCos добавить классы Cyg_RBNode, Cyg_RBTree работы с деревьями (по аналогии с существующими Cyg_DNode и Cyg_CList), шаблонные классы, переписать несколько классов для планировщика из ядра eCos, и дополнить заголовочные файлы ядра. Сейчас разбираюсь со скриптами CDL, чтобы этот планировщик можно было выбрать и сконфигурировать в ConfigurationTool. Создание потока выглядит следующим образом: // ------------------------------------------------------------------------- cyg_thread thread_s; char stack[2048]; cyg_thread_entry_t entry0; cyg_handle_t thread_hdl; // Время задается в тиках системных часов RTC cyg_edf_sched_info_t edf_info = {40, /* относительное время дедлайна */ 10, /* время выполнения в худшем случае */ 100 /* период возникновения */ }; /* . . . */ cyg_thread_create((cyg_addrword_t)(edf_info), entry0, (cyg_addrword_t) 2, "Thread А", (void *) stack, 2048, thread_hdl, &thread_s); // ------------------------------------------------------------------------- Теперь возникла еще одна проблема... Изначально EDF (как и статические алгоритмы), создавался для планирования независимых задач. Как быть, если требуется организовать взаимодействие между потоками? Для статических алгоритмов разработана куча механизмов синхронизации: всякие мютексы, семафоры, очереди сообщений, флаги событий. Будут ли они работать для динамических алгоритмов? Конечно понимаю, что вопрос довольно теоретический и редко встречается на практике, в реальных проектах, но все же, может быть, кто-нибудь когда-нибудь с этим этим встречался? Буду очень признателен, если Вы мне поможете. Как реализовать, например, наследование приоритетов в динамическом планировщике? Если, по аналогии с приоритетом потока в статических планировщиках, изменять время дедлайна (по-сути, тот же приоритет), будет ли система планируемой (другими словами, успеет ли обработать все потоки)? Еще один вопрос. В системах реального времени часто требуется обрабатывать какие-либо периодические события (например, прерывания от внешних устройств, обработку пакетов данных и т.д.). При этом хорошо было бы теоретически доказать, что система является планируемой. Конечно, по этой теме написаны целые научные труды, есть формулы оценки планируемости (хотя бы сумма Ci/Ti из книжки Таненбаума). Используется ли что-то из этого на практике, или можно обойтись как-то попроще? Да..слишком много, наверное, я сейчас понаписал =) Пока еще начинаю работать в этой области, и достаточного опыта в системах реального времени у меня нет. Дело в том, что по этой теме я пишу диплом и хотелось бы сделать чего-то стоящее и полезное, что потом кому-то бы пригодилось.
  11. Здравствуйте! Думаю написать динамический планировщик типа EDF (Earliest Deadline First) для eCos. Задача в большей степени учебная, но все же хотелось бы избежать лишних ошибок и услышать мнения специалистов по eCos-у. На данный момент в eCos реализованы планировщики: - Bitmap (32 уровня приоритета, на каждом уровне может находиться только один поток); - многоуровневые очереди; - лотерейный планировщик. По-сути, все эти планировщики, если верить хотя бы этому: http://ipm.kstu.ru/os/lec/4.php не предназначены для планирования задач реального времени (в первую очередь периодических задач, для которых точно известны времена выполнения, дедлайнов и периоды возникновения). На базе этих планировщиков можно реализовать только статические алгоритмы планирования, в которых приоритеты потоков будут жестко задаваться на уровне компиляции. Динамическое планирование там невозможно. Попытки написать EDF в eCos уже были, причем довольно недавно..например, тут: http://sourceware.org/ml/ecos-discuss/2010-01/msg00017.html только ничего путного, как я понял, у них не получилось. Можно по 3-м направлениям работать: - писать планировщик на базе уже существующего в eCos, например, MLQ; - писать с нуля; - оставить существующий планировщик и создать какую-либо надстройку (по аналогии например, с тем же RTAI в Linux) для обслуживания задач РВ. Третий варинат мне нравится больше всего, ведь останется какая-никакая совместимость. Конкретные детали пока обдумываю, читаю про RTAI, Xenomai, KURT, смотрю, как у них сделано. Может быть, посоветуете еще чего-нибудь?