Перейти к содержанию
    

Zhorick

Участник
  • Постов

    11
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный
  1. Вот есть пример сборки примеров для 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. В приложении - исходники и результаты тестов. src.tar.gz 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

    Да Вы зарегистрируйтесь и попробуйте скачать что получится =) Скачать можно ядро uCOS-II и BSP для некоторых процессоров и платформ. Бесплатно можно использовать для ознакомления/изучения и в образовательных целях, вроде еще в некоммерческих проектах. Для коммерческого использования придется лицензию покупать. Есть еще uCOS-III, но его скачивать пока не дают.
  5. Я, конечно, еще только начинаю с uCOS-ом работать, но, по-ходу, в этом случае заведомо планировщик никогда работать не будет, потоки переключаться ни будут: OSSchedLock инкрементирует переменную OSLockNesting. А теперь если посмотреть функцию OS_Sched(), то там сначала вызывается OS_ENTER_CRITICAL(), а потом проверяется OSLockNesting, и если она равна нулю, то выполняется планирование. То есть OSLockNesting нулю никогда равна не будет, и функция OS_Sched() просто завершит свою работу. Спасибо, надо будет так и сделать, быстрее работать будет. Только, может, для единообразия сделать обе функции или оба макроса. Хотя это и не принципиально. И вообще, в 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. Спасибо за ссылку. Надо будет эти тесты позапускать. И надо будет еще чего-нибудь погуглить на эту тему. А не подскажете, как Вы организовывали критические секции? Смотрел порт 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. Да, критическая секция - это запрещение вытеснения. Но для той платформы, для которой я смотрю (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, смотрю, как у них сделано. Может быть, посоветуете еще чего-нибудь?
×
×
  • Создать...