FreeRTOS
«Си для встраиваемых систем»
Это онлайн версия книги «Си для встраиваемых систем». В печатном формате её можно приобрести у нас в магазине, а в виде файла epub/mobi/pdf на площадке LeanPub.
Мы уже рассмотрели основные концепции ОСРВ, настало время разобрать одну из них — FreeRTOS.
Если рассмотреть типичное приложение с использованием FreeRTOS, то можно выделить три слоя поверх железа: пользовательский код, платформонезависимый код и платформозависимый код.

- Платформонезависимый код в свою очередь можно разделить на две подчасти.
- Задачи. Основное назначение ядра — это создание, уничтожение и управления задачами, за что отвечают два файла:
tasks.c
иtasks.h
, где заключено около половины всего кода. - Связь. Сами задачи так или иначе обмениваются данными, что создает проблему: нужно обеспечить безопасную и гарантированную их передачу. На решение этой проблемы также приходится около половины всего кода ядра. За связь отвечают файлы
queue.c
иqueue.h
, а критические ресурсы работают через семафоры и мьютексы (semaphr.c
иsemaphr.h
).
- Задачи. Основное назначение ядра — это создание, уничтожение и управления задачами, за что отвечают два файла:
- Аппаратное сопряжение. Большая часть кода FreeRTOS платформонезависима, т.е. может быть спокойно откомпилирована и запущена как на 8051, так и на ARM-ядрах. Однако операционная система не может полностью абстрагироваться от железа, а посему программно-зависимый код всё же необходим. Данная часть составляет примерно 5% от всего FreeRTOS и заключается в
port.c
,portmacro.h
.
Такой подход позволяет организовать поддержку большого количества платформ (ARM Cortex M, 8051, PIC и другие) и компиляторов (GCC, IAR, CodeWarrior и др.) — изменяется всего 5% кода вместо всей операционной системы. Сама ОС довольно гибкая в конфигурации и может быть настроена как для слабого одноядерного микроконтроллера с парой задач в программной части, так и для многоядерного МК с поддержкой стека TCP/IP, файловой системой и т. д. Настройка осуществляется через файл FreeRTOSConfig.h
изменением #define
-макросов. Ниже приведен пример настройки планировщика, частоты тактирования ядра МК, установки временного среза и максимального количества приоритетов.
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ (SystemCoreClock)
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES (7)
Подробное описание конфигурационного файла можно найти в официальной документации. Кроме упомянутых выше файлов, присутствуют и другие: list.c
/ list.h
реализует структуру данных двухсвязного списока, который используется для работы планировщика; файл portable.h
содержит макросы платформозависимых констант; в StackMacros.h
хранятся макросы для контроля переполнения стека; и другие.
Компания ARM, разработавшая ядро и библиотеку CMSIS, также предоставляет обертку (англ. wrapper) для систем реального времени (файлы cmsis_os.c
и cmsis_os.h
). Данный слой абстракции немного замедляет работу (будет выполняться лишний код), но позволяет легко переходить с одной операционной системы на другую. Так, если вы будете создавать проект для микроконтроллера stm32, используя утилиту STM32CubeMX, то она автоматически обернет операционную систему (FreeRTOS) в CMSIS-RTOS API. Отличие по большей части будет заключаться лишь в названии функций. Например, для запуска планировщика задач вам придется вызывать функцию osKernelStart()
вместо vTaskStartScheduler()
.
osStatus osKernelStart (void) {
vTaskStartScheduler();
return osOK;
}
Далее мы будем рассматривать родные функции FreeRTOS (9-й версии, последней на время написания книги), делая пометку об их эквиваленте из CMSIS-RTOS API.
Ниже рассмотрим основные возможности системы; само описание не является исчерпывающим, но достаточно для начала работы.