- Как работи RTOS?
- Често използвани термини в RTOS
- Инсталиране на библиотека Arduino FreeRTOS
- Електрическа схема
- Пример за Arduino FreeRTOS - Създаване на задачи за FreeRTOS в Arduino IDE
- Внедряване на задачата FreeRTOS в Arduino IDE
ОС, присъстваща във вградените устройства, се нарича RTOS (операционна система в реално време). Във вградените устройства задачите в реално време са от решаващо значение, когато времето играе много важна роля. Задачите в реално време са Детерминирани по време означава, че времето за реакция на всяко събитие е винаги постоянно, така че да може да се гарантира, че всяко конкретно събитие ще се случи в определен час. RTOS е проектиран да изпълнява приложения с много прецизно синхронизиране и висока степен на надеждност. RTOS също помага за многозадачност с едно ядро.
Вече разгледахме урок за това как да използваме RTOS във вградени системи, където можете да научите повече за RTOS, разликата между OS с общо предназначение и 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, нека видим какво е задача. Задачата е код, който може да се планира на процесора за изпълнение. Така че, ако искате да изпълните някаква задача, тя трябва да бъде насрочена, като се използва забавяне на ядрото или използване на прекъсвания. Тази работа се извършва от Scheduler, присъстващ в ядрото. В едноядрен процесор планировщикът помага на задачите да се изпълняват в определен интервал от време, но изглежда, че различни задачи се изпълняват едновременно. Всяка задача се изпълнява според приоритета, който й е даден.
Сега нека видим какво се случва в ядрото на RTOS, ако искаме да създадем задача за мигане на LED с интервал от една секунда и да поставим тази задача с най-висок приоритет.
Освен LED задачата, ще има още една задача, която се създава от ядрото, тя е известна като неактивна задача. Неактивната задача се създава, когато няма налична задача за изпълнение. Тази задача винаги работи с най-ниския приоритет, т.е. 0 приоритет. Ако анализираме графиката за синхронизация, дадена по-горе, може да се види, че изпълнението започва със светодиодна задача и тя работи за определено време, а след това за оставащото време, неактивната задача се изпълнява, докато не се появи прекъсване на отметката. Тогава ядрото решава коя задача трябва да бъде изпълнена според приоритета на задачата и общото изминало време на LED задачата. Когато завърши 1 секунда, ядрото отново избира водещата задача за изпълнение, тъй като има по-висок приоритет от неактивната задача, можем също да кажем, че светодиодната задача изпреварва неактивната задача. Ако има повече от две задачи с един и същ приоритет, те ще се изпълняват по обиколен начин за определено време.
Под диаграмата на състоянието, тъй като показва превключването на недействащата задача в работещо състояние.
Всяка новосъздадена задача отива в състояние на готовност (част от неработещо състояние). Ако създадената задача (Task1) има най-висок приоритет от другите задачи, тя ще премине в работещо състояние. Ако тази изпълняваща се задача изпревари другата задача, тя ще се върне отново в състояние на готовност. В противен случай, ако task1 е блокиран чрез използване на API за блокиране, тогава CPU няма да се ангажира с тази задача до времето за изчакване, определено от потребителя.
Ако Task1 е спрян в работещо състояние с помощта на Suspend APIs, тогава Task1 ще премине в Suspended state и той не е достъпен за планиращия отново. Ако възобновите Task1 в спряно състояние, той ще се върне в състояние на готовност, както можете да видите в блоковата диаграма.
Това е основната идея за това как Задачите се изпълняват и променят състоянията си. В този урок ще реализираме две задачи в Arduino Uno, като използваме FreeRTOS API.
Често използвани термини в RTOS
1. Задача: Това е парче код, което може да се планира на процесора за изпълнение.
2. Планировчик: Той е отговорен за избора на задача от списъка на готовите състояния към текущото състояние. Планировъците често се внедряват, така че да задържат всички компютърни ресурси (както при балансиране на натоварването).
3. Превенция: Това е актът на временно прекъсване на вече изпълняваща се задача с намерението да се премахне от текущото състояние без нейното сътрудничество.
4. Превключване на контекст: При предимство, базирано на приоритет, планировщикът сравнява приоритета на изпълняваните задачи с приоритет на готов списък със задачи при всяко прекъсване на systick . Ако в списъка има някаква задача, чийто приоритет е по-висок от изпълняваната задача, възниква превключване на контекста. По принцип в този процес съдържанието на различни задачи се запазва в съответната им стекова памет.
5. Видове политики за планиране:
- Предварително планиране: При този тип планиране задачите се изпълняват с еднакъв интервал от време, без да се вземат предвид приоритетите.
- Приоритетно основано на приоритет: Задача с висок приоритет ще се изпълни първа.
- Кооперативно планиране: Превключването на контекст ще се осъществи само при сътрудничество на изпълнявани задачи. Задачата ще се изпълнява непрекъснато, докато се извика доходността на задачата.
6. Обекти на ядрото: За сигнализиране на задачата за извършване на някаква работа се използва процесът на синхронизация. За изпълнение на този процес се използват обекти на ядрото. Някои обекти на ядрото са събития, семафори, опашки, мутекс, пощенски кутии и др. Ще видим как да използваме тези обекти в предстоящите уроци.
От горната дискусия имаме някои основни идеи за концепцията за RTOS и сега можем да реализираме проекта FreeRTOS в Arduino. И така, нека да започнем, като инсталираме библиотеки на FreeRTOS в Arduino IDE.
Инсталиране на библиотека Arduino FreeRTOS
1. Отворете Arduino IDE и отидете на Sketch -> Include Library -> Manage Libraries . Потърсете FreeRTOS и инсталирайте библиотеката, както е показано по-долу.
Можете да изтеглите библиотеката от github и да добавите.zip файла в Sketch-> Include Library -> Add.zip файл.
Сега рестартирайте IDE на Arduino. Тази библиотека предоставя примерни кодове, които също могат да бъдат намерени във Файл -> Примери -> FreeRTOS, както е показано по-долу.
Тук ще напишем кода от нулата, за да разберем работата, по-късно можете да проверите примерните кодове и да ги използвате.
Електрическа схема
По-долу е схемата за създаване на мигаща LED задача с помощта на FreeRTOS на Arduino:
Пример за Arduino FreeRTOS - Създаване на задачи за FreeRTOS в Arduino IDE
Нека видим основна структура за писане на проект FreeRTOS.
1. Първо, включете заглавния файл на Arduino FreeRTOS като
#include
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, тогава в RAM ще бъдат разпределени 400 байта пространство на стека (100 * 4 байта). Използвайте това разумно, защото Arduino Uno има само 2Kbytes RAM.
- pvParameters: Параметър за въвеждане на задача (може да бъде NULL).
- uxPriority: Приоритет на задачата (0 е най-ниският приоритет).
- pxCreatedTask: Може да се използва за предаване на манипулатор на създаваната задача. След това този манипулатор може да се използва за препращане към задачата в API извиквания, които например променят приоритета на задачата или изтриват задачата (може да бъде NULL).
Пример за създаване на задача
xTaskCreate (task1, "task1", 128, NULL, 1, NULL); xTaskCreate (task2, "task2", 128, NULL, 2, NULL);
Тук Task2 има по-висок приоритет и следователно се изпълнява първо.
4. След създаване на задачата стартирайте планировчика в void setup с помощта на vTaskStartScheduler (); API.
5. Функцията Void loop () ще остане празна, тъй като не искаме да изпълняваме никаква задача ръчно и безкрайно. Тъй като изпълнението на задачата вече се извършва от Scheduler.
6. Сега трябва да приложим функциите на задачите и да напишем логиката, която искате да изпълните вътре в тези функции. Името на функцията трябва да бъде същото като първия аргумент на xTaskCreate () API.
void task1 (void * pvParameters) { while (1) { .. ..//your logic } }
7. Повечето от кода се нуждаят от функция за забавяне, за да спрат изпълняващата се задача, но в RTOS не се препоръчва да се използва функцията Delay (), тъй като спира процесора и следователно RTOS също спира да работи. Така че FreeRTOS има API на ядрото, който блокира задачата за определено време.
vTaskDelay (const TickType_t xTicksToDelay);
Този API може да се използва за забавяне. Този API забавя задача за даден брой отметки. Действителното време, за което задачата остава блокирана, зависи от скоростта на отметка. Константният портTICK_PERIOD_MS може да се използва за изчисляване в реално време от скоростта на отметка.
Това означава, че ако искате закъснение от 200ms, просто напишете този ред
vTaskDelay (200 / портTICK_PERIOD_MS);
Така че за този урок ще използваме тези FreeRTOS API за реализиране на три задачи.
API, които ще се използват:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Задача, която трябва да бъде създадена за този урок:
- LED мига при цифров щифт 8 с честота 200ms
- LED мига при цифров щифт 7 с честота 300ms
- Отпечатвайте номера в сериен монитор с честота 500ms.
Внедряване на задачата 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); докато (1) { digitalWrite (8, HIGH); vTaskDelay (200 / портTICK_PERIOD_MS); digitalWrite (8, LOW); vTaskDelay (200 / портTICK_PERIOD_MS); } }
По същия начин внедрете функцията TaskBlink2. Функцията Task3 ще бъде записана като
void Taskprint (void * pvParameters) { int брояч = 0; докато (1) { брояч ++; Serial.println (брояч); vTaskDelay (500 / портTICK_PERIOD_MS); } }
Това е. Успешно завършихме проект FreeRTOS Arduino за Arduino Uno. Можете да намерите пълен код заедно с видеоклип в края на този урок.
И накрая, свържете два светодиода на цифровия щифт 7 и 8 и качете кода на вашата платка Arduino и отворете серийния монитор. Ще видите, че броячът се изпълнява веднъж на 500ms с име на задача, както е показано по-долу.
Също така, наблюдавайте светодиодите, те мигат през различни интервали от време. Опитайте се да играете с приоритетния аргумент във функцията xTaskCreate . Променете номера и наблюдавайте поведението на серийния монитор и светодиодите.
Сега можете да разберете първите два примерни кода, в които се създават задачи за аналогово четене и цифрово четене. По този начин можете да правите повече авансови проекти, като използвате само API на Arduino Uno и FreeRTOS.