This is an old revision of the document!
Dacă laboratorul trecut a fost destinat semafoarelor, cel de astăzi este dedicat mutexurilor.
Semafoarele binare și mutexurile sunt similare, dar prezintă două diferențe principale:
În schimb, semafoarele binare blocate pot fi deblocate de orice alt task și nu există un mecanism de prioritizare.
Similar cu semafoarele, mutexurile sunt referite cu ajutorul handle-urilor. De asemenea, pentru a le utiliza, este necesară declararea bibliotecii semphr.h.
// Include biblioteca FreeRTOS #include <Arduino_FreeRTOS.h> // Include biblioteca pentru semafoare #include <semphr.h> // Declară o variabilă globală de tipul SemaphoreHandle_t SemaphoreHandle_t mutex;
În Documentația oficială FreeRTOS, API-ul corespunzător este prezentat începând cu pagina 208, împreună cu exemple de utilizare pentru fiecare funcție.
După cum am specificat anterior, există câteva diferențe între semafoarele binare și mutexuri. Întrucât pot fi deblocate de orice task, semafoarele binare sunt mai potrivite atunci când avem nevoie de o sincronizare a două taskuri. De exemplu, un task mai rapid poate fi blocat la un semafor până când un task mai lent ajunge într-un punct în care îl deblochează.
Pentru a crea un semafor binar, este utilizată funcția xSemaphoreCreateBinary() . Aceasta alocă spațiu în heap pentru semaforul binar și îl creează, cu starea inițială este “blocat”. Dacă valoarea întoarsă este NULL, nu există suficientă memorie disponibilă.
Exemplu:
SemaphoreHandle_t xSemaphore; void vATask( void * pvParameters ) { /* Încearcă crearea unui semafor. */ xSemaphore = xSemaphoreCreateBinary(); if( xSemaphore == NULL ) { /* Nu există spațiu suficient în memorie pentru a crea semaforul */ } else { /* Semaforul poate fi acum utilizat. Apelarea xSemaphoreTake() va eșua până la apelarea xSemaphoreGive(). */ } }
Semafoarele generalizate pot avea orice valoare ≥ 0. Când valoarea sa este 0, semaforul este blocat. Pentru a crea un semafor generalizat, este utilizată funcția xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount ). Primul argument reprezintă valoarea maximă a semaforului, iar al doilea argument definește valoare inițială a acestuia.
Exemplu
void vATask( void * pvParameters ) { SemaphoreHandle_t xSemaphore; // Declarare handle xSemaphore = xSemaphoreCreateCounting( 10, 0 ); // Creare semafor generalizat cu valoare inițială 0 și valoarea maximă 10 if( xSemaphore != NULL ) { /* Semaforul a fost creat cu succces*/ }
În exemplul de mai sus, handle-ul a fost declarat în interiorul unui task și nu sub formă de variabilă globală.
Utilizate în principal pentru gestionarea accesului la o resursă partajată, mutexurile sunt create cu ajutorul funcției xSemaphoreCreateMutex().
Exemplu:
SemaphoreHandle_t xSemaphore; void vATask( void * pvParameters ) { xSemaphore = xSemaphoreCreateMutex(); // Apelare funcție creare mutex if( xSemaphore == NULL ) { /* Spațiu de memorie insuficient */ } else { /* Mutexul poate fi utilizat */ } }
Următoarele funcții sunt de interes: