FreeRTOS
Семафоры и мьютексы
Помимо очередей, во FreeRTOS есть семафоры и мьютексы, которые можно использовать для межзадачного взаимодействия в зависимости от требований приложения. Более подробно о семафорах и мьютексах во FreeRTOS рассказывается в учебнике FreeRTOS.
Прямые уведомления о задачах
Прямые уведомления о задачах (direct task notifications) - это события, отправляемые непосредственно задаче без промежуточного механизма, такого как очередь или семафор. Это ускоряет обмен данными и занимает гораздо меньше места в памяти. Задача блокируется, когда в массиве событий уведомления установлен бит уведомления. Заблокировать задачу может только одно уведомление; если бы произошло другое событие, оно не повлияло бы на состояние задачи.
Буферы потоков и сообщений
Потоковые буферы предлагают механизм связи "один к одному" в следующих случаях:
- связь между задачами;
- связь между прерываниями и задачами.
Эти буферы оптимизированы для сценариев однократной записи и однократного чтения. Буферы потоков способны передавать байты, а буферы сообщений - дискретные сообщения переменного размера. Буферы сообщений строятся поверх буферов потоков.
Эти буферы очень полезны для следующих типов коммуникационных сценариев:
- передача данных из подпрограммы обслуживания прерываний в задачу;
- передача данных от одного ядра микроконтроллера к другому на двухъядерных процессорах.
Данные передаются посредством копирования, то есть они копируются в буфер отправителем и выводятся из буфера операцией чтения.
Таймеры
Таймеры могут быть реализованы программно в RTOS, поэтому их также можно назвать программными таймерами. Они не используют аппаратные ресурсы и не потребляют процессорное время. Таймер позволяет запускать задачи или события, которые должны произойти в определенный момент в будущем. Будущее время выполнения контролируется настройками таймера. Задача, которая должна быть выполнена, называется функцией обратного вызова таймера. Функция обратного вызова (callback) таймера выполняется по истечении времени таймера или периода таймера.
Как и другие компоненты RTOS, таймер должен быть явно создан, прежде чем его можно будет использовать.
Таймеры: соображения эффективности при реализации программных таймеров
Функциональность программного таймера, в общем, легко реализовать, но трудно реализовать эффективно.
Реализация таймера в RTOS обладает следующими свойствами:
- не выполняет функции обратного вызова таймера из контекста прерывания, пока таймер не истечет;
- не требует времени на обработку;
- не добавляет накладных расходов на обработку тикового прерывания;
- не выполняет другие операции доступа к памяти, пока прерывания отключены.
Задача обслуживания таймера в основном использует существующие возможности FreeRTOS, позволяя добавить функциональность таймера в приложение с минимальным влиянием на размер приложения.
Таймеры: важная информация о написании функций обратного вызова таймера
Функции обратного вызова таймера выполняются в контексте задачи обслуживания таймера, поэтому важно, чтобы функции обратного вызова таймера никогда не пытались блокировать. Например, функция обратного вызова таймера не должна вызывать vTaskDelay() или vTaskDelayUntil(), а также не должна указывать ненулевое время блокировки при обращении к очереди или семафору.
Таймеры: типы
Два типа таймеров могут быть определены и использованы в приложении:
-
Однократные таймеры.
Однократный таймер выполняется только один раз. По истечении срока действия таймера его обратный вызов вызывается и выполняется один раз.
-
Таймеры автозагрузки.
Таймер автозагрузки выполняется неограниченное время, пока работает приложение. Каждый раз, когда таймер истекает, выполняется обратный вызов, и таймер сбрасывается; таймер снова работает до следующего истечения срока его действия, что приводит к выполнению обратного вызова. Этот процесс повторяется, что приводит к периодическому выполнению обратного вызова.
Создание FreeRTOS приложений
С чего начать
Лучше всего начать создание нового приложения, использующего FreeRTOS, с демонстрационного приложения для выбранного процессора. Рекомендуется модифицировать демо-версию в соответствии с текущими требованиями. Это обеспечит хорошую отправную точку для приложения и устранит многие проблемы портирования (porting), которые могут возникнуть при создании нового приложения с использованием FreeRTOS.
Затем разработчик должен указать следующую предварительную информацию, необходимую для создания чистого приложения RTOS:
-
Количество требуемых задач
Каждому приложению потребуется управлять различными частями функциональности в разные моменты времени. Эти функциональные компоненты называются задачами; перед созданием приложения необходимо понять и определить необходимое количество задач для системы.
-
Функциональность каждой задачи
Функциональность каждой задачи также должна быть определена, понята и подробно описана.
-
Зависимость между задачами
Зависимости между задачами должны быть перечислены, чтобы пользователь мог определить следующий шаг для каждой задачи.
-
Механизм связи между задачами с зависимостями
Важно описать, как задачи будут общаться друг с другом и какой информацией нужно будет обмениваться между каждым набором зависимых задач.
-
Прерывания и зависимости от внешних событий
Разработчику приложения необходимо определить различные входные данные (как внешние, так и внутренние), необходимые для системы, и то, как они связаны друг с другом.
-
Ограничения памяти
Ограничения памяти системы необходимо понимать и определять, чтобы гарантировать, что система будет работать эффективно.
-
Требования к производительности и приоритету для каждой задачи в системе
Наконец, перед внедрением приложения следует указать требования к производительности для каждой задачи, а также порядок приоритета среди задач.
После перечисления приведенных выше деталей пользователь может начать со следующих шагов по реализации приложения FreeRTOS.
Шаг 1: Настройка потока инструментов для контроллера
В качестве первого шага настройте поток инструментов (tool flow) для контроллера, на котором будет выполняться приложение RTOS. Используя процесс установки, запустите базовый тест Hello world, чтобы убедиться в следующем.
- Приложение написано.
- Необходимый стартовый код для контроллера, файлы компоновщика, файлы конфигурации компоновщика и другие связанные файлы уже готовы.
- Приложение компилируется в тулчейне (toolchain) для выбранного контроллера.
- Пользователь может запустить приложение на плате или эмулировать функциональность контроллера для проверки программного обеспечения.
В качестве альтернативы пользователь может выбрать демонстрационное приложение FreeRTOS и запустить его в потоке инструментов, чтобы убедиться, что установка выполнена правильно, а затем использовать его в качестве отправной точки для разработки приложения.
Шаг 2: Включение исходных файлов FreeRTOS
Необходимые файлы
Ниже перечислены основные файлы, которые должны быть включены в любое приложение FreeRTOS:
- FreeRTOS/Source/tasks.c
- FreeRTOS/Source/queue.c
- FreeRTOS/Source/list.c
- FreeRTOS/Source/portable/[compiler]/[architecture]/port.c, где [compiler] - используемый компилятор, [architecture] - тип используемой архитектуры
- FreeRTOS/Source/portable/MemMang/heap_x.c, где x - 1, 2, 3, 4 или 5
Если каталог, содержащий файл port.c, также содержит файл на языке ассемблера, то файл на языке ассемблера также должен быть включен.
Необязательные файлы
- Если требуется функциональность программного таймера, добавьте FreeRTOS/Source/timers.c в список исходных файлов проекта.
- Если требуется функциональность группы событий, добавьте FreeRTOS/Source/event_group.c в список исходных файлов проекта.
- Если требуется поток или буфер сообщений, добавьте FreeRTOS/Source/stream_buffer.c в список исходных файлов проекта.
- Существует также функциональность сопрограмм (или корутин, coroutines), но её не рекомендуется использовать для новых разработок (эта функциональность устарела).
Шаг 3: Включение необходимых заголовочных файлов RTOS
Следующие каталоги должны быть частью пути include сценария компиляции, чтобы компилятор мог найти заголовочные файлы RTOS:
- FreeRTOS/Source/include
- FreeRTOS/Source/portable/[compiler]/[architecture]
- Директория, содержащая FreeRTOSConfig.h
В зависимости от того, на какой процессор портируется RTOS, эти пути могут потребоваться и в include пути включения ассемблера.
Шаг 4: Обновление настроек файла конфигурации FreeRTOS
Каждый проект FreeRTOS требует наличия файла конфигурации FreeRTOSConfig.h. Это файл, который определяет настройки для ядра RTOS, подстраивая ядро под конкретное создаваемое приложение.
Этот файл зависит от пользователя или приложения и должен быть размещен в области кода приложения, а не вместе с исходным кодом ядра.
Подробнее о различных настройках, доступных в этом файле, можно ознакомиться в документации FreeRTOS.
Если в ваш проект включена куча heap_1, heap_2, heap_4 или heap_5, то значение параметра configTOTAL_HEAP_SIZE будет определять размер кучи FreeRTOS. Если для configTOTAL_HEAP_SIZE задано слишком большое значение, приложение не будет связываться, поэтому нужно устанавливать разумный размер кучи.
Параметр configMINIMAL_STACK_SIZE определяет размер стека, используемого бездействующей задачей. Если для configMINIMAL_STACK_SIZE установлено слишком малое значение, бездействующие задачи будут генерировать переполнение стека. Рекомендуется скопировать параметр configMINIMAL_STACK_SIZE из официальной демонстрации FreeRTOS, предоставленной для архитектуры микроконтроллера, используемой приложением. Однако некоторые демонстрационные проекты не были обновлены и могут не иметь всех необходимых параметров конфигурации; в этих случаях пользователь должен добавить их вручную по мере необходимости.
Шаг 5: Установка необходимых векторов прерывания
Каждый порт RTOS использует как минимум один таймер. Он используется для генерации периодического тикового прерывания. В зависимости от порта могут потребоваться дополнительные таймеры для управления переключением контекста и других связанных с этим задач. Прерывания, которые требуются RTOS, обслуживаются исходным файлом RTOS port.c.
В зависимости от порта и используемого компилятора, способ установки обработчиков прерываний также различается. Пользователи могут скопировать официальное демо-приложение для используемого порта из каталогов демо-версий RTOS.
После выполнения всех вышеперечисленных шагов пользователь сможет скомпилировать приложение для выбранного им контроллера. Затем пользователь может улучшить свое приложение в соответствии со своими требованиями и запустить его на выбранном им оборудовании.