Available Languages?:

Порт TNKernel для PIC24/dsPIC и PIC32

Скачать

Актуальная версия

  • 2.5.908 (16 февраля 2011) скачать @ 550 кБ
    • Исправлена ошибка в порте Cortex-M3, которая приводила к некорректной работе программы при вызове сервисов tn_sys_time_get() и tn_sys_time_set(). Спасибо Дмитрию Кривецкову.



Предыдущие версии

  • 2.5.716 (17 сентября 2010) скачать @ 550 кБ
    • Добавлен порт для ARM Cortex-M3 (для компилятора Keil RealView)
    • Найдены и исправлены ошибка во внутренних функциях try_lock_mutex() и do_unlock_mutex(). При использовании мютексов с протоколом увеличения приоритетов мог возникнуть exception (взятие значения по нулевому адресу). Спасибо Vanizma
    • Найдена и исправлена ошибка в порте для PIC32 (смена контекста не защищалась критической секцией). Спасибо Ивану Федотову.
    • Все определения, зависящие от архитектуры, под которую производится сборка, перенесены в файлы port_defs.h каждой архитектуры.
    • Переделана структура примера. В пример добавлена задача, использующая UART (работает на Explorer16 как для PIC24, так и для PIC32). Задача принимает 10 байт (с таймаутом 2 мс на скорости 19200 бит/с) и пересылает их обратно. Для разных архитектур используются разные файлы bsp.c

Настоятельно рекомендую обновиться



  • 2.5.601 (14 июля 2010) скачать @ 400 кБ
    • Добавлен порт TNKernel для PIC32
      • Рекомендую почитать список отличий и пройтись поиском по этой странице. Искать PIC32
    • Множество платформозависимых ассемблерных файлов сведено в один port.S
    • Переработан пример. Теперь его можно запускать в железе (Explorer 16 + PIC24FJ256GB110 или PIC32MX360F512L) и смотреть как моргают светодиоды, нажимать на кнопку, крутить потенциометр
    • Конфигурация сборки (TN_DEBUG) определяется во внешнем файле tnkernel_conf.h - см. пункт "11. Файл конфигурации"
    • Для всех функций без проверки параметров добавлена проверка, создан объект или нет. В противном случае можно нарваться на неприятные проблемы, типа отсылки сообщения через очередь, которая еще не создана. Это очень важный фикс, рекомендую обновиться.



  • 2.5.455 (07 апреля 2010) скачать @ 530 кБ
    • Исправлена ошибка в функции tn_task_exit(). Неладное заметил и настойчиво просил разобраться Daniil, за что ему большое спасибо.
      • Ошибка тянется еще издавна, когда были попытки использовать все приоритеты для реализации системных прерываний. Ошибка проявляла себя только в случае, если после вызова tn_task_exit() возникало системное прерывание, которое переключало контекст. Так как сервис tn_task_exit() вообще не очень популярный, то баг был замечен только сейчас


  • 2.5.298 (15 января 2010) скачать @ 530 кБ
    • Исправлена ошибка в функциях tn_sys_time_get() и tn_sys_time_set(). Проблему нашел vitalka, локализовал tester - гран мерси!
      • Использование этих функций разрешено как в задачах, так и в системных прерываниях. Однако функции запрещали и сбрасывали флаг приоритета ядра, не проверяя, в каком контексте находятся. При использовании этих функций в системном прерывании, приоритет ядра сбрасывался на 0


  • 2.5.182 (15 ноября 2009) скачать @ 530 кБ
    • Исправлена ошибка в макросе MAKE_ALIG(), который используется для выделения пула блоков памяти фиксированного размера. Спасибо vitalka!


  • 2.5.62 (24 июня 2009) скачать @ 530 кБ
    • Тип параметра, передаваемый в функции tn_task_reference() и tn_task_ireference() изменен с TN_TCB_S на TN_TCB
      • компилятор выдавал предупреждение о несоответствии типов. Спасибо Vanizma


  • 2.5.28 (23 апреля 2009) скачать @ 530 кБ
    • Исправлена ошибка в механизме карусельного (round-robin) планирования (обнаружил VXDRV, спасибо)
      • Карусельное планирование позволяет выделять задачам с фиксированным приоритетом временные кванты, длительность которых задается с помощью функции tn_sys_tslice_ticks(). Ошибка в системной функции tn_tick_int_processing() увеличивала этот интервал на один системный тик


  • 2.5.10 (8 декабря 2008) скачать @ 532 кБ
    • Обновлено до официальной версии 2.5
      • Исправлена ошибка в задаче системного таймера tn_timer_task_func()
        • В предыдущих версиях была следующая ошибка - если в момент выполнения задачи таймера tn_timer_task_func() возникало системное прерывание, в котором разблокировалась одна из задач (устанавливался ожидаемый семафор, и т.п.), то при выходе их этого прерывания запускалась разблокированная задача. Таким образом, в определенных ситуациях, было возможно непроизвольное увеличение таймаутов ожидающих событие задач
      • Исправлена ошибка в функции task_wait_complete()
        • Ошибка в обработке задач, использующих ceiling мютекс
    • Добавлено определение __TNKERNEL_VERSION
      • В связи с переездом на новый SVN хостинг номера ревизий будут меньше чем у предыдущих версий. Введено определение __TNKERNEL_VERSION, которое будет обозначать номер текущей версии (2.5)


  • 2.4.1037 (25 июня 2008) скачать @ 530 кБ
    • исправлена ошибка в порте для dsPIC (нашел Vlad, спасибо)
      • код с библиотекой просто не собирался


  • 2.4.1034 (20 июня 2008) скачать @ 494 кБ
    • добавлены сервисы получения информации о задаче tn_task_reference() и tn_task_ireference()
    • добавлен сервис получения текущего контекста системы tn_sys_context_get()
      • можно использовать в функциях, которые вызываются как из задач, так и из обработчиков прерываний и при этом используют системные сервисы
    • введен тип TN_TIMEOUT для параметров сервисов с таймаутами


  • 2.4.1000 (17 апреля 2008) скачать @ 458 кБ
    • изменен способ проверки контекста в сервисах
      • увеличена скорость выполнения системных сервисов в среднем на 15%
    • добавлен системный таймер и функции tn_sys_time_get() и tn_sys_time_set()
    • изменен способ нумерации версий
    • изменена структура исходников
      • начиная с этой версии для использования TNKernel достаточно подключить к проекту библиотеку xxx.lib и включить в модули, использующие сервисы RTOS файл tnkernel.h. Файл tnkernel_rev.h должен находиться в одной папке с tnkernel.h, другие заголовочные файлы не требуются


  • 2.4.977 (8 апреля 2008) скачать @ 550 кБ
    • добавлен код возврата TNERR_EXS - все сервисы создания объектов возвращают этот код, если объект уже создан
    • добавлен файл tnkernel_rev.h, в котором объявлена текущая ревизия и дата сборки библиотеки


  • 2.4.780 (6 января 2008) скачать @ 545 кБ
    • исправлена ошибка возникающая в режиме модульной и битреверсивной адресации в dsPIC (спасибо qas)
      • Если во время выполнения библиотечной функции, которая использует модульную или битреверсивную адресацию возникает системное прерывание, регистры MODCON и XBREV не сохраняются и не обнуляются. При этом косвенная адресация по прежнему подчиняется правилам модульной или битреверсивной адресации, что однозначно приведет к краху системы.
        В ревизии 780 введены два target-а - PIC24 и dsPIC. Для dsPIC в стеке задачи сохраняются регистры MODCON и XBREV. Соответственно изменены файлы сборки библиотеки. В архиве четыре варианта - PIC24 coff/elf и dsPIC coff/elf с оптимизацией Os. В проект нужно просто подключить соответствующую библиотеку.
        Тем не менее, ядро DSP до сих пор является разделяемым ресурсом и при его использовании нужно применять мютекс.
    • изменен способ проверки контекста в сервисах
      • увеличена скорость выполнения системных сервисов на 10-15%
    • исправлена ошибка проверки контекста в функции tn_task_exit()



Thread-Metric Test Suite

  • Thread-Metric Test Suite TNKernel для PIC24/dsPIC (17 апреля 2008) скачать @ 130 кБ

Документация

  • Оригинальная документация TNKernel 2.4 (скачать @ 390 кБ)

Почему TNKernel?

TNKernel (http://www.tnkernel.com) - вытесняющая RTOS, изначально разработанная для микроконтроллеров с ядром ARM7, имеющая ряд достоинств по сравнению с аналогичными некоммерческими и коммерческими продуктами. TNKernel распространяется по FreeBSD-like лицензии и написана в основном на языке Си, что сделало возможным ее портирование как на 16-битную архитектуру Microchip PIC24/dsPIC (для компилятора Microchip C30) так и на 32-битные PIC32 (архитектура MIPS32 M4K, компилятор Microchip C32)

При выборе RTOS для применения в проектах с PIC24/dsPIC рассматривались различные варианты: uC/OS-II, как наиболее распространенная коммерческая RTOS для однокристалльных контроллеров, freeRTOS - широко известная и бесплатная RTOS. Рассматривались варианты портирования ThreadX (оригинального порта тогда еще не было) и других платных и бесплатных "легких" планировщиков. Операционные системы с кооперативным планировщиком (Salvo, jacOS) были откинуты сразу, так как даже первые линейки PIC24/dsPIC имели достаточный объем оперативной памяти для реализации вытеснения.

Основные критерии выбора были следующие:

  • наличие исходных текстов и разрешение на коммерческое использование
  • простое портирование на другие архитектуры, понятный и масштабируемый код на языке Си
  • наличие дополнительных библиотек - файловой системы, tcp/ip стека и т.п.
  • объем программной памяти и памяти данных, используемый ядром
  • время реакции на внешнее событие

TNKernel изначально удовлетворяла всем критериям, поэтому и была выбрана за основу, несмотря на то что оригинальная версия разработана для контроллеров с ядром ARM7.

Наличие исходных текстов

Существует большое количество коммерческих и бесплатных "легких" RTOS для однокристальных контроллеров, исходные коды которых либо выложены в свободном доступе (freeRTOS), либо доступны только для ознакомительных целей (uC/OS-II), либо можно найти в файлообменных сетях (ThreadX).

TNKernel распространяется по лицензии, допускающей модификацию исходников и коммерческое использование при сохранении копирайта. Это стало одним из решающих аргументов.

Несмотря на то, что лицензия freeRTOS так же допускает изменение исходных кодов и коммерческое использование, freeRTOS не удовлетворяет многим другим критериям (с моей точки зрения).

Простое портирование, понятный код

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

Под "простым" портированием я понимаю четкое разделение собственно ядра системы (которое должно быть написано на С/С++) и модулей, зависящих от архитектуры (переключение контекста, работа с прерываниями и т.п.). Большинство известных RTOS для однокристальных контроллеров имеют как большое количество портов, так и сформировавшуюся структуру, которая позволяет быстро порты добавлять.

На момент выбора системы порты для 16-битных контроллеров Microchip имели только freeRTOS и uC/OS-II. Однако, порт для uC/OS-II не работал (ошибка в ассемблерном модуле - первый релиз, спишем на это), а в порте freeRTOS был найден комментарий типа "в этом месте может зависнуть, почему - пока не понятно…". Все это ставило под сомнение использование этих систем (тем более, что uC/OS-II еще и коммерческая). Сейчас ситуация изменилась - выходят обновления портов, обновления самих систем. Поэтому выбор может быть не столь очевидным, и, возможно, даже не в пользу TNKernel (если вы, например, уже используете freeRTOS).

Понятный код - еще один момент на котором стоит остановиться. Несомненно, что каждый программист или коллектив имеет сложившийся стиль, поэтому трудно оценивать чужой код - понятный он или нет. Мне наиболее ближе TNKernel - по такому критерию это несомненный лидер.

Наличие дополнительных библиотек

В этом случае явным лидером является uC/OS-II, так как имеет огромное количество дополнительного софта (за дополнительные же деньги): файловую систему, стек tcp/ip, библиотеку обслуживания USB, GUI и т.д. freeRTOS может включать в себя порт открытого tcp/ip стека uIP и большое количество примеров, построенных на его основе.

Оригинальная версия TNKernel имеет библиотеку USB Bulk Firmware для контроллеров NXP LPC2100 и урезанный порт Nano-X GUI. Если первое не может использоваться совместно с 16-битными контроллерами Microchip в силу понятных причин, то второе вполне можно успешно применять в проектах на PIC24/dsPIC и PIC32. Недавно автором TNKernel был выпущен TCP/IP стек, который, возможно будет работать и на PIC32.

Используемые ресурсы

По этому критерию TNKernel вне конкуренции - uC/OS-II и freeRTOS требовали почти в два раза больше программной памяти и в полтора раза больше ОЗУ (не считая стеков задач). Возможно сейчас ситуация изменилась, но в начале это произвело впечатление.

Следует заметить, что и uC/OS-II и freeRTOS требуют компиляции в составе проекта, а линкер Microchip C30 пока не умеет игнорировать неиспользуемые секции кода, подключая на выход целиком весь объектный файл, даже если из него используется одна функция, лежащая в отдельной секции. Поэтому в проект с использованием freeRTOS и uC/OS-II будет включаться весь исполняемый код RTOS.

Конечно это не является недостатком вышеназванных RTOS - это проблема компилятора Microchip C30. Частично она решается заголовочными файлами конфигурации, в которых указано, какие сервисы и объекты будут использоваться. Тем не менее даже полный вариант TNKernel использует меньше программной памяти чем freeRTOS или uC/OS-II.

Компилятор Microchip C32 основан на новой версии GCC и умеет игнорировать неиспользуемые функции в объектном файле, однако для совместимости с портом для PIC24/dsPIC структура системы оставлена прежней.

Время реакции

Под временем реакции будем понимать время, необходимое для входа в задачу ожидающую событие с момента наступления этого события. Как правило это время измеряется следующим образом: в задаче вызывается сервис ожидания семафора, а семафор освобождается в обработчике внешнего прерывания. Временем между возникновением прерывания и выходом из сервиса ожидания и будет время реакции.

Оценить время реакции и другие "скоростные" параметры RTOS, можно используя набор тестов известного производителя Express Logic Corp. (автора ThreadX), который называется Thread-Metric Test Suite. Результаты тестов для наиболее известных RTOS для PIC24/dsPIC приведены в таблице.

Cooperative Scheduling Preemptive Scheduling Interrupt Processing Interrupt Preemption Message Processing Sync Processing Memory Processing
TNKernel (1) 4,139,983 7,784,007 3,179,511 5,721,174 13,621,698 9,746,870
AVIX 9,069,625 5,100,589 7,400,858 3,293,937 5,020,698 19,030,131 10,609,717
ThreadX 11,848,815 5,032,710 7,342,967 3,132,150 7,354,317 17,592,956 14,413,455
uc/OS-II (1) 3,909,085 5,259,998 (1) 7,387,612 10,293,318 6,814,817
FreeRTOS (2) 3,717,913 1,881,892 2,400,967 0,484,691 1,989,999 (1)
AVA (1) 1,724,948 5,207,762 1,260,190 2,761,154 7,514,799 10,235,182

(1) Функция или объект не поддерживается
(2) Ошибка выполнения теста

Проект с тестовым приложением для TNKernel можно скачать по ссылке.

В таблице присутствуют RTOS, которые раньше не упоминались, поэтому дадим краткую характеристику каждой из них:

  • AVIX - коммерческая RTOS специально разработанная для микроконтроллеров PIC24/dsPIC (в начале 2008 г. появился порт для 32-битных контроллеров PIC32). По утверждению автора это первая в мире RTOS для однокристальных контроллеров, которая имеет "нулевую" программную задержку входа в обработчик прерывания, то есть системные сервисы прерывания не запрещают. Кроме того, для контекста прерываний AVIX использует отдельный системный стек.
  • ThreadX - порт известной коммерческой RTOS для контроллеров PIC24/dsPIC.
  • AVA - еще одна коммерческая RTOS, разработанная специально для 16-битных контроллеров Microchip. Судя по результатам теста и критическим ошибкам в первых релизах ничего хорошего из себя не представляет.

Тестирование TNKernel и AVIX можно повторить самостоятельно, скачав проекты. Остальные результаты взяты с форума microchip.com. Результаты тестов так же опубликованы на сайте AVIX, однако они устаревшие и неполные.

Если за первое место в тесте начислять 3 балла, за второе - 2 балла и за третье - 1 балл, то AVIX займет лидирующую позицию, ThreadX - второе место, а TNKernel - третье.

Самая популярная freeware RTOS для однокристальных микроконтроллеров - freeRTOS оказалась по совокупности результатов на одном из последних мест. По просьбе автора, freeRTOS удалена из таблицы сравнения на странице AVIX - по его утверждению результаты тестов сильно отличаются от реальности. Однако, до сих пор результаты автор freeRTOS не привел, поэтому в этом документе опубликовано то, что было получено в изначальной дискуссии. Вполне возможно, что на самом деле freeRTOS ведет себя гораздо лучше…

Таким образом, можно сказать, что TNKernel является лучшим из вытесняющих планировщиков, распространяемых с открытыми исходными кодами и допускающих использование в коммерческих разработках.

Отличия TNKernel для PIC24/dsPIC и PIC32

Исходные коды

Структура исходных текстов TNKernel значительно изменена по сравнению с оригинальной. Основное отличие - каждая функция находится в отдельном файле. Таким образом обходится проблема линкера C30, который не может игнорировать неиспользуемые секции кода.

При сборке проекта в исполняемый файл линкер добавляет только те функции, которые используются в пользовательском приложении. Это позволяет значительно сократить объем программной памяти, используемый ядром. Например, все сервисы требуют порядка 15 кБ программной памяти, тогда как в среднем приложении ядро RTOS занимает примерно 6-7 кБ.

Кроме разделения исходных кодов на файлы была предпринята попытка сделать TNKernel еще более портируемой - все основные типы переопределяются, все машинозависимые функции вынесены в отдельные модули (префикс port_). Это позволило в свое время достаточно просто добавить порт для PIC32.

Итак, скачав архив с проектом вы увидите католог source в котором и находятся исходные тексты TNKernel для PIC24/dsPIC. Файл _build_mchp_c30.bat предназначен для сборки библиотеки. Его можно отредактировать для сборки файла с требуемыми параметрами - другим уровнем оптимизации, моделью памяти и пр. Текущая версия командного файла собирает четыре библиотеки - две для PIC24 с оптимизацией Os и форматом coff и elf и две для dsPIC. То же самое и для PIC32, командный файл называется _build_mchp_c32.bat

Для сборки необходимо, чтобы в системе был прописан путь к исполняемому файлу компилятора.

Порт для PIC24/dsPIC

Компания Microchip имеет две основные линейки 16-битных контроллеров: PIC24 - микроконтроллеры общего назначения и dsPIC - контроллеры цифровой обработки сигналов. По сути PIC24 являются усеченной версией dsPIC - в них отсутствует DSP ядро и специальные методы адресации.

Изначально TNKernel портировалась как под PIC24, так и под dsPIC, причем в версии для последнего в стеке задачи кроме всего прочего, сохранялся контекст DSP-ядра. Но как выяснилось это не имело большого смысла, потому, что полностью восстановить контекст DSP простыми способами невозможно - большинство статусных флагов DSP-ядра имеют доступ только для чтения, да и с аппаратным циклом DO все не так просто. Поэтому от отдельного порта для dsPIC было решено отказаться - в следующих вариантах TNKernel для PIC24/dsPIC DSP-ядро было предложено рассматривать как разделяемые ресурс и использовать для доступа к нему из разных задач мютекс.

Но как выяснилось напрасно. Благодаря камраду qas был найден серьезный баг, который мог однозначно порушить систему при использовании модульной или бит-реверсивной адресации DSP-ядра. Баг исправлен, но опять появилось две версии TNKernel - для PIC24 и для dsPIC.

Тем не менее ситуация с DSP-ядром прежняя - его контекст не сохраняется и его следует рассматривать как разделяемый ресурс, используя для доступа из разных задач мютекс.

Порт для PIC32

Порт для PIC32 был реализован весной 2010 года по просьбам трудящихся. По сути он мало чем отличается от порта для PIC24/dsPIC. Начиная с версии 2.5.600 в комплекте идет пример, который может быть скомпилирован как под PIC24 так и под PIC32 без изменений.

Основные отличия от оригинальной версии

1. Типы данных

Все стандартные типы данных (кроме void) переопределены:

TN_CHAR
для всех архитектур соответствует signed char. Под char в данном случае подразумевается 1 байт.
TN_UCHAR
для всех архитектур соответствует unsigned char
TN_WORD
для PIC24/dsPIC (компилятор C30) соответствует signed int, то есть 16-битному целому со знаком
для ARM (Keil RV) и PIC32 (C32) соответствует signed int, то есть 32-битному целому со знаком
TN_UWORD
размер машинного слова. Этот тип рекомендуется использовать для объявления стеков задач
для PIC24/dsPIC (компилятор C30) соответствует unsigned int, то есть беззнаковому 16-битному целому
для ARM (Keil RV) и PIC32 (C32) соответствует unsigned int, то есть беззнаковому 32-битному целому
TN_SYS_TIM_T
тип счетчика системного времени. Для PIC24/dsPIC это 32-битный счетчик, для ARM/PIC32 - 64-битный
TN_TIMEOUT
тип таймаута
для PIC24/dsPIC (компилятор C30) соответствует unsigned int, то есть беззнаковому 16-битному целому
для ARM (Keil RV) и PIC32 (C32) соответствует unsigned int, то есть беззнаковому 32-битному целому

Рекомендуется употреблять эти типы для объявления переменных и массивов, связанных непосредственно с системой - стеков задач, блоков памяти фиксированного размера, очередей сообщений и др.:

TN_UWORD task_1_stack[128] TN_DATA;

2. Приоритеты задач

В оригинальной версии TNKernel задачи могут иметь приоритет от 1 до 30 (0 и 31 приоритет имеют системные задачи). В версии TNKernel для PIC24/dsPIC пользовательские задачи могут иметь приоритет от 1 до 14 (0 и 15 приоритет имеют системные задачи). Это связано с разрядностью слова контроллера и стремлением сократить время поиска следующей задачи, т.е. по сути время переключения контекста.

Следует сказать, что такого количества приоритетов вполне достаточно, так как опционально TNKernel обеспечивает карусельное (round-robin) переключение между задачами с одинаковым приоритетом.

В версии TNKernel для PIC32 задачи могут иметь такие же приоритеты как и в оригинальной: 1 до 30.

3. Инициализация системы

Инициализация системы в оригинальной версии TNKernel выполняется с помощью функции tn_start_system(), которая не имеет параметров. В порте TNKernel для PIC24/dsPIC и PIC32 эта функция выглядит следующим образом:

Вызов:

void tn_start_system (TN_UWORD *timer_task_stack,
                      TN_UWORD  timer_task_stack_size,
                      TN_UWORD *idle_task_stack,
                      TN_UWORD  idle_task_stack_size,
                      void      (*app_in_cb)(void),
                      void      (*cpu_int_en)(void),
                      void      (*idle_user_cb)(void)
                     );

Разрешен вызов:

В контексте задачи

Параметры функции:

timer_task_stack
указатель на стек системной задачи таймера
timer_task_stack_size
размер стека системной задачи таймера (в машинных словах)
idle_task_stack
указатель на стек системной задачи простоя
idle_task_stack_size
размер стека системной задачи простоя (в машинных словах)
app_in_cb
указатель на функцию инициализации приложения. Эта функция вызывается после того как системные задачи будут созданы, а планировщик запущен
cpu_int_en
указатель на функцию конфигурации прерываний. Эта функция вызывается сразу после функции app_in_cb
idle_user_cb
указатель на функцию, циклически вызываемую из задачи простоя. В этой функции можно, например, инкрементировать счетчик загрузки или уводить контроллер в состояние пониженного энергопотребления (Sleep или Idle)

Возвращаемые значения:

нет

Пример вызова:

#define TMR_TASK_STACK_SIZE    128
#define IDL_TASK_STACK_SIZE    128
 
TN_UWORD stk_tmr[TMR_TASK_STACK_SIZE] TN_DATA;  /* стек задачи таймера */
TN_UWORD stk_idl[IDL_TASK_STACK_SIZE] TN_DATA;  /* стек задачи простоя */
 
void appl_init(void);
void intr_init(void);
void idle_user(void);
 
int main (void)
{
    tn_start_system(stk_tmr,
                    TMR_TASK_STACK_SIZE,
                    stk_idl,
                    IDL_TASK_STACK_SIZE,
                    appl_init,
                    intr_init,
                    idle_user
                   );
}
 
void appl_init (void)
{
    /* инициализация */
}
 
void intr_init (void)
{
    /* инициализация и разрешение прерываний */
}
 
void idle_user (void)
{
    /* когда нечего делать мы тут */
}

Функции app_in_cb и cpu_int_en заменяют tn_app_init() и tn_cpu_int_enable() в оригинальной версии TNKernel.

Введение параметров в функцию tn_start_system() позволило более гибко настраивать систему, в частности, выбирать размеры стеков системных задач и выполнять полезные действия в задаче простоя (tn_task_idle()).

По сути в точке входа приложения - функции main() должен вызываться только сервис tn_start_system().

4. Создание задачи

Изменен вызов сервиса создания задачи tn_task_create():

TN_RETVAL tn_task_create (TN_TCB    *task,
                          void     (*task_func)(void *param),
                          TN_UWORD  priority,
                          TN_UWORD  *task_stack_start,
                          TN_UWORD  task_stack_size,
                          void      *param,
                          TN_UWORD  option
                         );

Параметр task_stack_start указывает на вершину (младший адрес) стека задачи, тогда как в оригинальной версии, task_stack_start указывает на старший адрес стека. Это связано с тем, что в PIC24/dsPIC стек растет от младшего адреса к старшему.

В версии TNKernel для PIC32 в функцию создания задачи так же должен передаваться адрес вершины стека, несмотря на то, что у MIPS32 стек растет от старшего адреса к младшему.

Нововведения

1. Критические секции

Добавлены функции tn_sys_enter_critical() и tn_sys_exit_critical(), которые аналогичны используемым в оригинальной версии tn_disable_interrupt() и tn_enable_interrupt(). Функции используются следующим образом:

/* ... */
 
tn_sys_enter_critical();
    /*
      критическая секция кода, в которой запрещено переключение контекста
    */
tn_sys_exit_critical();
 
/* ... */

Названия функций отражают их назначение - выделение части кода в критическую секцию в которой запрещено переключение контекста. tn_disable_interrupt() и tn_enable_interrupt() - не совсем корректное название для PIC24/dsPIC, которые имеют векторный приоритетный контроллер прерываний.

В версии TNKernel PIC32 функция tn_sys_enter_critical() запрещает все прерывания!

2. Новые сервисы

Добавлены следующие сервисы:

3. Атрибут задачи

Функции задач могут объявляться с атрибутом TN_TASK. Этот атрибут сообщает компилятору о том, что функция имеет бесконечный цикл и выхода из нее не будет. В большинстве случаев это позволяет уменьшить размер стека задачи. Пример:

void TN_TASK Task (void *par)
{
    for (;;)
    {
        tn_task_sleep(10);
    }
}

4. Атрибут данных

Объекты и стеки задач могут объявляться с атрибутом TN_DATA. По сути он размещает переменные в отдельной секции ОЗУ - это позволяет контролировать объем памяти, занимаемой объектами RTOS и стеками задач. Для этого в скрипт линкера необходимо добавить следующие строки (см., например, файл ..\example1\p24FJ128GA006.gld):

.tnk_data :
{
      *(tnk_data);
} > data

Пример использования атрибута:

TN_SEM   Sem_From_IRQ TN_DATA;
TN_DQUE  que_test     TN_DATA;

Все сервисы TNKernel размещаются в отдельную секцию кода. Это позволяет контролировать объем программной памяти, которую занимает ядро. Для этого в скрипт линкера необходимо добавить следующие строки (см., например, файл ..\example1\p24FJ128GA006.gld):

.tnk_code :
{
      *(tnk_code);
} >program

В версии TNKernel для PIC32 именованные секции кода пока не поддерживаются.

5. Отладка

Если в заголовочном файле tnkernel_conf.h не объявить TN_DEBUG, внутренняя структура всех объектов будет скрыта от пользователя, и структура объектов в окне Watch отладчика будет отображена в виде байтового массива.

Если TN_DEBUG будет объявлен, структуры объектов будут раскрыты. Это позволит отлаживать приложение контролируя значения полей структур.

6. Варианты сервисов без проверки параметров

В порте TNKernel для PIC24/dsPIC и PIC32 имеется два набора сервисов - с проверкой параметров и без проверки параметров. Естественно, последние будут занимать меньше программной памяти и будут быстрее выполняться.

Объявление TN_NO_ERROR_CHECKING в файле конфигурации системы tnkernel_conf.h позволяет использовать более компактные и быстрые варианты сервисов без проверки параметров.

7. Контроль переполнения стеков задач

Микроконтроллеры PIC24/dsPIC имеют аппаратный механизм контроля переполнения стека, который полностью задействован в TNKernel для PIC24/dsPIC. Для того чтобы контролировать переполнение, необходимо объявить в коде исключение (trap) по ошибке стека:

void __attribute__((interrupt, no_auto_psv)) _StackError (void)
{
    for (;;);   /* при переполнении стека задачи попадем сюда */
}

В версии TNKernel для PIC32 контроль переполнения стека не поддерживается

8. Код возврата TERR_EXS

Любой сервис, создающий объект (tn_task_create(), tn_sem_create(), tn_queue_create(), tn_event_create(), tn_fmem_create() и tn_mutex_create()), проверяет состояние объекта (уже создан или нет) и, либо продолжает работу, либо (если объект уже создан) возвращает код ошибки TERR_EXS.

Наличие проверки состояния объекта не зависит от типа вызываемого сервиса (с проверкой или без проверки параметров).

9. Получение ревизии TNKernel

Добавлен заголовочный файл tnkernel_rev.h, в котором присутствуют следующие определения:

  • __TNKERNEL_VERSION - текущая версия (float)
  • __TNKERNEL_REVISION - текущая ревизия (беззнаковое целое)
  • __TNKERNEL_REVISION_TIME_STRING - время и дата создания ревизии (строка)
  • __TNKERNEL_BUILD_TIME_STRING - время и дата сборки библиотеки (строка)

Пример использования:

TN_UWORD  tn_revision = __TNKERNEL_REVISION;
char     *tn_data     = __TNKERNEL_REVISION_TIME_STRING;
char     *tn_build    = __TNKERNEL_BUILD_TIME_STRING;
 
#if (__TNKERNEL_VERSION == 2.5)
    #if (__TNKERNEL_REVISION == 977)
        /* ... */
    #endif
#else
    /*...*/
#endif
 
printf(tn_data);

10. Системный таймер

Системным таймером назван счетчик, инкрементируемый каждый системный тик. Для установки и получения значения системного таймера используются следующие сервисы:

11. Файл конфигурации

Пользовательский проект должен включать в себя заголовочный файл конфигурации tnkernel_conf.h, в котором определены (или не определены) дефайны TN_DEBUG и TN_NO_ERROR_CHECKING. Конечно, в свойствах проекта папка с этим файлом должна быть добавлена в пути поиска заголовочных файлов.

Добавление пути поиска заголовочных файлов

Использование прерываний

Основное предупреждение: все прерывания должны быть запрещены до момента запуска системы. Для конфигурации источников прерываний и разрешения прерываний предназначена функция cpu_int_en, указатель на которую передается в сервисе tn_start_system().

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

В TNKernel для PIC24/dsPIC системные прерывания должны иметь приоритет, равный TN_INTERRUPT_LEVEL (приоритет 1). Вызов сервисов RTOS в обработчике прерывания с другим (более высоким) приоритетом (т.е. в ISR пользовательского прерывания) запрещен - это приведет к краху системы. В текущей версии TNKernel защита от вызова системных сервисов в пользовательском прерывании не реализована.

В TNKernel для PIC32 системные прерывания должны иметь одинаковый приоритет, но не обязательно равный TN_INTERRUPT_LEVEL. Однако для совместимости кода рекомендуется использовать приоритет 1, как и в версии TNKernel для PIC24/dsPIC.

В TNKernel для PIC24/dsPIC и PIC32 не реализована вложенность системных прерываний. С одной стороны это может привести к задержке обработки прерывания, с другой - экономит стек задачи, что на самом деле более важно, особенно для PIC32. Если задержка входа в прерывание недопустима, можно использовать пользовательское прерывание с приоритетом большим чем TN_INTERRUPT_LEVEL. Однако, не нужно забывать, что вызов сервисов RTOS в пользовательском прерывании запрещен, поэтому задачи должны взаимодействовать с пользовательским прерыванием с помощью глобальных переменных. Это некрасиво и по большому счету неправильно, но другого выхода нет…

Системные прерывания объявляются с помощью макроса tn_sys_interrupt, аргументом которого является зарезервированый псевдоним вектора прерывания:

/* PIC24/dsPIC */
tn_sys_interrupt (_INT0Interrupt)   /* системное прерывание, источник INT0 */
{
    IFS0bits.INT0IF = 0;
    tn_queue_isend_polling(&que_test, transceived_buff);
}
 
/* PIC32 */
tn_sys_interrupt(_CHANGE_NOTICE_VECTOR)
{
    INTClearFlag(INT_CN);
    /* обработка прерывания */
}

Пользовательские прерывания объявляются обычным для C30/C32 способом.

Одно из системных прерываний всегда должно быть зарезервировано для системного таймера. Как правило это прерывание от аппаратного таймера с периодом 1-10 мс:

/* PIC24/dsPIC */
tn_sys_interrupt (_T2Interrupt)     /* системное прерывание, источник TMR2 */
{
    IFS0bits.T2IF = 0;
    tn_tick_int_processing();
}
 
/* PIC32 */
tn_sys_interrupt(_CORE_TIMER_VECTOR)   /* системное прерывание, источник - системный таймер MIPS32 */
{
    Sys_Tmr_Int_Handler();
    tn_tick_int_processing();
}

Сервис tn_tick_int_processing() должен вызываться только из системного прерывания.

Внимание!!! Если в обработчике прерывания вызывается серсив tn_tick_int_processing(), то вызов других сервисов RTOS в этом прерывании запрещен!

Следует заметить что сервисы tn_sys_enter_critical() и tn_sys_exit_critical() запрещают системные прерывания, в то время как прерывания с приоритетом, большим TN_INTERRUPT_LEVEL остаются активными - только для PIC24/dsPIC. Для PIC32 эти сервисы запрещают ВСЕ прерывания.

Отличия порта для PIC32 от порта для PIC24/dsPIC

  1. tn_sys_enter_critical() запрещает все прерывания, а не только с приоритетом TN_INTERRUPT_LEVEL
  2. данные и код не размещаются в именованные секции
  3. системные прерывания могут иметь приоритет отличный от TN_INTERRUPT_LEVEL, однако приоритет должен быть одинаковым для всех системных прерываний
  4. приоритеты задач - от 1 до 30
  5. переполнение стека не контролируется!
 
tnkernel/mchp_c30_16bit_port.txt · Последние изменения: 16.02.2011 20:57 От admin
 
Creative Commons License Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki