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.

Ниже рассмотрим основные возможности системы; само описание не является исчерпывающим, но достаточно для начала работы.


Изменено: