RTOS ChibiOS/RT – операционная система для микроконтроллеров.
RTOS ChibiOS/RT:
CHIBIOS/RT – операционная система для микроконтроллеров
Поток
Каждый поток имеет свой собственный стек, структуру потока и некоторые области вытеснения. Все структуры были отнесены в «потоки рабочей области» (рисунок 1), поток собственной кучи, как правило, статически объявляются в коде. Потоки не используют другую память за пределами выделенной рабочей зоны, кроме случаев, когда осуществляется общий доступ к статическим данным.
Рисунок 1. Потоки рабочей области.
Обратите внимание, что область вытеснения присутствует только, когда поток не работает (включается выход), переключение контекста осуществляется выбором регистра в стеке коммутируемого выходного потока. Появляющиеся регистры включается в потоке от его стека. Область опережения можно разделить на три структуры:
- Внешний контекст.
- Прерывание стека.
- Внутренний контекст.
Рисунок 2. Совместная схема работы базовых служб ядра.
Поток – абстракция независимого потока инструкций. В СhibiOs/RT поток представляет собой функцию на языке “C”, владеющую контекстом процессора, использующую системную информацию, а также имеющую специальную зону стека. В этом случае статические переменные являются общими для всех потоков, а автоматические переменные являются локальными для обработки данных.
Создание потока, поток запускается для заданной функции потока. Эта операция доступна в нескольких вариантах, как статически, так и динамически. Выход из потока, поток завершается по возвращении из своей функции верхнего уровня или вызова конкретного API, поток может возвращать значение, которое можно получить из других потоков. Ожидание потока, поток ожидает прекращения работы другого потока и получает возвращаемое значение. Резюме потока, происходит запуск потока, созданного в подвешенном состоянии. Спящий режим потока, выполнение потока приостанавливается в течение указанного времени или достигнуто указанное абсолютное время. SetPriority, установка приоритета потока, поток изменяет свой уровень приоритета. Выход потока, поток добровольно может отказаться от своего временного интервала работы и закончить свое выполнение. Для потока характерна наследование, список потоков наследует свойства и методы от очереди потоков, очередь потоков наследует свойства и методы от базового класса потока.
Структуры данных:
struct Thread – структура представляет поток.
Функции:
Thread* _thread_init(Thread *tp, tprio_t prio) – инициализация структуры потока.
void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v) – заполнение памяти.
Thread* chThdCreateI (void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) – создание нового потока в статической области памяти.
Thread* chThdCreateStatic (void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) – создание нового потока в статической области памяти.
tprio_t chThdSetPriority (tprio_t newprio) – изменяет уровень приоритета для текущего потока.
Thread* chThdResume (Thread *tp) – возобновляет работу приостановленного потока.
void chThdTerminate (Thread *tp) – запрос на прекращение работы потока.
void chThdSleep (systime_t time) – приостанавливает работу потока на указанный промежуток времени.
void chThdSleepUntil (systime_t time) – планировщик приостанавливает работу потока, до тех пор, пока система недосчитает до заданного времени.
void chThdYield (void) – функция вырабатывает временной интервал.
void chThdExit (msg_t msg) – завершение работы текущего потока.
void chThdExitS (msg_t msg) – завершение работы текущего потока.
msg_t chThdWait (Thread *tp) – блокирует выполнение вызывающего потока, пока заданный поток не завершит свою работу, функция имеет код возврата.
Прототип и описание функций находиться в файлах chthreads.h и chthreads.c.
В данной статье разберем особенности создания вытесняющей многозадачности для отладочной платы SMT32429I – DISCO компании STMicroelectronics.
Рисунок 3. Отладочная плата STM32F429I – DISCO.
Многозадачность – свойство операционной системы или среды выполнения обеспечивать возможность параллельной (или псевдопараллельной) обработки нескольких процессов. Истинная многозадачность операционной системы возможна только в распределённых вычислительных системах. Вытесняющая многозадачность в ChibiOS/RT реализуется за счет работы планировщика Диспетчер (планировщик) каждый системный тик, останавливает задачу (A) и передает управление другой задаче, задаче (B). Обеспечивая тем самым псевдопараллельное выполнение.
Для работы необходимо скачать дистрибутив ChibiOS/RT с официального сайта (chibios.org), на момент написания статьи последняя рабочая версия ОСРВ ChibiOS/RT 2.6.8. В июне 2015 года выйдет обзорная версия, на новой 3-ей версии ядра, ChibiOS/RT 3.0.0p5.
Каталог с ChibiOS/RT 2.6.8. содержит следующие подкаталоги: boards, demos, docs, ext, os, test, testhal. Каталог boards содержаться список поддерживаемых отладочных плат, для каждой отладочной платы присутствует файлы конфигурации внешней периферии. Каталог demos содержит демонстрационные проекты под различные IDE и для различных компиляторов, в случае если у Вас нет в наличии отладочной платы, проект можно собрать для Win32-MinGW. Каталог docs содержит описание ChibiOs/RT и результаты запуска тестов для различных платформ. Каталог ext содержит Middlewares для стека TCP/IP (lwip, uip) и файловую систему fatfs. Каталог os является основным каталогом, так как в нем располагаются подкаталоги ядра ChibiOs/RT, HAL слой аппаратных абстракций, Middlewares связующее программное обеспечение и подкаталог для запуска под различные компиляторы (ports). Каталог test содержит тесты для оценки быстродействия работы ядра для различных платформ и отладочных плат. Каталог testhal содержит примеры работы со слоем аппаратной абстракции.
Процесс создания проекта для отладочной платы STM32F429I – DISCO в среде разработке keil uVision 5:
- Запустите keil uVision 5, в главном меню выберите «Project» -> «New uVision Project…».
- Создайте каталог для будущего проекта, например, ChibiOS_2.6.8\demos\STM32F429I_DISCO_KEIL (STM32F429I_DISCO_KEIL – название созданного каталога), введите название Имя файла: «template», нажмите кнопку «Сохранить»
- Появилось окно выбора микроконтроллера, на отладочной плате установлен STM32F429ZITx, выбираем из списка соответствующий микроконтроллер, нажимаю кнопку «ОК».
- Появилось окно «Менеджер среды keil uVision», ничего не выбираем, а нажимаем кнопку «ОК».
- Настроим проект, для этого в главном меню необходим выбрать «Project» – > «Options for Target …»
- Вкладка «Target», изменяем опорную частоту Xtal(Mhz) на 8 Mhz (данный пункт не является обязательным, а показывает правильный стиль дальнейшего сопровождения проекта).
- Вкладка «Target», изменяем IRAM2, «start» устанавливаем 0x20030000, а «size» устанавливаем 0x1 и затем выбираем default для IRAM2, аналогично IRAM1 (начала области памяти для IRAM2 = IRAM1 + Size[IRAM1]).
- Переходим во вкладку «С/C++». Вкладка «С/C++». В строке «Preprocessor Symbols»/Define пишем следующий текст «__heap_base__=Image$$RW_IRAM1$$ZI$$Limit __heap_end__=Image$$RW_IRAM2$$Base».
- Вкладка «С/C++». Выставляем 3 уровень оптимизации (-O3), выбираем оптимизировать по времени.
- Вкладка «С/C++». Нажимаем кнопку «…» Include Paths, в появившемся окне необходимо добавить весь список следующих каталогов, относительно родительского каталога:
..\STM32F429I_DISCO_KEIL
..\..\os\kernel\include
..\..\os\ports\common\ARMCMx
..\..\os\ports\common\ARMCMx\CMSIS\include
..\..\os\ports\RVCT\ARMCMx
..\..\os\ports\RVCT\ARMCMx\STM32F4xx
..\..\os\hal\include
..\..\os\hal\platforms\STM32
..\..\os\hal\platforms\STM32\GPIOv2
..\..\os\hal\platforms\STM32\SPIv1
..\..\os\hal\platforms\STM32\TIMv1
..\..\os\hal\platforms\STM32\USARTv1
..\..\os\hal\platforms\STM32F4xx
..\..\os\various
..\..\os\various\devices_lib\accel
- Переходим во вкладку «Asm». Вкладка «Asm». Необходимо давить строку «–cpreproc» в строке ввода Misc Controls.
- Вкладка «Asm». Нажимаем кнопку «…» Include Paths, в появившемся окне необходимо добавить весь список следующих каталогов, относительно родительского каталога:
..\STM32F429I_DISCO_KEIL
..\..\boards\ST_STM32F429I_DISCOVERY
..\..\os\ports\RVCT\ARMCMx\STM32F4xx
- Переходим во вкладку «Debug». В списке отладчиков выбираем ST-Link Debugger.
- После выбора отладчика нажимаем кнопку «Settings». В появившемся окне «Cortex – M Target Driver Setup» выбираем Port: SW, Max Clock 4 Mhz, слева в окне отобразиться текущий микроконтроллер.
- Остаемся в том же окне и выбираем вкладку «Flash Download». Вкладка «Flash Download». Нажимаем кнопку «Add» и добавляем «STM32F4xx 2 MB Flash». Затем нажимаем кнопку «OK».
- Переходим во вкладку «Utilities». В списке устройств загрузки прошивки выбираем ST-Link Debugger и нажимаем кнопку «OK».
- В главном меню выберите «Project» -> «Manage» -> «Components, Environment, Books…». В появившемся окне необходимо создать следующего вида архитектуру с вложенными файлами:
main
main.c
conf
board.c
os
chcond.c
chdebug.c
chdynamic.c
chevents.c
chheap.c
chlists.c
chmboxes.c
chmemcore.c
chmempools.c
chmsg.c
chmtx.c
chqueues.c
chregistry.c
chschd.c
shsem.c
shsys.c
chthreads.c
chvt.c
hal
pal.c
adc.c
pwm.c
serial.c
spi.c
hal.c
platform
hal_lld.c
adc_lld.c
pwm_lld.c
serial_lld.c
spi_lld.c
stm32_dma.c
pal_lld.c
port
chcore_v7m.c
chcore.c
nvic.c
cstartup.c
vectors.s
chcoreasm_v7m.s
- В главный исходный файл (c) необходимо добавить ниже приведенный пример.
Пример реализации многозадачности в ChibiOS/RT.
//main.c #include «ch.h» #include «hal.h» //Выделение памяти под Thread1 static WORKING_AREA(waThread1, 128); //Выделение памяти под Thread2 static WORKING_AREA(waThread2, 128); //Объявление прототипа функции Thread1 static msg_t Thread1(void *arg); //Объявление прототипа функции Thread2 static msg_t Thread2(void *arg); //Создаем структуры для отсчета промежутка времени typedef struct TaskParam_t{ signed long int period; } Task; Task p1, p2; int main(void){ //Пауза 1000мс p1.period = 1000; //Пауза 500мс p2.period = 500; //Инициализируем hal halInit(); //Системная инициализация chSysInit(); //Создание потока для Thread1 chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, (void *)&p1); //Создание потока для Thread2 chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, (void *)&p2); while(TRUE){ } } //Описание первого потока static msg_t Thread1(void *arg){ Task *period; period = (Task *) arg; //Задаем начальное состояние для GPIOG_LED4_RED, порт находиться в логической 1. palSetPad(GPIOG, GPIOG_LED4_RED ); while(TRUE){ //Переключаем состояние работы выходного порта для GPIOG_LED4_RED palTogglePad(GPIOG, GPIOG_LED4_RED); //Отправляем задачу в спящий режим chThdSleepMilliseconds(period->period); } } //Описание второго потока static msg_t Thread2(void *arg){ Task *period; period = (Task *) arg; //Задаем начальное состояние GPIOG_LED3_GREEN, порт находиться в логической 1. palSetPad(GPIOG, GPIOG_LED3_GREEN); while(TRUE){ //Переключаем состояние работы выходного порта для GPIOG_LED3_GREEN palTogglePad(GPIOG, GPIOG_LED3_GREEN); //Отправляем задачу в спящий режим chThdSleepMilliseconds(period->period); } }
Thread *chThdCreateStatic(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) – создание нового потока в статической области памяти.
wsp – указатель на выделенную память для текущей задачи.
size – размер памяти, сколько выделили памяти для задачи.
prio – уровень приоритета задачи.
pf – имя функции.
arg – данные передаваемые в функцию.
- Компилируем проект и загружаем firmware на микроконтроллер.
После загрузки firmware на микроконтроллер Вы сможете наблюдать мигание светодиодов на отладочной плате STM32F429I – DISCO и проанализировать принцип работы вытесняющей многозадачности ОСРВ ChibiOS/RT.