- Hvordan fungerer RTOS?
- Ofte brukte termer i RTOS
- Installere Arduino FreeRTOS-bibliotek
- Kretsdiagram
- Arduino FreeRTOS Eksempel - Opprette FreeRTOS-oppgaver i Arduino IDE
- FreeRTOS oppgaveimplementering i Arduino IDE
Operativsystemet som er tilstede i de innebygde enhetene, kalles et RTOS (sanntidsoperativsystem). I innebygde enheter er sanntidsoppgaver kritiske der timing spiller en veldig viktig rolle. Sanntidsoppgaver er tidsbestemmende betyr at responstiden på en hendelse alltid er konstant, slik at det kan garanteres at en bestemt hendelse vil inntreffe på et fast tidspunkt. RTOS er designet for å kjøre applikasjoner med veldig presis timing og høy grad av pålitelighet. RTOS hjelper også i multi-tasking med en enkelt kjerne.
Vi har allerede dekket en veiledning om hvordan du bruker RTOS i innebygde systemer der du kan vite mer om RTOS, forskjellen mellom OS og RTOS for generelle formål, forskjellige typer RTOS osv.
I denne opplæringen starter vi med FreeRTOS. FreeRTOS er en klasse av RTOS for innebygde enheter som er liten nok til å kjøres på 8/16-biters mikrokontrollere, selv om bruken ikke er begrenset til disse mikrokontrollerne. Det er en helt åpen kildekode, og koden er tilgjengelig på github. Hvis vi kjenner noen grunnleggende konsepter i RTOS, er det veldig enkelt å bruke FreeRTOS fordi den har veldokumenterte API-er som kan brukes direkte i koden uten å kjenne backend-delen av kodingen. Komplett FreeRTOS-dokumentasjon finner du her.
Da FreeRTOS kan kjøres på 8-biters MCU, kan den også kjøres på Arduino Uno-kort. Vi må bare laste ned FreeRTOS-biblioteket og deretter begynne å implementere koden ved hjelp av API-er. Denne opplæringen er ment for en komplett nybegynner, nedenfor er emnene vi vil dekke i denne Arduino FreeRTOS-opplæringen:
- Hvordan RTOS fungerer
- Noen ofte brukte termer i RTOS
- Installere FreeRTOS i Arduino IDE
- Hvordan lage FreeRTOS-oppgaver med eksempel
Hvordan fungerer RTOS?
Før vi begynner med RTOS-arbeid, la oss se hva som er en oppgave. Oppgave er et stykke kode som kan planlegges på prosessoren å utføre. Så hvis du vil utføre en oppgave, bør den planlegges ved hjelp av kjerneforsinkelse eller ved hjelp av avbrudd. Dette arbeidet utføres av Scheduler til stede i kjernen. I en enkeltkjerneprosessor hjelper planleggeren oppgaver å utføre i en bestemt tidsperiode, men det virker som om forskjellige oppgaver utføres samtidig. Hver oppgave løper i henhold til den prioritet som er gitt den.
La oss nå se hva som skjer i RTOS-kjernen hvis vi ønsker å lage en oppgave for LED som blinker med et sekund-intervall og setter denne oppgaven på høyeste prioritet.
Bortsett fra LED-oppgaven, vil det være en annen oppgave som opprettes av kjernen, den er kjent som en inaktiv oppgave. Tomgangsoppgaven opprettes når ingen oppgaver er tilgjengelige for utføring. Denne oppgaven kjører alltid på laveste prioritet, dvs. 0 prioritet. Hvis vi analyserer timinggrafen som er gitt ovenfor, kan det sees at utførelse starter med en LED-oppgave, og den kjører i en spesifisert tid og deretter for gjenværende tid, går tomgangsoppgaven til en kryssavbrudd oppstår. Deretter bestemmer kjernen hvilken oppgave som skal utføres i henhold til oppgavens prioritet og total forløpt tid for LED-oppgaven. Når 1 sekund er fullført, velger kjernen ledet oppgave igjen for å utføre fordi den har høyere prioritet enn inaktiv oppgave, vi kan også si at LED-oppgaven forhindrer inaktiv oppgave. Hvis det er mer enn to oppgaver med samme prioritet, vil de kjøre på en robin-måte i en bestemt tid.
Under tilstandsdiagrammet, da det viser bytte av den ikke-kjørende oppgaven til kjører tilstand.
Hver nyopprettede oppgave går i Klar-tilstand (del av tilstand som ikke kjører). Hvis den opprettede oppgaven (Oppgave1) har høyest prioritet enn andre oppgaver, vil den gå over til å kjøre tilstand. Hvis denne løpende oppgaven forhindrer den andre oppgaven, vil den gå tilbake til klar tilstand igjen. Ellers hvis oppgave 1 er blokkert ved å bruke blokkerende API, vil ikke CPU engasjere seg i denne oppgaven før tidsavbruddet som er definert av brukeren.
Hvis Oppgave1 er suspendert i kjørende tilstand ved hjelp av Suspend APIer, vil Oppgave1 gå til Suspendert tilstand, og den er ikke tilgjengelig for planleggeren igjen. Hvis du gjenopptar Oppgave 1 i suspendert tilstand, vil den gå tilbake til klar tilstand som du kan se i blokkdiagrammet.
Dette er den grunnleggende ideen om hvordan oppgaver kjører og endrer deres tilstand. I denne opplæringen vil vi implementere to oppgaver i Arduino Uno ved hjelp av FreeRTOS API.
Ofte brukte termer i RTOS
1. Oppgave: Det er et stykke kode som kan planlegges på prosessoren å utføre.
2. Planlegger: Den er ansvarlig for å velge en oppgave fra listen over klar tilstand til den kjørende tilstanden. Planleggere implementeres ofte, slik at de holder alle datamaskinsressurser opptatt (som i lastbalansering).
3. Innløsning: Det er en handling som midlertidig avbryter en allerede utførende oppgave med den hensikt å fjerne den fra den løpende staten uten dens samarbeid.
4. Kontekstbytte: I prioritetsbasert forhåndsinnsamling sammenligner planleggeren prioriteten til å kjøre oppgaver med en prioritet som klar oppgaveliste på hver systickavbrudd . Hvis det er noen oppgaver i listen som har høyere prioritet enn å kjøre oppgave, skjer kontekstsvitsj. I utgangspunktet blir innhold i forskjellige oppgaver lagret i deres respektive stackminne.
5. Typer planleggingsretningslinjer:
- Forebyggende planlegging: I denne typen planlegging kjøres oppgaver med samme tidsdel uten å ta hensyn til prioriteringene.
- Prioritetsbasert forebyggende: Oppgave med høy prioritet kjøres først.
- Samarbeidsplanlegging: Kontekstbytte vil bare skje med samarbeid om løpende oppgaver. Oppgaven vil kjøre kontinuerlig til oppgaveutbyttet kalles.
6. Kernel Objects: For å signalisere oppgaven om å utføre noe arbeid, brukes synkroniseringsprosessen. For å utføre denne prosessen brukes kjerneartikler. Noen kjernobjekter er hendelser, semaforer, køer, Mutex, postkasser osv. Vi vil se hvordan du bruker disse objektene i kommende opplæringsprogrammer.
Fra diskusjonen ovenfor har vi noen grunnleggende ideer om RTOS-konseptet, og nå kan vi implementere FreeRTOS-prosjektet i Arduino. Så la oss komme i gang med å installere FreeRTOS-biblioteker i Arduino IDE.
Installere Arduino FreeRTOS-bibliotek
1. Åpne Arduino IDE og gå til Skisse -> Inkluder bibliotek -> Administrer biblioteker . Søk etter FreeRTOS og installer biblioteket som vist nedenfor.
Du kan laste ned biblioteket fra github og legge til.zip-filen i Sketch-> Inkluder bibliotek -> Legg til.zip- fil.
Start Arduino IDE på nytt. Dette biblioteket gir noen eksempler på kode, også som du finner i Fil -> Eksempler -> FreeRTOS som vist nedenfor.
Her vil vi skrive koden fra bunnen av for å forstå funksjonen, senere kan du sjekke eksemplets koder og bruke dem.
Kretsdiagram
Nedenfor er kretsskjemaet for å lage Blinkende LED-oppgave ved bruk av FreeRTOS på Arduino:
Arduino FreeRTOS Eksempel - Opprette FreeRTOS-oppgaver i Arduino IDE
La oss se en grunnleggende struktur for å skrive et FreeRTOS-prosjekt.
1. Først må du ta med Arduino FreeRTOS header-fil som
#inkludere
2. Gi funksjonsprototypen til alle funksjonene du skriver for utførelse som er skrevet som
ugyldig Oppgave1 (ugyldig * pvParameters); ugyldig Oppgave2 (ugyldig * pvParameters); .. ….
3. Nå, i ugyldig oppsett () -funksjon, oppretter du oppgaver og starter oppgaveplanleggeren.
For å opprette oppgave kalles xTaskCreate () API i oppsettfunksjon med visse parametere / argumenter.
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
Det er 6 argumenter som skal sendes mens du oppretter en hvilken som helst oppgave. La oss se hva disse argumentene er
- pvTaskCode: Det er rett og slett en peker til funksjonen som implementerer oppgaven (faktisk bare navnet på funksjonen).
- pcName: Et beskrivende navn for oppgaven. Dette brukes ikke av FreeRTOS. Den er inkludert kun for feilsøkingsformål.
- usStackDepth: Hver oppgave har sin egen unike stabel som tildeles av kjernen til oppgaven når oppgaven er opprettet. Verdien angir antall ord stabelen kan inneholde, ikke antall byte. For eksempel, hvis stakken er 32-bits bred og usStackDepth sendes inn som 100, vil 400 byte med stabelplass bli tildelt (100 * 4 byte) i RAM. Bruk dette med omhu fordi Arduino Uno bare har 2 kB RAM.
- pvParameters: Oppgaveparameter (kan være NULL).
- uxPriority: Oppgavens prioritet (0 er den laveste prioriteten).
- pxCreatedTask: Den kan brukes til å formidle et håndtak til oppgaven som blir opprettet. Dette håndtaket kan deretter brukes til å referere til oppgaven i API-anrop som for eksempel endrer oppgaveprioriteten eller sletter oppgaven (kan være NULL).
Eksempel på oppgaveopprettelse
xTaskCreate (oppgave1, "oppgave1", 128, NULL, 1, NULL); xTaskCreate (oppgave2, "oppgave2", 128, NULL, 2, NULL);
Her har Task2 høyere prioritet og kjøres derfor først.
4. Etter at oppgaven er opprettet, starter du planleggeren i et ugyldig oppsett ved hjelp av vTaskStartScheduler (); API.
5. Void loop () -funksjonen forblir tom da vi ikke vil kjøre noen oppgaver manuelt og uendelig. Fordi oppgaveutførelse nå håndteres av Scheduler.
6. Nå må vi implementere oppgavefunksjoner og skrive logikken du vil utføre i disse funksjonene. Funksjonsnavnet skal være det samme som det første argumentet til xTaskCreate () API.
ugyldig oppgave1 (ugyldig * pvParameters) { mens (1) { .. ..//logikken din } }
7. Det meste av koden trenger forsinkelsesfunksjon for å stoppe den løpende oppgaven, men i RTOS foreslås det ikke å bruke Delay () -funksjonen da den stopper CPU og dermed slutter RTOS å fungere. Så FreeRTOS har en kjerne-API for å blokkere oppgaven i en bestemt tid.
vTaskDelay (const TickType_t xTicksToDelay);
Denne API-en kan brukes til forsinkelsesformål. Denne API-en forsinker en oppgave for et gitt antall flått. Den faktiske tiden oppgaven forblir sperret for, avhenger av kryssfrekvensen. Den konstante portenTICK_PERIOD_MS kan brukes til å beregne sanntid fra kryssraten .
Dette betyr at hvis du vil ha en forsinkelse på 200 ms, er det bare å skrive denne linjen
vTaskDelay (200 / portTICK_PERIOD_MS);
Så for denne opplæringen vil vi bruke disse FreeRTOS APIene til å implementere tre oppgaver.
APIer som skal brukes:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Oppgave som skal opprettes for denne opplæringen:
- LED blinker ved Digital pin 8 med 200 ms frekvens
- LED blinker ved Digital pin 7 med 300ms frekvens
- Skriv ut tall i seriell skjerm med 500 ms frekvens.
FreeRTOS oppgaveimplementering i Arduino IDE
1. Fra ovennevnte grunnleggende strukturforklaring, inkluder Arduino FreeRTOS header-fil. Lag deretter funksjonsprototyper. Siden vi har tre oppgaver, så lag tre funksjoner, og det er prototyper.
#include void TaskBlink1 (void * pvParameters); ugyldig TaskBlink2 (ugyldig * pvParameters); ugyldig Oppgaveavtrykk (ugyldig * pvParameters);
2. I tomt oppsett () -funksjon, initialiser seriekommunikasjon med 9600 bits per sekund og opprett alle tre oppgavene ved hjelp av xTaskCreate () API. Først må du prioritere alle oppgaver som '1' og starte planleggeren.
ugyldig oppsett () { 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. Nå, implementer alle tre funksjonene som vist nedenfor for oppgave 1 LED blinker.
ugyldig TaskBlink1 (ugyldig * pvParameters) { pinMode (8, OUTPUT); mens (1) { digitalWrite (8, HIGH); vTaskDelay (200 / portTICK_PERIOD_MS); digitalWrite (8, LAV); vTaskDelay (200 / portTICK_PERIOD_MS); } }
På samme måte implementerer du TaskBlink2-funksjonen. Task3-funksjon vil bli skrevet som
void Taskprint (void * pvParameters) { int counter = 0; mens (1) { counter ++; Serial.println (teller); vTaskDelay (500 / portTICK_PERIOD_MS); } }
Det er det. Vi har fullført et FreeRTOS Arduino- prosjekt for Arduino Uno. Du kan finne full kode sammen med en video på slutten av denne veiledningen.
Til slutt kobler du til to lysdioder på den digitale pin 7 og 8 og laster opp koden på Arduino-kortet og åpner seriell skjerm. Du vil se at en teller kjører en gang i 500 ms med oppgavens navn som vist nedenfor.
Observer også lysdiodene, de blinker med forskjellige tidsintervaller. Prøv å spille med prioritetsargumentet i xTaskCreate- funksjonen. Endre nummeret og følg oppførselen på seriell skjerm og lysdioder.
Nå kan du forstå de to første eksempelkodene der analoge lese- og digitale leseoppgaver blir opprettet. På denne måten kan du lage flere forhåndsprosjekter ved hjelp av bare Arduino Uno og FreeRTOS APIer.