Использование мультизадачности FreeRTOS на Arduino

Добавлено 30 ноября 2018 в 08:57

О проекте

В Arduino IDE имеется множество доступных драйверов и библиотек, но среда Arduino ограничена только setup() и loop() и эффективно не поддерживает многозадачность.

Рассмотрим простую, легкую в использовании и надежную реализацию FreeRTOS, которую можно вставить в Arduino IDE в виде библиотеки, и которая позволяет беспрепятственно использовать лучшие части обоих сред.

Использование мультизадачности FreeRTOS в Arduino
Использование мультизадачности FreeRTOS в Arduino

Происхождение

Большинство операционных систем позволяют одновременно выполнять несколько программ или потоков. Это называется многозадачностью. На самом деле, каждое ядро процессора в любой заданный момент времени может запускать только одну программу. Часть операционной системы, называемая планировщиком, отвечает за принятие решения о том, какая программа должна выполняться, и обеспечивает иллюзию одновременного выполнения путем быстрого переключения между программами.

Планировщик в операционный системе реального времени (RTOS) предназначен для обеспечения предсказуемого (обычно описываемого как детерминированного) шаблона выполнения. Это особенно интересно для встраиваемых систем, таких как устройства Arduino, поскольку к встраиваемым системам часто предъявляются требования реального времени.

Традиционные планировщики реального времени, такие как планировщик, используемый во FreeRTOS, достигают детерминизма, позволяя пользователю назначать приоритет для каждого потока выполнения. Затем планировщик использует этот приоритет, чтобы узнать, как поток должен выполниться следующим. Во FreeRTOS поток выполнения называется задачей Task.

Давайте начнем

Во-первых, в менеджере библиотек Arduino IDE, начиная с версии 1.6.8, найдите библиотеку FreeRTOS под типом «Contributed» («Внесены») и темой «Timing» («Расчет времени»).

Поиск в менеджере библиотек Arduino
Поиск в менеджере библиотек Arduino

Убедитесь, что установлен последний релиз библиотеке FreeRTOS. В данном случае это v10.1.0-1.

FreeRTOS v8.2.3 Release 6 истановлена
FreeRTOS v8.2.3 Release 6 истановлена

Затем подключите библиотеку FreeRTOS либо через меню Скетч → Подключить библиотеку, либо добавьте следующую строку в начале скетча:

#include <Arduino_FreeRTOS.h>

Скомпилируйте и загрузите этот пустой скетч (с FreeRTOS) на устройство Arduino Uno/Yun/Leonardo/Mega. Это покажет вам, сколько флэш памяти потребляется планировщиком FreeRTOS. При тестировании с Arduino IDE v1.6.9 на Windows 10 было получено следующее:

Размер флэш-памяти, занимаемой FreeRTOS на разных платах Arduino
УстройствоПустой скетч только с loop()Пустой скетч с FreeRTOSДополнительный занимаемый объем памяти программ
Uno444701820%
Goldilocks50270865%
Leonardo36181016623%
Yun36121016023%
Mega65670862%

На этом этапе FreeRTOS уже запущена на вашем устройстве.

Следующие шаги

Теперь загрузите и протестируйте скетч Blink, используя операционную систему реального времени, просто вставив #include <Arduino_FreeRTOS.h> в начало скетча. Это всё, что нужно, чтобы FreeRTOS работала в ваших скетчах.

Следующим шагом будет изучение возможностей, предоставляемых профессиональной RTOS в Arduino IDE.

Blink_AnalogRead.ino – это хороший способ начать, поскольку он объединяет два базовых примера Arduino, Blink и AnalogRead, в один скетч с двумя отдельными задачами Task. Обе задачи выполняют свою работу, управляемые планировщиком FreeRTOS. Данный скетч может быть найден через меню Файл → Примеры → FreeRTOS.

#include <Arduino_FreeRTOS.h>

// объявить две задачи для мигания Blink и чтения аналогового входа AnalogRead
void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );

// функция setup запускается единожды, когда вы нажимаете reset или включаете плату
void setup() 
{

  // Теперь устанавливаем задачи для независимого запуска.
  xTaskCreate(
    TaskBlink
    ,  (const portCHAR *)"Blink"   // Название только для людей
    ,  128  // размер стека
    ,  NULL
    ,  2    // приоритет
    ,  NULL );

  xTaskCreate(
    TaskAnalogRead
    ,  (const portCHAR *) "AnalogRead"
    ,  128 // этот размер стека может быть провере и подстроен с помощью чтения Highwater
    ,  NULL
    ,  1   // приоритет
    ,  NULL );

  // Теперь планировщик задач, берущий управление над планированием отдельных задач, 
  // запускается автоматически.
}

void loop()
{
  // Пусто. Всё выполняется в задачах.
}

/*---------------------------------------------------*/
/*---------------------- Задачи ---------------------*/
/*---------------------------------------------------*/

void TaskBlink(void *pvParameters)  // Это задача.
{
  (void) pvParameters;

  // настроить цифровой вывод 13 на выход.
  pinMode(13, OUTPUT);

  for (;;) //  задача должна никогда не прекращаться или прерываться
  {
    digitalWrite(13, HIGH);   // включить светодиод (HIGH – это уровень напряжения)
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); // ждать одну секунду
    digitalWrite(13, LOW);    // выключить светодиод, установив напряжение LOW
    vTaskDelay( 1000 / portTICK_PERIOD_MS ); // ждать одну секунду
  }
}

void TaskAnalogRead(void *pvParameters)  // Это задача.
{
  (void) pvParameters;

  // инициализировать последовательный порт на скорость 9600 бит/секунда:
  Serial.begin(9600);

  for (;;)
  {
    // прочитать вход на аналоговом выводе 0:
    int sensorValue = analogRead(A0);
    // напечатать прочитанное значение:
    Serial.println(sensorValue);
    vTaskDelay(1);  // задержка один тик (15 мс) между чтениями (для стабильности)
  }
}

Если вас интересуют устройства с малым энергопотреблением или работающие от аккумуляторов, то FreeRTOS легко использовать для поддержки режимов снижения энергопотребления AVR ATmega.

Следующие статьи буду посвящены использованию семафоров (Semaphore) для защиты аппаратных ресурсов (например, последовательного порта), очередей (Queue) для передачи данных между задачами (Task) или таймеров (Timer) для управления точными задержками и таймаутами.


На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.


Сообщить об ошибке