Sisteme de operare în timp real pentru microcontrolere. Sisteme încorporate și sisteme de operare pentru acestea

Bună, Habr!
Astăzi vă voi spune despre un lucru atât de interesant ca sistem de operareîn timp real (RTOS). Nu sunt sigur dacă acest lucru va fi interesant pentru programatorii experimentați, dar cred că începătorilor le va plăcea.

Ce este un RTOS?

Dacă ne uităm la Wikipedia, vedem până la 4 definiții.
Pe scurt, un RTOS este un sistem de operare care reacționează la evenimente externe într-o anumită perioadă de timp. Prin urmare, putem înțelege scopul principal al RTOS - dispozitive în care este necesară o reacție rapidă la evenimente (cu toate acestea, în niciun caz nu confundați funcționarea RTOS cu întreruperile).

De ce avem nevoie de ea?

Există destul de multe motive pentru aceasta.
În primul rând, RTOS acceptă multitasking, priorități de proces, semafor și multe altele.
În al doilea rând, este foarte ușor și nu necesită aproape resurse.
În al treilea rând, putem obține toate cele de mai sus pe aproape orice hardware (de exemplu, FreeRTOS rulează chiar și pe AtMega pe 8 biți).
Și în al patrulea rând: doar joacă-te și distrează-te.

Revizuirea a 3 RTOS binecunoscute.

Atenție: ceea ce urmează este părerea mea personală.
FreeRTOS
Unul dintre cele mai populare RTOS de astăzi. Adus la o cantitate imensă de fier. Site-ul oficial.
pro
1) Gratuit
2) Portat la un numar mare de glanda
3) Funcționalitate puternică
4) Există diverse biblioteci: grafică, internet și multe altele.
5) Documentație bună.
Minusuri
1) Proces destul de complicat de portare pe hardware nou.

Concluzie: Acesta este un RTOS cu adevărat profesionist, cu o documentație bună. Va fi bine pentru un începător dacă există deja un port pe hardware-ul său.

KeilRTX
Până de curând, acest RTOS era comercial, dar recent a devenit deschis. Funcționează numai pe arhitectura brațelor. Site-ul oficial.
pro
1) Gratuit
2) Portat cu ușurință pe hardware nou (în cadrul arhitecturii brațului).
3) Există diverse biblioteci: grafică, internet și multe altele.
Minusuri
1) Lucrul pentru Keil cu ea este aproape imposibil
2) Funcționalitate ușor eliminată
3) Numai brațul este sprijinit.
4) (pe experienta personala) Pierde multor viteze RTOS.
Concluzie: ideală pentru începători și proiecte mici.
uc / os
RTOS comercial puternic. Site.
pro
1) Un număr mare de funcții și biblioteci.
2) Suportă mult fier
Minusuri
1) Comercial.
2) Greu de utilizat.

Concluzie: este o întindere să-l numim RTOS pentru un începător.

Alte RTOS interesante

RTLinux Un RTOS bazat pe Linux obișnuit.
QNX RTOS bazat pe Unix.

Caracteristici ale dezvoltării folosind RTOS

Ei bine, în primul rând, trebuie să înțelegeți următoarele: RTOS nu este Windows. Nu poate fi instalat. Acest sistem este compilat pur și simplu cu programul dvs.
Când scrieți programe cu RTOS, funcțiile în sensul lor obișnuit nu sunt utilizate. În loc de funcții, se utilizează procese (sau sarcini). Diferența este că procesele, spre deosebire de funcții, sunt bucle infinite și nu se termină niciodată (cu excepția cazului în care cineva sau el însuși îl ucide - adică îl descarcă din memorie).
Dacă sunt activate mai multe procese, RTOS le schimbă, afișând la rândul său timpul și resursele mașinii. Aici apare conceptul de prioritate de proces - dacă două procese au nevoie simultan de timp de mașină, atunci RTOS îl va acorda celui cu prioritate mai mare.
În RTOS există funcții speciale de întârziere - astfel încât timpul să nu fie pierdut în timpul întârzierii unui proces, al doilea este executat.
Acum, să vorbim despre un semafor - acesta este un lucru care controlează accesul unui proces la resursele aplicației. Pentru fiecare resursă există un marker - atunci când un proces are nevoie de o resursă, aceasta o ia și o folosește. Dacă nu există niciun marker, atunci procesul va trebui să aștepte să fie returnat. Voi da un exemplu: diferite procese trimit informații pe un UART. Dacă nu exista semafor, atunci ei ar trimite octeți unul câte unul și ar fi o mizerie. Și astfel primul proces a luat marcajul pe UART, a trimis un mesaj și l-a dat celui de-al doilea (și așa mai departe - ad infinitum).

Biblioteci RTOS suplimentare.

RTOS oferă adesea diverse biblioteci pentru a lucra, de exemplu, cu grafică, Internet etc. Sunt foarte confortabile și nu ar trebui să ezitați să le folosiți. Cu toate acestea, amintiți-vă că fără RTOS pentru care sunt scrise, nu vor funcționa.
Aici sunt cateva exemple:
Pentru RTX

Ce îți vine în minte când auzi un sistem de operare? Cu siguranță orificii de ventilație, Linux, Macos .. sau ceva de genul asta. Așa este, și atunci când sunt întrebați de ce este nevoie, toată lumea va răspunde cu încredere: ascultă muzică, joacă un joc (pe Internet!), În timp ce vorbește cu un prieten pe Skype. În același timp, contemplând modul în care LED-ul clipește, după ce a primit un octet de la uart =).

Și dacă săpați mai adânc, ascultați muzică, trimiteți date prin Internet sunt toate procese unice și, din moment ce avem un singur procesor, acesta poate îndeplini o singură sarcină la un moment dat. Prin urmare, sarcinile sunt realizate una câte una în „porțiuni” mici, esența sistemului de operare este să o facă imperceptibil pentru utilizator: astfel încât sunetul să nu respire și bicicletele să dispară și totul să funcționeze în același timp. În același timp, dacă una dintre sarcini „atârnă”, atunci orice altceva a continuat să funcționeze.

Dacă aruncăm toate chiflele suplimentare și lăsăm esența goală, atunci în primul rând sistemul de operare este doar un cronometru care numără în jos intervale egale de timp și, de asemenea, comută între sarcini fără intervenția utilizatorului, efectuează o parte și comută din nou. De asemenea, trebuie să țineți cont de faptul că este posibil ca majoritatea sarcinilor să nu aibă timp să fie finalizate într-o singură tranșă de timp, deci trebuie să salvați starea sarcinii în momentul trecerii la alta, iar data viitoare să restabiliți starea variabilelor. Toate acestea sunt gestionate de programatorul de sarcini.

Există două tipuri principale de sisteme de operare: preventiv și cooperativ. În primul caz, comutarea între sarcini va fi „grea”, adică. dacă felia de timp este de 1 ms, atunci prima sarcină va fi executată exact pentru 1 ms, apoi a doua pentru exact 1 ms etc. Astfel de axe sunt numite în timp real (RTOS). Cele cooperative sunt puțin mai simple, procesul în sine trebuie să spună că „Am îndeplinit”, prin urmare nu pot fi atribuite RTOS.

Nu va funcționa pentru a împinge preventiv pe AVR-uri mici dintr-un motiv cantitate mică RAM. Dintre opțiunile disponibile pentru cooperative, mi-a plăcut mRTOS, puteți citi detaliile acestui sistem pe site-ul autorului (ușor de căutat pe Google). Motivul principal utilizarea sa - simplitate, disponibilitatea unei versiuni gata făcute pentru CAVR, pentru înțelegere principii generale chiar lucrul.

Deci, principalele întrebări rămân, de ce și când să se utilizeze axa. În teorie, totul este la fel ca ceea ce faci cu axa, poți face fără ea, deoarece resursele sunt aceleași. Din faptul că îl adaptați la proiect, megaherții nu vor zbura în spațiu, fierul va rămâne același, prin urmare resursele sunt aceleași.

Prin urmare, merită să vă puneți câteva întrebări:
1. Îți poți gestiona resursele cu înțelepciune?
2. Nu se presupune că, în procesul de scriere a firmware-ului, să reinventăm aceeași bicicletă, asemănătoare planificatorului?
3. Cât de lizibil este codul dvs.? Ești capabil să-l deschizi în șase luni sau un an și să-ți dai seama imediat?
4. Scrii singur sau în grup?

Este dificil să răspunzi la prima întrebare, deoarece totul depinde de curbura dezvoltatorului. Cu al doilea, este din ce în ce mai clar, dacă există multe sarcini independente și este planificat să le efectuați la intervale regulate, atunci este mai bine să priviți către sistemul de operare. Cu al treilea, este, de asemenea, clar, este mult mai ușor să înțelegeți o sarcină separată decât alegerea dependențelor în bucla principală. Dacă nu scrieți singur, atunci există și avantaje aici, deoarece fiecare își poate scrie propria problemă separat, fără a deranja restul.

Combinând cele de mai sus, domeniul de aplicare este destul de specific, pentru o anumită gamă de sarcini. Nu ar trebui să-l împingi în fiecare proiect. Pentru majoritatea meșteșugurilor de radioamatori, axa este redundantă, dar având o idee despre asta înainte, probabil că l-aș fi împins în câteva proiecte.

Acum să aruncăm o privire sub capotă. Pentru a rula mRTOS, trebuie să vă conectați mrtos.c la proiect și să includeți mrtos.h. Structura codului este ușor diferită de cea obișnuită

#include #include "mrtos.h" // aici este corpul funcției în care scriem super-codul nostru void task1 () (while (1) // sarcinile din orice sistem de operare sunt construite pe baza unei bucle infinite { // aici este codul sarcinii tale EXPEDIERE; // funcția de a transfera controlul către planificator } ; } // timer interrupt handler 0întrerupe [TIM0_OVF] void timer0_ovf_isr (void) (char ii; #asm ("cli") TCNT0 = 0x9C; inc_systime (); for (ii = 0; ii< init_tasks; ii++ ) if (tasks[ ii] .delay ) -- tasks[ ii] .delay ; #asm("sei") } void main(void ) { // inițializează periferice Init_mRTOS (); // inițializați os // aici creăm sarcini (task-uri) 3 task-uri au fost create aici create_task (task1, 1, Active); // creați o sarcină (numele sarcinii, prioritatea, starea) create_task (task2, 1, Active); create_task (task3, 1, Active); Sheduler (); // pornește programatorulîn timp ce (1); )

#include #include „mrtos.h” // aici este corpul funcției în care scriem super codul nostru task1 () (în timp ce (1) // sarcinile din orice sistem de operare sunt construite pe baza unei bucle infinite (// aici este codul sarcinii dvs. DISPATCH; // controlul funcției transfer la planificator);) // timer 0 întrerupere manipulare întrerupere void timer0_ovf_isr (void) (char ii; #asm ("cli") TCNT0 = 0x9C; inc_systime (); pentru (ii = 0; ii

Acum, mai detaliat. numărul de sarcini este indicat în mrtos.h de APPTASKS N. Sarcina este declarată în task1 () (), task2 () () și altele asemenea, în timp ce (1) nu trebuie să scrieți nimic, nici nu trebuie să apelați funcții; planificator. După cum puteți vedea, sarcina constă dintr-o buclă infinită, acest lucru este normal și ar trebui să fie, dar în cadrul sarcinii este imperativ să dați control planificatorului. Fie funcția WAIT, fie DISPATCH. Dacă acest lucru nu este realizat, atunci sarcina va rula la nesfârșit.

Cum functioneaza? Să creăm o sarcină LED intermitentă.

void task1 () (while (1) (PORTB.0 =! PORTB.0; WAIT (100););)

void task1 () (while (1) (PORTB.0 =! PORTB.0; WAIT (100););)

WAIT este un fel de analog al întârzierii () numai, în timpul întârzierii, microcontrolerul nu face nimic și rulează cicluri goale. În timpul WAIT, controlul este transferat către alte sarcini. Acestea. puteți crea o grămadă de sarcini intermitent cu LED-uri diferite, cu AȘTEPTĂRI diferite, și toate vor clipi cu frecvențe diferite. Dacă nu sunt necesare întârzieri, atunci DISPATCH este utilizat la final.

Când utilizați WAIT, este important să înțelegeți că întregul sistem are o bifă minimă (felie de timp), deci nu așteptăm WAIT (50) 50 de milisecunde, ci 50 de bifări ale sistemului. Setarea bifării depinde de frecvența cu care sunt apelate întreruperile Timer0, adică dacă setăm întreruperea la 1 ms, atunci putem presupune că acțiunea noastră va fi executată în termen de 1 ms. Experimentele au arătat că este posibil să se reducă bifarea sistemului la ~ 20 μs cu un ceas de 16 MHz.

Setarea temporizatorului nu diferă de cea studiată anterior, deoarece timer0 are doar o întrerupere de depășire, apoi toate setările sunt legate de aceasta. În cele mai recente versiuni de CAVR, este foarte convenabil să scrieți cerințe de timp, setările vor fi generate automat.

create_task (task1, 1, Active);

create_task (task1,1, Active);

Cu priorități, este încă destul de dificil. Dacă există două sarcini cu priorități diferite și o sarcină cu o prioritate ridicată este în curs de executare în mod constant, atunci nu vom introduce niciodată o sarcină cu o prioritate redusă. Prin urmare, trebuie să organizați munca astfel încât toate sarcinile să aibă acces. Nu ne vom concentra asupra acestui lucru, îl vom salva pentru data viitoare. Starea activității, Activ - pornit, oprit StopTask.

Deci, pentru cei care doresc să clipească LED-ul:

#include #include "mRTOS.h" void task1 () (while (1) (WAIT (1000); PORTB.0 =! PORTB.0;)) // Rutina de service a întreruperii temporizatorului 0întrerupe [TIM0_OVF] void timer0_ovf_isr (void) (char ii; #asm ("cli") TCNT0 = 0xb2; inc_systime (); for (ii = 0; ii< init_tasks; ii++ ) if (tasks[ ii] .delay ) -- tasks[ ii] .delay ; #asm("sei") } void main(void ) { DDRB= (1 << DDB7) | (1 << DDB6) | (1 << DDB5) | (1 << DDB4) | (1 << DDB3) | (1 << DDB2) | (1 << DDB1) | (1 << DDB0) ; PORTB= (0 << PORTB7) | (0 << PORTB6) | (0 << PORTB5) | (0 << PORTB4) | (0 << PORTB3) | (0 << PORTB2) | (0 << PORTB1) | (0 << PORTB0) ; // Inițializare temporizator / contor 0// Sursă ceas: Ceas sistem // Valoare ceas: 7,813 kHz TCCR0 = (0<< CS02) | (1 << CS01) | (1 << CS00) ; TCNT0= 0x83 ; // Temporizator (e) / Contor (e) Inițializare întrerupere (e) TIMSK = (0<< OCIE2) | (0 << TOIE2) | (0 << TICIE1) | (0 << OCIE1A) | (0 << OCIE1B) | (0 << TOIE1) | (1 << TOIE0) ; Init_mRTOS() ; create_task(task1, 1 , Active) ; Sheduler() ; while (1 ) ; }

#include #include "mRTOS.h" void task1 () (while (1) (WAIT (1000); PORTB.0 =! PORTB.0;)) // Timer 0 overflow întrerupere serviciu rutină întrerupere void timer0_ovf_isr (void) (char ii ; #asm ("cli") TCNT0 = 0xb2; inc_systime (); for (ii = 0; ii

Ca bonus, am încercat să fac o melodie polifonică (cu două voci) „Dr. Mario chill”. Ideea este că fiecare picior al controlerului este inversat constant într-o sarcină separată, generând astfel o frecvență. Modificând întârzierea, puteți schimba tonul notei.

void task2 (void) (while (1) (if (mut == 0) // dacă este permis să se joace(dacă (note_ch2 [n_n] == 0) // dacă există o pauză, atunci așteptați, nu redați nimic(PORTB.4 = 0; WAIT (5);) else (PORTB.4 =! PORTB.4; // dacă nu o pauză, atunci smulgeți piciorul cu frecvența dorită WAIT (note_ch2 [n_n]); ))))

void task2 (void) (în timp ce (1) (dacă (mut == 0) // dacă este permisă redarea (dacă (note_ch2 == 0) // dacă există o pauză atunci așteptăm, nu jucăm nimic (PORTB.4 = 0; WAIT (5);) else (PORTB.4 =! PORTB.4; // dacă nu întrerupeți, atunci loviți cu frecvența necesară WAIT (note_ch2);))))

Nu m-am deranjat cu ideea, într-o sarcină se generează un meandru cu o frecvență a notelor pentru partea solo, în a doua pentru bas. Tonul fiecărei note este preluat din tablouri. Durata, schimbarea și încetarea sarcinii 3.

void task3 (void) (while (1) (WAIT (1500); // redați durata minimă a notei for (mut = 0; mut< 500 ; mute++ ) // tăiați nota, astfel încât să nu se îmbine(PORTB.3 = 0; PORTB.4 = 0;); mut = 0; // setați steagul în care puteți reda sunetul n_n ++; // treceți la nota următoare if (n_n == n_max) // dacă am jucat totul, atunci mergem în cerc(n_n = 0;)))

void task3 (void) (while (1) (WAIT (1500); // redă durata minimă a notei pentru (mut = 0; mut< 500; mute++) //обрываем ноту, чтобы не сливались { PORTB.3 = 0; PORTB.4 = 0; }; mute = 0; //выставляем флаг, что можно воспроизводить звук n_n++; //переходим на следующую ноту if(n_n == n_max) //если сыграли все то идем по кругу { n_n = 0; } } }

Pentru a amesteca cele două canale am folosit o schemă simplă.

Bucată mică totală

Pentru cei care doresc firmware-ul

Am dezvoltat puțin mai mult de 10 dispozitive electronice și am renunțat complet la funcționarea lor la nivel scăzut fără un sistem de operare. Situația s-a schimbat când funcționalitatea dispozitivului următor s-a extins dramatic. În plus, este nevoie de o sarcină care este apelată la intervale de timp specificate, iar acuratețea apelului afectează rezultatul. De asemenea, a devenit clar că nu va fi posibil să scriem tot software-ul în timpul alocat și va fi creat mai târziu. După câteva gândiri, mi-am dat seama că proiectul trebuie să includă un sistem de operare în timp real (RTOS sau RTOS).

Spre deosebire de un PC, în care sistemul de operare este mai mult un strat pentru lucrul cu resursele sistemului, pentru un microcontroler RTOS este în primul rând un programator de sarcini, de fapt joacă rolul principal în „timp real”. În acest moment, este important pentru mine să ofer așa-numita execuție de sarcini „pseudo-paralele”. Adică, există mai multe sarcini cu aceeași prioritate și este important să le apelați în ordinea specificată la intervale specificate.

Următorul exemplu este clar: în proiectul Eurobot 2011, în sistem erau 18 dispozitive periferice. 2 plăci electronice ar putea fi combinate într-una singură în ceea ce privește funcționalitatea. Costul acestora ar scădea, fiabilitatea ar crește (numărul de componente din sistem ar fi redus), iar cantitatea de spațiu liber în caz ar crește. Circumstanța este complicată de faptul că numărul de sarcini crește proporțional și aici nu puteți face fără sistemul de operare. RTOS ajută, de asemenea, la evitarea posibilelor perioade de nefuncționare ale procesorului, de exemplu, în timpul conversiei ADC, puteți bloca această sarcină și efectua altele, distribuind astfel corect lucrurile dispozitivului. De asemenea, este important ca acum dispozitivul să nu cadă din cauza unei eșecuri a sarcinii; în schimb, este posibil să se mențină o operabilitate parțială (deși acest lucru poate duce la rezultate imprevizibile). Cum asigurăm creșterea acestor indicatori? De fapt, stoarcem tot posibilul de la MK, folosind în mod eficient capacitățile sale de calcul.

După o scurtă căutare, alegerea a căzut pe freeRTOS. Acest RTOS este distribuit în sursă C și portat la 27 de arhitecturi. Ultima circumstanță este decisivă pentru mine. Va reduce costurile forței de muncă atunci când lucrați cu MCU-uri de la alți producători. Acum mă interesează mai mult portul pentru AVR.

Prezența RTOS freeRTOS în proiect consumă aproximativ 9,8 KB de memorie de program și 1,8 KB de memorie RAM. De exemplu, pentru ATmega32 și compilatorul WinAVR, acestea sunt 60% și, respectiv, 85%. Deja pentru acest model, este dificil să creați un dispozitiv cu funcționalități excelente - nu va fi suficientă memorie. Dar această problemă dispare odată cu noile modele AVR. Acest lucru este complet lipsit de importanță pentru Mega2560 cu 256 KB de memorie de program și 8 KB de RAM. Tendința viitorilor MCs însoțește doar succesul RTOS.

După ce am parcurs Runetul, am fost surprins să constat că nu există nicio documentație pentru sistemul de operare în limba rusă. Ce este! Documentația originală este distribuită la un cost suplimentar. Situația a fost simplificată de articolul lui Andrey Kurnits ( [e-mail protejat]) din revista „Componente și tehnologii”. Cu acordul autorului, voi folosi materialele articolului într-o versiune revizuită. Articolul său poate servi drept documentație în limba rusă. Dar originalul nu este disponibil sub formă tipărită, site-ul revistei este mincinos, astfel încât materialul va trebui să fie ușor refăcut. În general, autorul a făcut un articol excelent și nu are rost să treacă din nou la teorie, acesta va fi publicat integral aici. Articolul original va fi atașat la sfârșitul publicației. De asemenea, am observat că utilizatorii întâmpină dificultăți în compilarea RTOS. Acest lucru se datorează faptului că este utilizat un makefile extern, care conține căile către foldere. Prin urmare, voi atașa un proiect finalizat ca șablon pentru AVR Studio și AVR Eclipse. Din păcate, makefile-ul nativ nu afișează informații de depanare, cum ar fi memoria RAM și utilizarea memoriei de program, aceasta trebuind să fie remediată prin adăugarea apelului standard corespunzător.

Deci, pe scurt despre necesitate, este recomandabil să utilizați un RTOS în proiectul dvs., dacă este necesar:

Organizați activități multitasking și alternative

Asigurați-vă că sarcina începe la intervale strict definite

Transferați informații de la o sarcină la alta

Adăugați sarcini noi după cum este necesar

Avantajele RTOS față de M. LA:

  1. Multifunctional. RTOS pune la dispoziția programatorului un mecanism multitasking gata, depanat. Într-un caz simplu, fiecare sarcină poate fi programată separat, toate lucrările pot fi împărțite între mai mulți membri ai echipei. Nu trebuie să vă faceți griji cu privire la comutarea între sarcini, programatorul o va face.
  2. Baza de timp. Intervalele de timp trebuie măsurate. RTOS trebuie să aibă acest instrument. Vă va permite să efectuați acțiuni la intervale strict alocate.
  3. Schimb de date între sarcini. Pentru aceasta, RTOS folosește o coadă.
  4. Sincronizare. Dacă diferite sarcini utilizează aceeași resursă, cum ar fi un port serial, atunci pot fi folosite mutexes și secțiuni critice. Dacă trebuie să efectuați sarcini într-o succesiune strictă sau când apare un anumit eveniment, puteți utiliza semafoare sau semnale pentru a sincroniza sarcinile.

Dezavantaje ale RTOS:

1. O creștere accentuată a memoriei de program necesare pentru implementarea kernel-ului

2. Creșterea memoriei RAM necesare pentru stocarea stivei fiecărei sarcini, a semaforelor, a cozilor, a mutelor și a altor obiecte ale nucleului sistemului.

3. Întârzieri la comutarea între sarcini pentru a salva contextul.

DescrierefreeRTOS:

FreeRTOS este un sistem de operare open source gratuit în timp real. Scris mai ales în C, dar sunt prezente inserții de asamblare. A fost dezvoltat de Real Time Engineers ltd special pentru sistemele încorporate. Recent, a început să se dezvolte proiectul SafeRTOS - o versiune modificată, documentată, testată și certificată a FreeRTOS pentru conformitatea cu standardul de siguranță IEC 61508. Acest proiect a fost realizat de o companie germană și acum safeRTOS este utilizat în industria aerospațială și în tehnologia medicală. Există, de asemenea, proiectul openRTOS - o versiune comercială cu garanția producătorului.

Principalele caracteristici ale freeRTOS:

1. Scheduler acceptă 3 tipuri de multitasking:

Deplasare

O cooperativă

Hibrid

2. Dimensiunea nucleului este de 9,8 KB compilată pentru AVR. (WINAVR)

3. Baza nucleului - 4 fișiere în C.

4. Sprijină sarcinile și coroutinele. Coroutinele sunt special concepute pentru MCU-uri cu o cantitate mică de RAM.

5. Capacități bogate de urmărire.

6. Este posibil să urmăriți depășirea stivei.

7. Nu există restricții software cu privire la numărul de sarcini executate simultan.

8. Nu există o limită a numărului de priorități ale sarcinilor.

9. Mai multor sarcini li se poate atribui aceeași prioritate

10. Mijloace avansate de sincronizare „task-task” și „task-interrupt”:

Cozi

Semafoare binare

Numărarea semaforelor

Semafoare recursive

Mutexes

11. Mutexes cu moștenire prioritară.

12. Suport pentru modul de protecție a memoriei pentru Cortex-M3

13. Furnizat în formă depanată cu proiecte demo pentru diverse platforme și compilatoare.

14. Gratuit. Poate fi utilizat în proiecte fără a dezvălui codul sursă sub licența GPL extinsă.

15. Documentația este plătită, dar este disponibilă online aici.

16. Timpul de comutare a contextului pentru un AVR cu un cristal de cuarț de 16 MHz este de numai 20,8 µs. Acesta este exact cât este nevoie pentru a salva date în stiva de sarcini și a apela următoarea. (O notă interesantă, dacă comparați acest lucru cu PIC18xxx, atunci controlerul AVR îl face de 4 ori mai rapid !!!, cel mai probabil acest lucru se datorează calității compilatorului)

Multitaskingul preventiv înseamnă că o sarcină care rulează cu o prioritate redusă este suprapusă de o activitate terminată cu o prioritate mai mare. Comutarea între sarcini are loc în felii de timp egale. Prin urmare, înainte ca sarcina cu prioritate ridicată să poată începe executarea, trebuie să se încheie perioada actuală de timp la care se execută prioritatea redusă.

Astfel, timpul de reacție al FreeRTOS la evenimentele externe în modul multitasking preventiv nu este mai mult de o singură bucată de timp a planificatorului, care poate fi setată în setări. În mod implicit, este de 1 ms.

Dacă mai multe sarcini cu aceeași prioritate sunt gata de execuție, atunci planificatorul alocă fiecăreia dintre ele câte o felie de timp, după care controlul este primit de următoarea sarcină cu aceeași prioritate și așa mai departe într-un cerc.

Multitaskingul cooperativ diferă de multitaskingul preventiv prin faptul că planificatorul în sine nu poate întrerupe executarea sarcinii curente, chiar și o sarcină cu o prioritate ridicată care este gata de execuție. Fiecare sarcină trebuie să transfere independent controlul către planificator. Astfel, sarcina cu prioritate ridicată va aștepta ca sarcina cu prioritate redusă să-și finalizeze activitatea și să returneze controlul către planificator. Timpul de răspuns al sistemului la un eveniment extern devine nedefinit și depinde de cât timp va fi executată sarcina curentă înainte de transferul controlului. Multitaskingul cooperativ a fost utilizat în familia de sisteme de operare Windows 3.x.

Conceptele de multitasking preventiv și cooperativ se reunesc în multitasking hibrid, unde programatorul este numit de fiecare dată, dar spre deosebire de multitaskingul preventiv, programatorul are capacitatea de a face acest lucru cu forța în corpul sarcinii. Acest mod este util mai ales atunci când este necesar să se scurteze timpul de răspuns al sistemului la o întrerupere. Să presupunem că o sarcină cu prioritate redusă este în curs de executare și o sarcină cu prioritate ridicată așteaptă să se producă o întrerupere. Apoi apare o întrerupere, dar după sfârșitul manipulatorului de întrerupere, execuția revine la sarcina curentă cu prioritate redusă, iar cea cu prioritate ridicată așteaptă până când se termină felia de timp curentă. Cu toate acestea, dacă după executarea manipulatorului de întrerupere, controlul este transferat către planificator, atunci acesta va transfera controlul către o sarcină cu prioritate ridicată, ceea ce reduce timpul de răspuns al sistemului asociat cu un eveniment extern.

De cepeconversațieb?

Puteți începe să dezvoltați un dispozitiv cu microcontroler care rulează FreeRTOS descărcând cea mai recentă versiune a acestuia.

Distribuția FreeRTOS este disponibilă ca o arhivă ZIP obișnuită sau autoextractabilă. Distribuție Conține direct codul kernel-ului (sub forma mai multor fișiere antet și fișiere cu cod sursă) și proiecte demo (un proiect pentru fiecare mediu de dezvoltare pentru fiecare port). Apoi, ar trebui să despachetați arhiva în orice locație adecvată de pe stația de dezvoltare.

În ciuda numărului mare de fișiere din arhivă, structura directorului este de fapt simplă. Dacă intenționați să proiectați dispozitive pe 2-3 arhitecturi în 1-2 medii de dezvoltare, atunci majoritatea fișierelor legate de proiecte demo și diverse medii de dezvoltare nu vor fi necesare.

Structura detaliată a directorului este prezentată în diagramă.

Toată sursa kernelului se află în directorul / Source.

Conţinut:

1.taskuri.c- implementarea mecanismului sarcinii, planificator

2. coadă.c- implementarea cozilor

3. listă.c- nevoile interne ale planificatorului, dar funcțiile pot fi utilizate și în programele de aplicații.

4. crutină.c- implementarea coroutinelor (poate lipsi dacă nu sunt utilizate coroutinele).

Fișierele antet care se află în director sursă / include

1.tasks.h, queue.h, tist.h, croutine.h- fișierele antet, respectiv, pentru fișierele cu același nume cu codul.

2. FreeRTOS.h-contine directive preprocesor pentru configurarea compilarii.

3.mpu_wrappers.h- conține suprascrieri ale funcțiilor interfeței de programare FreeRTOS (API) pentru a sprijini modulul de protecție a memoriei (MPU).

4.portabil.h-setări dependente de platformă.

5.projdefs.h-unele definiții ale sistemului

6.semphr.h- definește funcțiile API pentru lucrul cu semaforele, care sunt implementate pe baza cozilor.

7. StackMacros.h- conține macrocomenzi pentru a controla depășirea stivei. Fiecare platformă hardware necesită o mică bucată de cod de nucleu care implementează interoperabilitatea FreeRTOS cu acea platformă. Toate codurile specifice platformei se află în subdirector / Sursă / Portabil unde este clasificat după medii de dezvoltare (IAR, GCC etc.) și platforme hardware (de exemplu, AtmelSAM7S64, MSP430F449). De exemplu, subdirectorul / Sursă / Portabil / GCC / ATMega323 conține fișierele port.c și portmacro.h, care implementează salvarea / restaurarea contextului activității, inițializarea cronometrului pentru a crea o bază de timp, inițializarea stivei fiecărei sarcini și a altor funcții dependente de hardware pentru microcontrolere din familia mega AVR și Compilator WinAVR (GCC).

Separat, ar trebui să evidențiați subdirectorul / Sursă / Portabil / MemMang care conține fișierele heap_l.c, heap_2.c, heap_3.c care implementează 3 mecanisme diferite pentru alocarea memoriei pentru nevoile FreeRTOS, care vor fi descrise în detaliu mai târziu.

Directorul / Demo conține proiecte demo gata de compilare și construire. Partea comună a codului pentru toate proiectele demo este evidențiată într-un subdirector / Demo / Commo n.

Pentru a utiliza FreeRTOS în proiectul dvs., trebuie să includeți fișierele sursă ale nucleului și fișierele antet aferente. Nu este nevoie să le modificați sau să le înțelegeți implementarea.

De exemplu, dacă intenționați să utilizați portul pentru microcontrolerele MSP430 și compilatorul GCC, atunci pentru a crea un proiect de la zero, veți avea nevoie de subdirectoare / Sursă / Portabil / GCC / MSP430_GCCși / Sursă / Portabil / MemMang... Toate celelalte subdirectoare din directorul / Source / Portable nu sunt necesare și pot fi eliminate.

Dacă intenționați să modificați proiectul demo existent (ceea ce, de fapt, este recomandat să faceți la începutul studiului FreeRTOS), atunci veți avea nevoie și de subdirectoare / Demo / msp430_GCCși / Demo / Comun... Restul subdirectoarelor / Demo nu sunt necesare și pot fi eliminate.

Când creați o aplicație, se recomandă utilizarea makefile(sau fișier proiect de mediu de dezvoltare) din proiectul demo corespunzător ca punct de plecare. Este recomandabil să excludeți din fișierele de construire (construire) din directorul / Demo, înlocuindu-le cu propriile dvs. și fișierele din directorul / Sursă - intacte. Ar trebui menționat și fișierul antet FreeRTOSConfig.h care este în fiecare proiect demo. FreeRTOSConfig.h conține definiții (#define) care permit configurarea kernel-ului FreeRTOS:

1. Un set de funcții ale sistemului.

2. Folosirea coroutinelor.

3. Numărul de priorități ale sarcinilor și coroutinelor

4. Dimensiunile memoriei (stivă și heap).

5. Frecvența ceasului MK.

6. Perioada planificatorului de timp alocată fiecărei sarcini de execuție, care este de obicei 1 ms. Dezactivați unele funcții ale sistemului și reduceți numărul de priorități (reduce consumul de memorie).

Distribuția FreeRTOS include, de asemenea, instrumente pentru conversia informațiilor de urmărire primite de la planificator în formă text (director / TgaseCon) și textul licenței (director / Licență).

concluzii

Cu ajutorul primului articol din serie, cititorul s-a familiarizat cu sistemul de operare pentru microcontrolerele FreeRTOS. Sunt prezentate caracteristicile lucrării. Descrieți conținutul distribuției FreeRTOS. Pașii de bază pentru a începe dezvoltarea unui dispozitiv care rulează FreeRTOS sunt furnizați.

În publicațiile viitoare, se va acorda atenție mecanismului multitasking, și anume sarcinilor și coroutinelor. Un exemplu de planificator va fi prezentat folosind exemplul microcontrolerelor Atmel AVR și compilatorul WinAVR (GCC).

Îmi pun în mod constant această întrebare, în timp ce îmi fac hobby-ul - dezvoltarea unui sistem de control automat pentru casă (casă inteligentă) bazat pe un microcontroler de 16 biți - este aceasta într-adevăr abordarea corectă? Acum o lună și jumătate, am scris deja pe blogul meu pe tema „Microcontrolere versus sisteme pe un cip”. Deci, voi scrie din nou despre asta.

În parte, am fost motivat de lansarea Stellaris Launchpad și Arduino Due. Ambele se bazează pe microcontrolere pe 32 de biți și sunt foarte asemănătoare din multe puncte de vedere. Am studiat foaia tehnică pentru ambele și, deși diferă decent în ceea ce privește prețul, acestea sunt concepute pentru același public țintă. M-am gândit că poate ar trebui să trec de la MSP430 la Stellaris, sau poate chiar să trec la un sistem fundamental diferit, să folosesc ceva de genul Raspberry Pi în loc de microcontrolere.

Atât Stellaris Launchpad, cât și Arduino Due sunt foarte puternice, dar nu sunt concepute pentru a rula Linux. Acestea rulează fie pe cod executabil scris direct pentru ele, fie sub controlul unui sistem de operare în timp real (RTOS), un sistem de operare minimalist cu timpi de răspuns foarte scurți la evenimente externe. Ambele sunt semnificativ mai complexe decât MSP430 sau AVR-urile pe 8 biți.

Pe de altă parte, în viața reală (în afara internetului), majoritatea oamenilor pe care îi cunosc folosesc Raspberry Pi sau alte sisteme Linux încorporate. Utilizarea microcontrolerelor este un caz destul de rar în rândul celor pe care i-am cunoscut. Chiar și Arduino este mult mai puțin popular în mediul meu decât Linux încorporat. După cum înțeleg, de ce ar cumpăra cineva un Arduino când puteți obține un Raspberry Pi care poate face mult mai mult, dar costă la fel sau mai puțin? Există o cantitate imensă de software gata pregătit pentru Linux și puteți programa pe el folosind limbaje de scriptare simple.

Pentru mine personal, motivul pentru care nu vreau să folosesc Linux este că îl folosesc în fiecare zi la serviciu și, când ajung acasă, nu am plăcerea de a trebui să lucrez din nou pe sisteme Linux. Nu am nicio problemă să folosesc Linux, dar sunt prea multe din toate colțurile, mă cântărește. Este mult mai interesant pentru mine să lucrez cu dispozitive electronice simple pe microcipuri de 8/16 biți.

Cu toate acestea, nu dau spatele realității. Dacă vreau să rămân în ton cu lumea reală, trebuie să folosesc instrumentele folosite în lumea reală. În caz contrar, este ca și cum ai vrea să conduci o mașină cu un motor cu aburi, doar pentru că motorul cu ardere internă este prea banal, așa că îl folosesc tot timpul. Dacă lumea din jurul nostru trece la o tehnologie mai avansată, este necesar să o stăpânesc, indiferent dacă îmi place sau nu. Mai ales dacă vreau ca blogul meu să fie interesant pentru oameni și să rămână relevant.

În proiectul meu de casă inteligentă, am întâmpinat de fapt această problemă. Am făcut deja un driver LAN pentru sistemul de control de pe MSP430 și totul arată foarte decent. Practic, pot face tot ce este necesar pentru un sistem de automatizare pe MSP430. Cu toate acestea, mă întreb dacă modul în care o fac este corect? Încerc să mănânc supă cu furculița când există o lingură? Poate Linux este un sistem mai bun? Lasă-mă să explic.

Dacă ne oprim și analizăm situația actuală, în ceea ce privește progresele tehnologice pentru noiembrie 2012. Mă întreb, sunt microcontrolerele bune și relevante în comparație cu sistemele pe cip care utilizează Linux?

Dacă enumerați proiectele pe sisteme încorporate care îmi vin în minte, acestea sunt: ​​drone, roboți, automatizări casnice, controlere de motor, senzori, ceasuri de mână, imprimante 3D etc. În care dintre aceste cazuri este Linux încorporat mai potrivit decât microcontrolerele? Și de ce?

Cred că există trei situații în care microcontrolerul este cea mai bună alegere: unde răspunsul instant (în timp real) la evenimente este important; acolo unde este necesar un consum extrem de redus de energie; și unde trebuie să utilizați cipuri cu cel mai mic cost posibil.

Pentru început, utilizarea microcircuitelor ieftine nu este atât de importantă pentru mine. Îmi fac hobby-ul pentru mine și nu intenționez să lansez vreodată produse competitive. Nu trebuie să mă gândesc la mutarea producției într-o fabrică de muncă sclavă pentru a avea un preț competitiv pentru proiectele mici pe care le dezvolt. M-aș bucura dacă aș putea lipi mai mult de o placă pe zi datorită abilităților mele!

De exemplu, pentru un proiect de casă inteligentă, pot proiecta un comutator controlat de la distanță. Poate aprinde / stinge luminile sau altceva. În același timp, pot să merg la magazinul meu local de electricitate și să cumpăr același preț pentru 20 USD, fabricat în China. Voi bate vreodată acest preț încercând să-mi vând propriul switch? Nu cred că este posibil.

Dacă vă gândiți la asta, acest lucru se aplică și multor alte lucruri necesare pentru automatizarea casei. Senzori de temperatură, fum, mișcare etc., sunt destul de capabil să fac și eu același lucru, dar este puțin probabil ca din aceasta să se poată obține beneficii financiare. Cui îi pasă să cumpere astfel de lucruri de la mine cu 75 USD când le poate găsi la 20 USD în Produse de uz casnic?

Dacă vă gândiți să obțineți unele beneficii din hobby-ul dvs., atunci este mai bine să acordați atenție produselor mai scumpe și mai complexe. De exemplu, un controler de automatizare a locuinței sau un termostat costă, de obicei, mai mult de 100 USD și lasă mai multă libertate creativității individuale, puteți construi unul, vinde vecinilor dvs. și chiar puteți câștiga bani din acesta.

Dar dorința de a obține un preț mai bun pentru dispozitivul final nu înseamnă că trebuie să utilizați cel mai ieftin microcontroler de pe Pământ. De fapt, aceasta este o idee proastă pentru că timpul de dezvoltare are același cost ca și piesele utilizate. Microcontrolerul poate fi ieftin, dar este nevoie de mai mult timp pentru a scrie codul de control. Timpul înseamnă bani și, dacă lucrezi mai repede, poți obține mai mult.

Toate aceste reflecții mă conduc la concluzia că este mai profitabil să dezvolt un sistem de acasă inteligent pe Linux decât pe microcontrolere, în ciuda preferințelor personale, să nu folosesc Linux (îmi place mai mult programarea la nivel scăzut decât scripturile, Linux mă plictisește) .

Revenind la subiectul subiectului, prețul microcontrolerelor, acesta poate fi un factor important pentru corporațiile mari care vor lansa un nou produs, dar la nivel individual, dacă încercați să conduceți o afacere în stilul Kickstarter, acest lucru factorul nu este atât de important, de fapt, timpul de dezvoltare rapid mai important decât costul componentelor.

Pe de altă parte, microcontrolerele pot fi o alegere mai bună decât sistemele pe un cip atunci când este necesar un consum redus de energie. În astfel de sisteme, există două puncte: consumul redus al circuitului în sine, în timpul funcționării și un timp de pornire scurt. O metodă tipică de economisire a bateriei pentru dispozitivele mici este oprită. Când opriți un computer Linux, este nevoie de o perioadă decentă de timp pentru a reveni la muncă, uneori până la câteva minute. Acest timp nu este acceptabil pentru sistemele încorporate.

Dacă luați un microcontroler precum MSP430, acesta poate rula ani de zile cu o singură baterie. Stellaris Launchpad și Arduino Due, în principiu, sunt capabili de acest lucru, consumă mai multă energie decât MSP430, dar încă foarte puțin în comparație cu Raspberry Pi. De asemenea, MSP430 poate porni imediat după oprire.

Astfel, sunt absolut sigur că în toate situațiile în care sunt necesare operațiuni de joasă tensiune, are sens să folosim microcontrolere. Există o mare varietate de dispozitive cu baterii disponibile acolo unde apare nevoia.

În al treilea caz, așa cum am spus deja, utilizarea unui microcontroler este mai semnificativă decât Linux, în operațiile care necesită răspuns instantaneu (răspuns în timp real). Mă refer la dispozitive precum imprimante 3D și mașini CNC, știu despre ce vorbesc, deoarece am dedicat mult timp studierii lor. Prin natura lor, necesită un grad ridicat de precizie în munca lor, care depinde puțin mai puțin decât în ​​totalitate de timpul de răspuns la comenzi.

De exemplu, dacă rulați un ferăstrău circular care taie în prezent o bucată de lemn sau metal, nu puteți opri procesul, datorită faptului că computerul care îl controlează are nevoie de o pauză pentru a spăla datele din memorie pe disc sau ceva altfel în același spirit. Oricine a folosit un computer este familiarizat cu înghețarea ocazională care apare intermitent în timpul utilizării normale. Acum imaginați-vă că aveți o mașină de găurit mare, care rulează un computer, care începe brusc să caute actualizări pentru Windows, în timp ce funcționează, iar burghiul găureste prin masa pe care stă. computerul și-a pierdut controlul asupra ei.

PC-urile și sistemele pe un cip nu sunt concepute pentru a funcționa în timp real, chiar și cu Windows, chiar și cu Linux, dar, desigur, încearcă să se apropie de acest lucru. De exemplu, există un patch în timp real pentru kernel-ul Linux și un software CNC special creat pentru a face acest lucru. Nu sunt suficient de familiarizat cu acest patch Linux pentru a ști cât de flexibil este să controlezi complet evenimentele în timp real. Dar cred că aceasta este doar o alternativă posibilă, deoarece Linux, indiferent de patch-urile care sunt agățate pe el, nu va bate niciodată microcontrolerele în această zonă, datorită sistemului lor de întrerupere.
În concluzie, vreau să spun că am petrecut mult timp încercând să găsesc zone în care utilizarea microcontrolerelor în proiectele mele are un avantaj. Și totul pare a fi epoca dominației mondiale a Raspberry Pi și a Beaglebones. Aceasta este situația actuală în comunitatea DIY. În majoritatea cazurilor, este mai rapid și mai ușor de dezvoltat pe aceste sisteme, deci este adesea cea mai bună alegere pentru majoritatea proiectelor.

Pentru microcontrolere, rămân doar zonele dispozitivelor de joasă tensiune, operațiunilor în timp real și dispozitivelor cu cost redus.

Nu depinde de faptul că microcontrolerele pot părea „mai distractive” decât computerele. Acest lucru este ceva cu care trebuie să vă împăcați.

Traducerea din engleză a postării originale