- Hoe RTOS werkt?
- Veelgebruikte termen in RTOS
- Arduino FreeRTOS Library installeren
- Schakelschema
- Arduino FreeRTOS-voorbeeld - FreeRTOS-taken maken in Arduino IDE
- FreeRTOS-taakimplementatie in Arduino IDE
Het besturingssysteem dat aanwezig is in de ingebouwde apparaten, wordt een RTOS (Real-Time Operating System) genoemd. In embedded apparaten zijn realtime taken van cruciaal belang waarbij timing een zeer belangrijke rol speelt. Realtime taken zijn tijddeterministisch, wat betekent dat de reactietijd op elke gebeurtenis altijd constant is, zodat kan worden gegarandeerd dat een bepaalde gebeurtenis op een vast tijdstip zal plaatsvinden. RTOS is ontworpen om applicaties uit te voeren met een zeer nauwkeurige timing en een hoge mate van betrouwbaarheid. RTOS helpt ook bij multi-tasking met een enkele kern.
We hebben al een tutorial behandeld over het gebruik van RTOS in embedded systemen, waar je meer te weten kunt komen over RTOS, het verschil tussen algemene OS en RTOS, verschillende soorten RTOS, enz.
In deze tutorial beginnen we met FreeRTOS. FreeRTOS is een klasse van RTOS voor embedded apparaten die klein genoeg is om op 8/16-bit microcontrollers te draaien, hoewel het gebruik niet beperkt is tot deze microcontrollers. Het is een volledig open-source en de code is beschikbaar op github. Als we enkele basisconcepten van RTOS kennen, dan is het heel gemakkelijk om FreeRTOS te gebruiken, omdat het goed gedocumenteerde API's heeft die direct in de code kunnen worden gebruikt zonder het back-endgedeelte van de codering te kennen. De volledige FreeRTOS-documentatie is hier te vinden.
Omdat FreeRTOS op 8-bit MCU kan draaien, kan het ook op Arduino Uno-bord worden uitgevoerd. We moeten gewoon de FreeRTOS-bibliotheek downloaden en dan beginnen met het implementeren van de code met behulp van API's. Deze tutorial is bedoeld voor een complete beginner, hieronder staan de onderwerpen die we in deze Arduino FreeRTOS-tutorial zullen behandelen:
- Hoe RTOS werkt
- Enkele veelgebruikte termen in RTOS
- FreeRTOS installeren in Arduino IDE
- Hoe FreeRTOS-taken te maken met een voorbeeld
Hoe RTOS werkt?
Laten we, voordat we beginnen met werken met RTOS, eens kijken wat een taak is. Taak is een stukje code dat op de CPU kan worden uitgevoerd om uit te voeren. Dus als je een bepaalde taak wilt uitvoeren, dan moet deze worden gepland met kernelvertraging of met interrupts. Dit werk wordt gedaan door Scheduler aanwezig in de kernel. In een single-core processor helpt de planner taken uit te voeren in een bepaald tijdsegment, maar het lijkt erop dat verschillende taken tegelijkertijd worden uitgevoerd. Elke taak wordt uitgevoerd volgens de prioriteit die eraan wordt gegeven.
Laten we nu eens kijken wat er in de RTOS-kernel gebeurt als we een taak willen maken voor LED-knipperend met een interval van één seconde en deze taak op de hoogste prioriteit willen zetten.
Afgezien van de LED-taak, zal er nog een taak zijn die door de kernel wordt gemaakt, het staat bekend als een inactieve taak. De inactieve taak wordt gemaakt als er geen taak beschikbaar is voor uitvoering. Deze taak draait altijd op de laagste prioriteit, dwz 0 prioriteit. Als we de bovenstaande timinggrafiek analyseren, kan worden gezien dat de uitvoering begint met een LED-taak en deze gedurende een bepaalde tijd loopt en vervolgens voor de resterende tijd de inactieve taak wordt uitgevoerd totdat er een tikonderbreking optreedt. Vervolgens beslist de kernel welke taak moet worden uitgevoerd volgens de prioriteit van de taak en de totale verstreken tijd van de LED-taak. Wanneer 1 seconde is voltooid, kiest de kernel de geleide taak opnieuw om uit te voeren omdat deze een hogere prioriteit heeft dan de inactieve taak, we kunnen ook zeggen dat de LED-taak de inactieve taak voorrang geeft. Als er meer dan twee taken met dezelfde prioriteit zijn, worden ze gedurende een bepaalde tijd round-robin uitgevoerd.
Hieronder het toestandsdiagram omdat het het overschakelen van de niet-actieve taak naar de actieve status laat zien.
Elke nieuw gemaakte taak gaat in de status Gereed (onderdeel van de status niet actief). Als de gemaakte taak (taak1) de hoogste prioriteit heeft dan andere taken, wordt deze naar de actieve status verplaatst. Als deze lopende taak voorrang heeft op de andere taak, keert deze weer terug naar de status Gereed. Anders, als taak1 wordt geblokkeerd met behulp van een blokkeer-API, zal de CPU deze taak pas uitvoeren na de time-out die door de gebruiker is gedefinieerd.
Als Task1 wordt onderbroken in actieve status met behulp van API's voor opschorten, gaat Task1 naar de status Opgeschort en is deze niet meer beschikbaar voor de planner. Als u Task1 in de onderbroken toestand hervat, keert het terug naar de status gereed, zoals u kunt zien in het blokschema.
Dit is het basisidee van hoe taken worden uitgevoerd en hun status wijzigen. In deze tutorial zullen we twee taken in Arduino Uno implementeren met behulp van FreeRTOS API.
Veelgebruikte termen in RTOS
1. Taak: het is een stukje code dat op de CPU kan worden uitgevoerd om uit te voeren.
2. Planner: het is verantwoordelijk voor het selecteren van een taak uit de gereedstatuslijst tot de actieve toestand. Planners worden vaak geïmplementeerd zodat ze alle computerbronnen bezet houden (zoals bij taakverdeling).
3. Voorrang: het is de handeling van het tijdelijk onderbreken van een reeds uitgevoerde taak met de bedoeling deze zonder zijn medewerking uit de actieve toestand te verwijderen.
4. Contextwisseling: bij prioriteitsgebaseerde voorrang, vergelijkt de planner de prioriteit van lopende taken met een prioriteit van de lijst met gereedstaande taken op elke systick- interrupt. Als er een taak in de lijst staat met een hogere prioriteit dan een actieve taak, vindt er een contextwisseling plaats. In principe wordt in dit proces de inhoud van verschillende taken opgeslagen in hun respectievelijke stapelgeheugen.
5. Soorten planningsbeleid:
- Preventieve planning: bij dit type planning worden taken uitgevoerd met een gelijk tijdsbestek zonder rekening te houden met de prioriteiten.
- Op prioriteit gebaseerde preventieve: taak met hoge prioriteit wordt eerst uitgevoerd.
- Coöperatieve planning: Contextomschakeling gebeurt alleen met de medewerking van lopende taken. De taak wordt continu uitgevoerd totdat de taakopbrengst wordt aangeroepen.
6. Kernelobjecten: voor het signaleren van de taak om wat werk uit te voeren, wordt het synchronisatieproces gebruikt. Om dit proces uit te voeren, worden kernelobjecten gebruikt. Sommige Kernel-objecten zijn Gebeurtenissen, Semaforen, Wachtrijen, Mutex, Mailboxen, enz. We zullen zien hoe deze objecten te gebruiken in komende tutorials.
Uit de bovenstaande discussie hebben we enkele basisideeën gekregen over het RTOS-concept en nu kunnen we het FreeRTOS-project in Arduino implementeren. Laten we dus aan de slag gaan door FreeRTOS-bibliotheken in Arduino IDE te installeren.
Arduino FreeRTOS Library installeren
1. Open Arduino IDE en ga naar Sketch -> Bibliotheek opnemen -> Bibliotheken beheren . Zoek naar FreeRTOS en installeer de bibliotheek zoals hieronder weergegeven.
U kunt de bibliotheek downloaden van github en het.zip-bestand toevoegen in Sketch-> Bibliotheek opnemen ->.zip- bestand toevoegen.
Start nu de Arduino IDE opnieuw. Deze bibliotheek biedt enkele voorbeeldcode, ook die kan worden gevonden in Bestand -> Voorbeelden -> FreeRTOS zoals hieronder weergegeven.
Hier zullen we de code helemaal opnieuw schrijven om de werking te begrijpen, later kunt u de voorbeeldcodes controleren en ze gebruiken.
Schakelschema
Hieronder vindt u het schakelschema voor het maken van een knipperende LED-taak met FreeRTOS op Arduino:
Arduino FreeRTOS-voorbeeld - FreeRTOS-taken maken in Arduino IDE
Laten we een basisstructuur bekijken om een FreeRTOS-project te schrijven.
1. Voeg eerst het Arduino FreeRTOS-headerbestand toe als
# omvatten
2. Geef het functieprototype van alle functies die u aan het schrijven bent voor uitvoering die is geschreven als
void Task1 (void * pvParameters); void Task2 (void * pvParameters); .. ….
3. Maak nu in de void setup () functie taken aan en start de taakplanner.
Voor het maken van een taak wordt xTaskCreate () API aangeroepen in de setup- functie met bepaalde parameters / argumenten.
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
Er zijn 6 argumenten die moeten worden doorgegeven bij het maken van een taak. Laten we eens kijken wat deze argumenten zijn
- pvTaskCode: het is gewoon een verwijzing naar de functie die de taak implementeert (in feite alleen de naam van de functie).
- pcName: een beschrijvende naam voor de taak. Dit wordt niet gebruikt door FreeRTOS. Het wordt puur voor foutopsporingsdoeleinden meegeleverd.
- usStackDepth: Elke taak heeft zijn eigen unieke stapel die door de kernel aan de taak wordt toegewezen wanneer de taak wordt gemaakt. De waarde specificeert het aantal woorden dat de stapel kan bevatten, niet het aantal bytes. Als de stapel bijvoorbeeld 32-bits breed is en usStackDepth wordt doorgegeven als 100, wordt 400 bytes aan stapelruimte toegewezen (100 * 4 bytes) in RAM. Gebruik dit verstandig, want Arduino Uno heeft slechts 2 KB RAM.
- pvParameters: taakinvoerparameter (kan NULL zijn).
- uxPriority: prioriteit van de taak (0 is de laagste prioriteit).
- pxCreatedTask: Het kan worden gebruikt om een handvat uit te geven aan de taak die wordt gemaakt. Deze handle kan vervolgens worden gebruikt om naar de taak te verwijzen in API-aanroepen die bijvoorbeeld de taakprioriteit wijzigen of de taak verwijderen (kan NULL zijn).
Voorbeeld van het maken van taken
xTaskCreate (task1, "task1", 128, NULL, 1, NULL); xTaskCreate (task2, "task2", 128, NULL, 2, NULL);
Hier heeft Task2 een hogere prioriteit en wordt daarom als eerste uitgevoerd.
4. Start na het aanmaken van de taak de planner in een lege opstelling met vTaskStartScheduler (); API.
5. De functie Void loop () blijft leeg omdat we geen enkele taak handmatig en oneindig willen uitvoeren. Omdat de taakuitvoering nu wordt afgehandeld door Scheduler.
6. Nu moeten we taakfuncties implementeren en de logica schrijven die u binnen deze functies wilt uitvoeren. De functienaam moet hetzelfde zijn als het eerste argument van xTaskCreate () API.
void task1 (void * pvParameters) { while (1) { .. ..//your logic } }
7. De meeste code heeft een vertragingsfunctie nodig om de lopende taak te stoppen, maar in RTOS wordt niet aangeraden om de functie Delay () te gebruiken omdat het de CPU stopt en dus ook RTOS stopt met werken. Dus FreeRTOS heeft een kernel-API om de taak voor een bepaalde tijd te blokkeren.
vTaskDelay (const TickType_t xTicksToDelay);
Deze API kan worden gebruikt voor vertragingsdoeleinden. Deze API vertraagt een taak voor een bepaald aantal ticks. De daadwerkelijke tijd dat de taak geblokkeerd blijft, is afhankelijk van de tick rate. De constante portTICK_PERIOD_MS kan worden gebruikt om real-time te berekenen op basis van de tick rate.
Dit betekent dat als je een vertraging van 200 ms wilt, je gewoon deze regel schrijft
vTaskDelay (200 / portTICK_PERIOD_MS);
Dus voor deze tutorial zullen we deze FreeRTOS API's gebruiken om drie taken te implementeren.
Te gebruiken API's:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Taak die moet worden gemaakt voor deze tutorial:
- LED knippert op digitale pin 8 met een frequentie van 200 ms
- LED knippert op digitale pin 7 met een frequentie van 300 ms
- Druk nummers af op een seriële monitor met een frequentie van 500 ms.
FreeRTOS-taakimplementatie in Arduino IDE
1. Voeg uit de bovenstaande basisstructuurverklaring het Arduino FreeRTOS-headerbestand toe. Maak vervolgens functieprototypes. Omdat we drie taken hebben, moeten we dus drie functies maken en zijn prototypes.
#include void TaskBlink1 (void * pvParameters); void TaskBlink2 (void * pvParameters); void Taskprint (void * pvParameters);
2. Initialiseer in de void setup () -functie seriële communicatie met 9600 bits per seconde en maak alle drie de taken met behulp van de xTaskCreate () API. Stel in eerste instantie de prioriteiten van alle taken in op '1' en start de planner.
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. Implementeer nu alle drie de functies zoals hieronder weergegeven voor taak1 LED knippert.
void TaskBlink1 (void * pvParameters) { pinMode (8, OUTPUT); while (1) { digitalWrite (8, HIGH); vTaskDelay (200 / portTICK_PERIOD_MS); digitalWrite (8, LOW); vTaskDelay (200 / portTICK_PERIOD_MS); } }
Implementeer op dezelfde manier de TaskBlink2-functie. De functie Task3 wordt geschreven als
void Taskprint (void * pvParameters) { int counter = 0; while (1) { counter ++; Serial.println (teller); vTaskDelay (500 / portTICK_PERIOD_MS); } }
Dat is het. We hebben met succes een FreeRTOS Arduino- project voor Arduino Uno afgerond. Aan het einde van deze tutorial vindt u de volledige code en een video.
Sluit ten slotte twee LED's aan op de digitale pin 7 en 8 en upload de code naar je Arduino-bord en open de seriële monitor. U zult zien dat een teller eenmaal per 500 ms loopt met de taaknaam, zoals hieronder weergegeven.
Let ook op de LED's, ze knipperen met verschillende tijdsintervallen. Probeer te spelen met het prioriteitsargument in de xTaskCreate- functie. Wijzig het nummer en observeer het gedrag op de seriële monitor en LED's.
Nu kunt u de eerste twee voorbeeldcodes begrijpen waarin analoge lees- en digitale leestaken worden gemaakt. Op deze manier kunt u meer geavanceerde projecten maken met alleen Arduino Uno en FreeRTOS API's.