Differences

This shows you the differences between two versions of the page.

Link to this comparison view

patr:laboratoare:07 [2022/01/09 15:56]
alexandru.ionita99 [Crearea unui Task]
patr:laboratoare:07 [2022/02/14 15:16] (current)
alexandru.ionita99 [Task-uri FreeRTOS]
Line 1: Line 1:
 ===== Laboratorul 07 - Programare în timp-real pe Arduino ===== ===== Laboratorul 07 - Programare în timp-real pe Arduino =====
  
-===== Fire de execuție în Ardunio ​=====+==== Fire de execuție în Ardunio ====
  
 Întrucât microcontroller-ele prezente pe Arduino sunt single-chip și single core, un singur fir de execuție poate rula simultan. Mai mult, Arduino este construit în jurul unui singur fir de execuție principal, ce rulează în interiorul funcției **void loop()** Întrucât microcontroller-ele prezente pe Arduino sunt single-chip și single core, un singur fir de execuție poate rula simultan. Mai mult, Arduino este construit în jurul unui singur fir de execuție principal, ce rulează în interiorul funcției **void loop()**
Line 18: Line 18:
  
 Pentru a putea diviza programul în mai multe fire de execuție și a avea o rulare cvasi-paralelă a acestora, utilizăm biblioteca FreeRTOS, pe care am instalat-o în cadrul laboratorului trecut. ​ Pentru a putea diviza programul în mai multe fire de execuție și a avea o rulare cvasi-paralelă a acestora, utilizăm biblioteca FreeRTOS, pe care am instalat-o în cadrul laboratorului trecut. ​
-===== Ce este FreeRTOS? ​=====+==== Ce este FreeRTOS? ====
  
 În general, un sistem de operare controlează procesele și resursele hardware ale unui calculator, definind regulile care permit unui program să acceseze servicii și să interacționeze cu sistemul de calcul. \\ În general, un sistem de operare controlează procesele și resursele hardware ale unui calculator, definind regulile care permit unui program să acceseze servicii și să interacționeze cu sistemul de calcul. \\
Line 45: Line 45:
 modificarea acestora se realizează cu ajutorul Semaphore API. Toate aceste funcții sunt definite și prezentate detaliat în documentația FreeRTOS, disponibilă pe site-ul https://​www.freertos.org/​. modificarea acestora se realizează cu ajutorul Semaphore API. Toate aceste funcții sunt definite și prezentate detaliat în documentația FreeRTOS, disponibilă pe site-ul https://​www.freertos.org/​.
  
-===== FreeRTOS Scheduler ​=====+==== FreeRTOS Scheduler ====
  
 Tot mecanismul de funcționare FreeRTOS are la bază un scheduler, care gestionează task-urile și alte elemente real-time și realizează preempțiunea,​ atunci când este cazul. Funcția de pornire a scheduler-ului este **vTaskStartScheduler()** și, în mod normal, este apleată la sfârșitul funcției **void setup()**, pentru a începe gestionarea elementelor de programare real-time. Tot mecanismul de funcționare FreeRTOS are la bază un scheduler, care gestionează task-urile și alte elemente real-time și realizează preempțiunea,​ atunci când este cazul. Funcția de pornire a scheduler-ului este **vTaskStartScheduler()** și, în mod normal, este apleată la sfârșitul funcției **void setup()**, pentru a începe gestionarea elementelor de programare real-time.
  
-===== Task-uri FreeRTOS ​=====+==== Task-uri FreeRTOS ====
  
-Crearea, ștergerea și gestionarea task-urilor se realizează cu ajutorul **Task and Scheduler API**. ​+Crearea, ștergerea și gestionarea task-urilor se realizează cu ajutorul **Task and Scheduler API**. Pentru a utiliza task-uri, trebuie inclusă și biblioteca //task.h//, alături de //​FreeRTOS.h//​.
  
-==== Crearea unui Task ====+ 
 + 
 +<note warning>​Utilizarea FreeRTOS face ca funcția clasică **void loop()** să nu mai aibă nicio utilitate, întrucât toată logica programului se desfășoară în task-uri separate. Astfel, funcția va fi doar definită, pentru a nu primi erori la compilare, dar va rămâne goală</​note>​ 
 + 
 +=== Crearea unui Task ===
  
 Pentru a crea un nou task, utilizăm funcția **BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, const char * const pcName, unsigned short usStackDepth,​ void *pvParameters,​ UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask )**, care are următorii parametri: Pentru a crea un nou task, utilizăm funcția **BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, const char * const pcName, unsigned short usStackDepth,​ void *pvParameters,​ UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask )**, care are următorii parametri:
Line 83: Line 87:
 void setup() void setup()
 { {
-TaskHandle_t xHandle;+  
 + ... 
 +  
 + // Definim un element de tipul TaskHandle, pentru a referenția viitorul task 
 + TaskHandle_t xHandle;
  
- /* Create the task. */+ // ​Creăm task-ul
  if( xTaskCreate(  if( xTaskCreate(
- ​vTaskCode,​ /Pointer ​to the function that implements the task. */ + ​vTaskCode,​ //Pointer ​către funcția ce va rula la pornirea ​task-ului 
- "​Demo task", /* Text name given to the task. */ + "​Demo task", // Un nume pentru ​task 
- STACK_SIZE, /* The size of the stack that should be created for the task+ 200, // Sunt alocate 200 cuvinte de memorie din stivă pentru acest task 
- This is defined in words, not bytes. */ + ​(void*) &​xParameter,​ // Cast la (void*) pentru parametrul ce va fi transmis funcției 
- ​(void*) &​xParameter,/​* A reference to xParameters is used as the task parameter. + 1, // Task-ul are setată prioritatea 
- This is cast to a void * to prevent compiler warnings. */ + &​xHandle // Handle pentru ​task-ul creat
- TASK_PRIORITY, /* The priority to assign to the newly created task. *+
- &​xHandle /* The handle to the task being created will be placed in +
- ​xHandle. */+
  ) != pdPASS )  ) != pdPASS )
  {  {
- /* The task could not be created as there was insufficient heap memory remainingIf + // Task-ul nu a putut fi creatNu există suficient spațiu în stack.
- ​heap_1.c, heap_2.c or heap_4.c are included in the project then this situation can be +
- ​trapped using the vApplicationMallocFailedHook() callback (or ‘hook’) function, and the +
- ​amount of FreeRTOS heap memory that remains unallocated can be queried using the +
- ​xPortGetFreeHeapSize() API function.*/+
  }  }
  else  else
  {  {
- /* The task was created successfully. The handle can now be used in other API functions, + // Task-ul a fost creat cu succes 
- for example to change the priority of the task.*/+ 
 + // Schimbăm prioritatea task-ului, utilizând handle-ul xHandle
  ​vTaskPrioritySet( xHandle, 2 );  ​vTaskPrioritySet( xHandle, 2 );
  }  }
 +
 + // Pornim scheduler-ul FreeRTOS. Fără acest pas, task-ul nu ar rula. 
 + ​vTaskStartScheduler();​
 +
 } }
  
 +// Funcția ce va fi rulată la execuția task-ului
 void vTaskCode( void * pvParameters ) void vTaskCode( void * pvParameters )
 { {
 xStruct *pxParameters;​ xStruct *pxParameters;​
  
- /* Cast the void * parameter back to the required type. */+ // ​Cast al parametrului înapoi la tipul necesar
  ​pxParameters = ( xStruct * ) pvParameters;​  ​pxParameters = ( xStruct * ) pvParameters;​
  
- /* The parameter can now be accessed as expected. */+ // ​Lucru cu parametrul
  if( pxParameters->​cStructMember1 != 1 )  if( pxParameters->​cStructMember1 != 1 )
  {  {
Line 125: Line 132:
  }  }
  
- /* Enter an infinite loop to perform the task processing. */+ // ​Buclă infinită
  for( ;; )  for( ;; )
  {  {
- /* Task code goes here*/+  ...
  }  }
 } }
 +
 +// Definim funcția void loop(), dar rămâne goală, pentru că utilizăm task-uri
 +void loop(){}
 +
 </​code>​ </​code>​
 +
 +
 +=== vTaskDelay() ===
 +
 +O funcție foarte importantă din Task API este **void vTaskDelay( TickType_t xTicksToDelay );**. Aceasta înlocuiește clasica funcție **delay()** din Arduino. Funcția plasează **task-ul din care a fost apelată** în starea **BLOCAT** pentru o perioadă de X ticks, unde X este oferit ca parametru, timp în care alte task-uri, de exemplu cele cu o prioritate mai mică, pot accesa procesorul. ​
 +
 +Pentru a transforma timpul din milisecunde în ticks, utilizăm funcția **pdMS_TO_TICKS()**.
 +
 +<note warning>​Utilizarea funcției **delay()** nu este recomandată împreună cu FreeRTOS, deoarece conduce la **suspendarea activității procesorului**,​ adică a tutoror task-urilor care rulează. Dacă în cazul programării clasice, acest aspect nu era o problemă (exista un singur task), în cazul FreeRTOS pot apărea efecte neașteptate.</​note>​
 +
 +
 +
 +**Exemplu:​**
 +<code c>
 +void vAnotherTask( void * pvParameters )
 +{
 + for( ;; )
 + {
 +  ...
 + // Intră în starea BLOCAT pentru 20 ticks
 + ​vTaskDelay( 20 );
 +
 + // Intră în starea blocat pentru 20 ms
 + ​vTaskDelay( pdMS_TO_TICKS( 20 ) );
 + }
 +}
 +
 +</​code>​
 +
 +=== Alte funcții utile ===
 +
 +  * **vTaskDelete( TaskHandle_t pxTask ) ** - Șterge task-ul aferent hande-ului oferit ca parametru. Este eliberată memoria alocată automat la momentul creării task-ului
 +  * **xTaskGetCurrentTaskHandle() ** - Este întors handle-ul task-ului care se află **în execuție** la acel moment
 +  * **xTaskGetHandle( const char *pcNameToQuery ) ** - Este întors handle-ul task-ului cu numele oferit ca parametru
 +  * **pcTaskGetName( TaskHandle_t xTaskToQuery ) ** - Întoarce numele task-ului referit prin handle
 +  * **uxTaskPriorityGet( TaskHandle_t pxTask ) ** - Întoarce prioritatea task-ului referit prin hadle, la acel moment
 +  * **vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority ) ** - Setează o nouă prioritate pentru un task
 +  * **vTaskSuspend( TaskHandle_t pxTaskToSuspend ) ** - Pune task-ul în starea **Suspendat**
 +  * **vTaskResume( TaskHandle_t pxTaskToResume) ** - Pune task-ul în starea **Running**. Funcționează doar pentru task-uri **suspendate**
 +  * **taskYIELD() ** - Se apelează dintr-un task **Running**,​ care iși oferă partiția de timp către alte task-uri **de aceeași prioritate**
patr/laboratoare/07.1641736601.txt.gz · Last modified: 2022/01/09 15:56 by alexandru.ionita99
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0