- Як працює RTOS?
- Терміни, що часто використовуються в RTOS
- Встановлення бібліотеки Arduino FreeRTOS
- Кругова діаграма
- Приклад Arduino FreeRTOS - Створення завдань FreeRTOS в Arduino IDE
- Впровадження завдання FreeRTOS в Arduino IDE
ОС, що знаходиться всередині вбудованих пристроїв, називається RTOS (операційна система реального часу). У вбудованих пристроях завдання в режимі реального часу є критично важливими, коли час відіграє дуже важливу роль. Завдання в режимі реального часу є детермінованими за часом: час відгуку на будь-яку подію завжди є постійним, так що можна гарантувати, що будь-яка конкретна подія відбудеться у визначений час. RTOS призначений для запуску програм з дуже точним синхронізацією та високим ступенем надійності. RTOS також допомагає в багатозадачності з одним ядром.
Ми вже розглядали підручник про те, як використовувати RTOS у вбудованих системах, де ви можете дізнатись більше про RTOS, різницю між ОС загального призначення та RTOS, різні типи RTOS тощо.
У цьому посібнику ми почнемо з FreeRTOS. FreeRTOS - це клас RTOS для вбудованих пристроїв, який досить малий, щоб працювати на 8/16-бітних мікроконтролерах, хоча його використання не обмежується цими мікроконтролерами. Це повністю відкритий код, і його код доступний на github. Якщо ми знаємо деякі основні поняття RTOS, то дуже легко використовувати FreeRTOS, оскільки він має добре задокументовані API, які можна безпосередньо використовувати в коді, не знаючи внутрішньої частини кодування. Повну документацію щодо FreeRTOS можна знайти тут.
Оскільки FreeRTOS може працювати на 8-розрядному MCU, то він також може працювати на платі Arduino Uno. Нам потрібно просто завантажити бібліотеку FreeRTOS, а потім розпочати впровадження коду за допомогою API. Цей підручник призначений для початківців, нижче наведено теми, які ми розглянемо у цьому посібнику з Arduino FreeRTOS:
- Як працює RTOS
- Деякі часто вживані терміни в RTOS
- Встановлення FreeRTOS в Arduino IDE
- Як створити завдання FreeRTOS на прикладі
Як працює RTOS?
Перш ніж розпочати роботу з RTOS, давайте подивимося, що таке Завдання. Завдання - це фрагмент коду, який можна запланувати на ЦП для виконання. Отже, якщо ви хочете виконати якесь завдання, його слід запланувати за допомогою затримки ядра або використання переривань. Цю роботу виконує Планувальник, присутній у ядрі. В одноядерному процесорі планувальник допомагає виконувати завдання за певний зріз часу, але, схоже, різні завдання виконуються одночасно. Кожне завдання виконується відповідно до пріоритету, який йому надано.
Тепер давайте подивимося, що відбувається в ядрі RTOS, якщо ми хочемо створити завдання для мигання світлодіодів з інтервалом в одну секунду і поставити це завдання на найвищий пріоритет.
Окрім світлодіодного завдання, буде ще одне завдання, яке створюється ядром, воно відоме як неактивне завдання. Неактивне завдання створюється, коли жодне завдання не доступне для виконання. Це завдання завжди виконується з найнижчим пріоритетом, тобто 0 пріоритетом. Якщо ми проаналізуємо графік синхронізації, наведений вище, можна побачити, що виконання починається зі світлодіодного завдання, і воно виконується протягом певного часу, а протягом часу, що залишився, виконується, поки не відбувається переривання галочки. Потім ядро вирішує, яке завдання має бути виконане, відповідно до пріоритету завдання та загального часу, який минув завдання LED. Коли закінчиться 1 секунда, ядро знову вибирає завдання під керівництвом для виконання, оскільки воно має вищий пріоритет, ніж завдання в режимі очікування, ми також можемо сказати, що завдання світлодіодів випереджає завдання в режимі очікування. Якщо є більше двох завдань з однаковим пріоритетом, тоді вони будуть виконуватися круговим способом протягом певного часу.
Нижче діаграми стану, оскільки вона показує перемикання не запущеного завдання в робочий стан.
Кожне новостворене завдання переходить у стан готовності (частина не запущеного стану). Якщо створене завдання (Завдання 1) має найвищий пріоритет, ніж інші завдання, тоді воно переходить у робочий стан. Якщо це запущене завдання випереджує інше, воно знову повернеться до стану готовності. В іншому випадку, якщо task1 заблоковано за допомогою API блокування, тоді процесор не буде взаємодіяти з цим завданням до часу очікування, визначеного користувачем.
Якщо Task1 призупинено в робочому стані за допомогою API призупинення, тоді Task1 перейде в призупинений стан, і він знову не буде доступний планувальнику. Якщо ви відновите Task1 у призупиненому стані, він повернеться у готовий стан, як ви можете бачити на блок-схемі.
Це основна ідея того, як Завдання запускаються та змінюють свої стани. У цьому посібнику ми реалізуємо два завдання в Arduino Uno за допомогою API FreeRTOS.
Терміни, що часто використовуються в RTOS
1. Завдання: Це фрагмент коду, який можна запланувати на ЦП для виконання.
2. Планувальник: Він відповідає за вибір завдання зі списку готових станів до робочого стану. Планувальники часто впроваджуються, щоб вони зайняли всі комп'ютерні ресурси (як при балансуванні навантаження).
3. Попередження: Це акт тимчасового переривання вже виконуваного завдання з наміром вивести його з робочого стану без його співпраці.
4. Перемикання контексту: При випуску на основі пріоритетів планувальник порівнює пріоритет виконуваних завдань з пріоритетом готового списку завдань на кожному перериванні систику . Якщо в списку є якесь завдання, пріоритет якого вищий за запущене, тоді відбувається перемикання контексту. В основному в цьому процесі вміст різних завдань зберігається у відповідній пам'яті стека.
5. Типи політик планування:
- Попереджувальне планування: У цьому типі планування завдання виконуються з однаковим часовим інтервалом без урахування пріоритетів.
- Пріоритет на основі пріоритетів: Завдання з високим пріоритетом виконується першим.
- Планування співпраці: Переключення контексту відбуватиметься лише за умови співпраці запущених завдань. Завдання буде виконуватися безперервно, доки не буде викликано вихід результату.
6. Об’єкти ядра: Для сигналізації завдання про виконання якоїсь роботи використовується процес синхронізації. Для виконання цього процесу використовуються об'єкти ядра. Деякі об’єкти ядра - це події, семафори, черги, мутекс, поштові скриньки тощо. Ми побачимо, як використовувати ці об’єкти у наступних навчальних посібниках.
З наведеного вище обговорення ми отримали кілька основних ідей щодо концепції RTOS, і тепер ми можемо реалізувати проект FreeRTOS в Arduino. Отже, почнемо з встановлення бібліотек FreeRTOS в Arduino IDE.
Встановлення бібліотеки Arduino FreeRTOS
1. Відкрийте Arduino IDE і перейдіть до Ескіз -> Включити бібліотеку -> Керування бібліотеками . Шукайте FreeRTOS та встановлюйте бібліотеку, як показано нижче.
Ви можете завантажити бібліотеку з github і додати.zip-файл у Sketch-> Include Library -> Add.zip- файл.
Тепер перезапустіть IDE Arduino. Ця бібліотека містить приклад коду, який також можна знайти у меню Файл -> Приклади -> FreeRTOS, як показано нижче.
Тут ми напишемо код з нуля, щоб зрозуміти роботу, пізніше ви зможете перевірити приклади кодів і використовувати їх.
Кругова діаграма
Нижче наведена принципова схема для створення миготливого світлодіодного завдання за допомогою FreeRTOS на Arduino:
Приклад Arduino FreeRTOS - Створення завдань FreeRTOS в Arduino IDE
Давайте побачимо базову структуру для написання проекту FreeRTOS.
1. По-перше, включіть файл заголовка Arduino FreeRTOS як
#включати
2. Надайте прототип функції всіх функцій, які ви пишете для виконання, які записуються як
void Task1 (void * pvParameters); void Task2 (void * pvParameters); .. ...
3. Тепер, у функції void setup () , створіть завдання та запустіть планувальник завдань.
Для створення завдання у функції налаштування із певними параметрами / аргументами викликається API xTaskCreate () .
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
Існує 6 аргументів, які слід передавати під час створення будь-якого завдання. Давайте подивимось, що це за аргументи
- pvTaskCode: Це просто вказівник на функцію, яка реалізує завдання (фактично, лише ім'я функції).
- pcName: описова назва завдання. Це не використовується FreeRTOS. Він включений виключно для налагодження.
- usStackDepth: Кожне завдання має власний унікальний стек, який виділяється ядром для завдання при створенні завдання. Значення визначає кількість слів, які може містити стек, а не кількість байтів. Наприклад, якщо стек шириною 32 біти, а usStackDepth передано як 100, тоді в ОЗП буде виділено 400 байт простору стека (100 * 4 байти). Використовуйте це з розумом, оскільки Arduino Uno має лише 2 Кбайт оперативної пам'яті.
- pvParameters: вхідний параметр завдання (може бути NULL).
- uxPriority: Пріоритет завдання (0 - найнижчий пріоритет).
- pxCreatedTask: Він може використовуватися для передачі дескриптора завдання, яке створюється. Потім цей дескриптор можна використовувати для посилання на завдання у викликах API, які, наприклад, змінюють пріоритет завдання або видаляють завдання (може бути NULL).
Приклад створення завдання
xTaskCreate (task1, "task1", 128, NULL, 1, NULL); xTaskCreate (task2, "task2", 128, NULL, 2, NULL);
Тут Завдання 2 має вищий пріоритет і, отже, виконується першим.
4. Після створення завдання запустіть планувальник у програмі void, використовуючи vTaskStartScheduler (); API.
5. Функція Void loop () залишатиметься порожньою, оскільки ми не хочемо запускати жодне завдання вручну та нескінченно. Оскільки виконанням завдань зараз займається Планувальник.
6. Тепер ми повинні реалізувати функції завдань і записати логіку, яку ви хочете виконати всередині цих функцій. Ім'я функції має збігатися з першим аргументом API xTaskCreate () .
void task1 (void * pvParameters) { while (1) { .. ..//your logic } }
7. Більшості кодів потрібна функція затримки для зупинки запущеного завдання, але в RTOS не рекомендується використовувати функцію Delay (), оскільки вона зупиняє центральний процесор, а отже, RTOS також перестає працювати. Тож FreeRTOS має API ядра для блокування завдання на певний час.
vTaskDelay (const TickType_t xTicksToDelay);
Цей API можна використовувати для затримки. Цей API затримує завдання для заданої кількості галочок. Фактичний час, протягом якого завдання залишається заблокованим, залежить від швидкості галочок. Постійний портTICK_PERIOD_MS може бути використаний для обчислення реального часу за частотою тиків .
Це означає, що якщо ви хочете затримку 200 мс, просто напишіть цей рядок
vTaskDelay (200 / портTICK_PERIOD_MS);
Отже, для цього підручника ми використаємо ці FreeRTOS API для реалізації трьох завдань.
Використовувані API:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Завдання, яке потрібно створити для цього підручника:
- Світлодіод блимає на цифровому виводі 8 з частотою 200 мс
- Світлодіод блимає на цифровому штифті 7 з частотою 300 мс
- Друк номерів на послідовному моніторі з частотою 500 мс.
Впровадження завдання FreeRTOS в Arduino IDE
1. З наведеного вище пояснення базової структури включіть файл заголовка Arduino FreeRTOS. Потім створіть прототипи функцій. Оскільки ми маємо три завдання, так складіть три функції і це прототипи.
#include void TaskBlink1 (void * pvParameters); void TaskBlink2 (void * pvParameters); void Taskprint (void * pvParameters);
2. У функції void setup () ініціалізуйте послідовний зв’язок із частотою 9600 біт на секунду та створіть усі три завдання за допомогою API xTaskCreate () . Спочатку визначте пріоритети всіх завдань як "1" і запустіть планувальник.
void setup () { Serial.begin (9600); xTaskCreate (TaskBlink1, "Task1", 128, NULL, 1, NULL); xTaskCreate (TaskBlink2, "Task2", 128, NULL, 1, NULL); xTaskCreate (Taskprint, "Task3", 128, NULL, 1, NULL); vTaskStartScheduler (); }
3. Тепер реалізуйте всі три функції, як показано нижче, для мигання світлодіода task1.
void TaskBlink1 (void * pvParameters) { pinMode (8, OUTPUT); while (1) { digitalWrite (8, HIGH); vTaskDelay (200 / портTICK_PERIOD_MS); digitalWrite (8, LOW); vTaskDelay (200 / портTICK_PERIOD_MS); } }
Подібним чином реалізуйте функцію TaskBlink2. Функція Task3 буде записана як
void Taskprint (void * pvParameters) { int counter = 0; while (1) { counter ++; Serial.println (лічильник); vTaskDelay (500 / портTICK_PERIOD_MS); } }
Це воно. Ми успішно завершили проект FreeRTOS Arduino для Arduino Uno. Ви можете знайти повний код разом із відео в кінці цього підручника.
Нарешті, підключіть два світлодіоди до цифрових контактів 7 і 8 і завантажте код на свою плату Arduino і відкрийте послідовний монітор. Ви побачите, що лічильник працює раз на 500 мс з назвою завдання, як показано нижче.
Також спостерігайте за світлодіодами, вони блимають через різні проміжки часу. Спробуйте пограти з пріоритетним аргументом у функції xTaskCreate . Змініть номер і спостерігайте за поведінкою послідовного монітора та світлодіодів.
Тепер ви можете зрозуміти перші два приклади кодів, в яких створюються завдання аналогового читання та цифрового читання. Таким чином, ви можете робити більше авансових проектів, використовуючи лише API Arduino Uno та FreeRTOS.