Sunteți pe pagina 1din 40

II. 5.

Gestionare resurse pasive partajabile


II. 5. 1. Probleme in gestionarea resurselor pasive partajabile
Acces concurent mai multe taskuri folosesc aceeai resurs pasiv
La monotasking: partajarea apare ntre funcii i ISR
Probleme principale:
Reentranta si partajare resursa
Exemplu: resursa partajat este un dispozitiv periferic ce accept mai multe
moduri de lucru
Proces 1

Proces 2

..............
Setez mod de lucru 1
Folosesc resursa pe mod 1
........................

..............
Setez mod de lucru 2
Folosesc resursa pe mod 2
........................

Proces 1 ocupa procesorul.


Pe durata folosirii resursei
pe modul 1 pierde
procesorul care este preluat
de Proces 2.
Proces 2 instaleaz alt mod
de lucru pe resursa.
Refacerea contextului la
revenirea in procesul 1 nu e
suficenta pentru continurea
corecta a executiei aplicatiei

Exemple resurse
- citire AD
- iesire pe PWM
- citire/setare IN/OUT digitale
- o variabila din memorie (de orice tip)
- un numator
- un canal serial
etc

 Reentranta si partajarea neadecvat gestionate pot conduce si la pierderea


consistenei datelor stocate n memorie, registri IO, etc.

Soluia: excludere mutual


= se accept la un moment dat accesul unui singur task la o resurs
partajat (dispozitiv IO, dat, coprocesor)
trebuie gsite seciunile critice (SC)
= secvena de program care conduce la conflict de acces

Reguli:
- o SC este executat de un singur task
- un task ateapt un timp finit nainte de o seciune critic
- n afara seciunii critice nu exist alte blocaje

Metode de excludere mutual


1. blocarea planificatorului nainte de intrarea n seciunea critic
2. prin programare - cu variabil de blocare: blocare =1 (acces interzis la resurs)
blocare =0 (acces permis la resurs)
3. prin semafoare
s = numr de taskuri ce pot face apel simultan la resursa (iniial toate
resursele sunt disponibile)
- la excludere mutuala smax=1 (exista o singura resursa de un anumit tip i
aceasta poate fi ocupat de un singur task, la un moment de timp)

Take funcie ce asigur solicitare acces la resursa (Take, Get)


s s-1
Dac s>=0 , exista resurse libere si una dintre resursele libere este
ocupat acum.
Dac s< 0, nu exista resurse libere. Taskul intra in
blocare/waiting, ateptand eliberarea resursei.

Give eliberarea resursei de un task care a ocupat-o (Give, Release)


s s+1
Dac s<= 0, pentru resursa eliberat exist o solicitare anterioar
de ocupare care nu a fost deservit. Resursa este oferit unui task
(in general la SOTR: n ordinea solicitrilor sau prioritilor)
>> FreeRTOS folosete o coada de mesaje pentru implementarea simpla
a semafoarelor

Probleme tipice generate de excluderea mutual:


Inversiunea de prioritate:
- un task mai putin prioritar conduce la ntrzierea unui alt task mai prioritar.
in acest caz ocupnd o resurs la care cere ulterior acces i taskul
mai prioritar
Soluia uzual acceptat: inferena de prioritate
Se crete temporar prioritatea pentru taskul mai puin prioritar,
grabind executia sa i, implicit, eliberarea resursei
Inversiunea de prioritate apare astfel pe un interval de timp mai mic

Exemplu
P_T1 > P_T2 > P_T3. Se considera modul preemtiv.
Initial T1, T2 sunt blocate. T3 primeste procesorul si ocupa resursa R
Se debocheaza T1 si T2. T1 primeste procesorul, cere resursa R, nu o poate
primi, este blocata.
T2 primeste procesorul, il tine cat are nevoie, apoi cedeaza procesorul catre T3
T3 foloseste resursa, o elibereaza. Acum resursa poate fi folosita de T1.
T1 asteapta executia lui T2 care este mai putin prioritar!
Inferenta de prioritate: cand T1 cere acces la resursa R, T3 primeste
temporar prioritate lui T1:

Initial T1, T2 sunt blocate. T3 primeste procesorul si ocupa resursa R


Se debocheaza T1 si T2. T1 primeste procesorul, cere resursa R, nu o poate
primi, este blocata. T3 primeste prioritatea P_T1
T3 foloseste resursa, o elibereaza, trece la prioritatea P_T3. Acum resursa
poate fi folosita de T1.

Deadlock
Dou taskuri nu mai pot progresa, mpiedicndu-se reciproc s primeasc acces
la procesor
Ex: Task1 ocup Resursa R1, Task2 ocup resursa R2.
Task1 cere acces la resursa R1, Task2 cere acces la resursa R2

Task1

Task2

Resursa 1

Resursa 2

Soluia:
eliberarea resurselor ocupate nainte de a cere acces la alta

II. 5. 2. Faciliti FreeRTOS pentru lucrul cu semafoare


Mecanismul folosit pentru implementare se bazeaz pe lucrul cu cozi de mesaje.
Un semafor are asociat o coada de mesaje la care continutul mesajului nu are
relevanta. Este folosita doar informatia exista sau nu mesaje mesaje in coada.
Resursa disponibil: exist mesaje n coad - semafor pe verde (acces permis)
Resursa nedisponibila: nu exist mesaje n coad - semafor pe rosu
Semafor binar
Coada cu 1 mesaj. Iniial coada este plin.
Operaia Take pune semaforul pe rou citind mesajul
Operaia Give pune semaforul pe verde scriind mesajul
Este util pentru excludere mutual un singur task poate ocupa la un moment
dat o resursa

Task1
{
..........
Take R
.....// instructiuni ce folosesc resursa R
Give R
..............
}
Task2
{
..........
Take R
.....// instructiuni ce folosesc resursa R
Give R
..............
}

Taskurile pot ajunge n orice ordine la


secvena critic.
Primul task care are nevoie de resurs, o
ocup i pune semaforul pe rou, pn
termin operaiile necesare cu acea
resurs.
Dac ntre timp alte taskuri au nevoie de
resurs, acestea gsesc semaforul pe rou,
ntr n blocare (conform detaliilor
precizate la cozi de mesaje).
La eliberarea resursei, toate taskurile
solicitante cu timeout convenabil devin
gata de execuie, cel mai prioritar va ocupa
resursa.
!!! Un task cu timeout mic poate
pierde resursa, indiferent de
prioritate

Exercitii
Mod preemtiv, P_T1>P_T2>P_T3. Alte situatii P_T3=P_T1>P_T2,
P_T3=P_T2>P_T1.
T1 se blocheaza
(temporizare)

T3 si T1 blocate
T2 ready
T2 foloseste Take R

Se deblocheaz T2

T2

Se deblocheaza T1, T3.


T1 doreste Take R, intra
in blocare

T1T2

T2T1

T1

T1T2

T2T3

T2 foloseste GiveR
T1 este deblocat
(timeout nedepasit),
executa Take R, cateva
instructiuni specifice si
apoi Give R.

T1 este prioritar, dar


asteapta eliberarea
resursei

T3 I

T2

T2 se blocheaza
(temporizare)

mod preemtiv, P_T1>P_T2>P_T3


T3 si T1 blocate
T2 ready
T2 foloseste Take R

Se deblocheaz T2

T3 se blocheaza
(temporizare)

T2

T1T2

T2

T1T2T3

T3I

T2

T2T3

T3 I

T2

T2 se blocheaza
(temporizare)

Se deblocheaza T1, T3.


T1 doreste Take R, intra
in blocare

T1 este deblocat
(timeout depasit, R
nefolosit in T1)
T2 foloseste GiveR si intra
in blocare
T3 se deblocheaza

T2 foloseste
resursa

atentie, taskurile prioritare pot pierde accesul la


resursa daca timeout e mic

verifica mereu daca folosirea resursei a fost posibila


sau nu (if!!!!!)

T1 doreste Take R, intra


in blocare,
T2 doreste Take R, intra
in blocare

mod preemtiv
P_T1>P_T2>P_T3.

T1 si T2 blocate
T3 ready
T3 foloseste Take R

T1 se blocheaza
(temporizare)

T3

Se deblocheaza
T1, T2.

T1T2T3

T3T1

T1

T1T2

T2T3

T3 foloseste GiveR
T1 este deblocat
(timeout nedepasit)

T3 I

T2 primeste resursa
(timeout nedepasit), o
elibereaza, etc

T1 foloseste Give R,
T2 se deblocheaza (timeout
inca nedepasit), dar T2 nu
primeste procesorul

Probleme
Daca mai multe taskuri folosesc aceeasi resursa, pot exista probleme in
stabilirea timeout (mai ales daca exista si alte taskuri mai prioritare)

semafoarele binare sunt greu de gestionat daca sunt multe taskuri &
taskuri care partajeaza resursa

poti folosi resurse diferite?


ocupa resursa pe intervale cat mai scurte de timp posibil
foloseste alt tip de semafoare

Exercitiu 1:
Schitati in pseudocod urmatoarele aplicatii, folosind semafoare binare:

T1 (prioritate 2) asigura un joc de leduri: aprinde ledurile 15, 14, 13 pentru


300 msec apoi le stinge pentru alte 300 msec, apoi aprinde doar ledul 14 pentru
300 msec. Acest joc nu trebuie distorsionat de alte taskuri, dar dupa o sectiune
de joc, ledurile pot fi folosite pentru alte semnalizari dorite. Sesiunea de joc
este repetata la fiecare 4 sec.

T2 (prioritate 3) asigura alt joc de leduri: aprinde ledul 13 pentru 300 msec si
apoi il stinge pentru 300 msec. Sesiunea este reluata la fiecare 2 sec.

T3 (prioritate 4) cere schimbarea starii ledului 15 la fiecare 4 sec.

Semafoare de tip contor


Coada cu mai multe mesaje
Operaia Take citete un mesaj; pune semaforul pe rou cnd coada este
goal
Operaia Give scrie un mesaj; pune semaforul pe verde
Este util pentru:
1. Acces la cluster de resurse identice
Iniial coada este plin, iar numrul resurselor = nr maxim de mesaje din
coada.
Dac exist mesaje n coad, interpretam ca mai exist resurse libere n
cluster.
Cnd coada devine goal, nu mai exist resurse disponbile, taskurile
solicitante intr n blocare.
Cere resursa = Take, elibereaza resursa = Give

2. Numrare evenimente.
Iniial coada este goal, iar adancimea cozii = numrul evenimentelor ce
ateapt s fie procesate.
Sosirea unui eveniment corespunde unei operatii Give (scrie in coad).
Procesarea (folosirea) unui eveniment este nsoit de o operaie Take
(terge un mesaj din coad).
Exemplu: interpretarea rezultatelor unor achiziii de date, interpretarea unor
comenzi de la tastatur.
>> nu pot suprascrie date ce nu au fost interpretate inca (astept eliberare
spatiu in coada)
Poate aprea >> inversiunea de prioritate / pericol diminuat cu semafoare mutex

Exercitiul 2
Schitati in pseudocod urmatoarele aplicatii, folosind semafoare contor:
i) T1 (de prioritate 2) perioada 1 sec, T2 (de prioritate 3) perioada 2 sec si T3 (de
prioritate 4) perioada 1 sec cer ocuparea unui canal serial pentru transmitere unor
blocuri de date. Exista doar 2 canale seriale disponibile.
ii) Se considera un cluster de resurse de tip led (led 15, 14, 13, 12). Ocuparea se face
in aceasta ordine (prioritar se ocupa led 15; led 12 este ocupat doar cand nu exista
alte leduri libere)
T1 (de prioritate 2) perioada 1 sec, T2 (de prioritate 2) perioada 2 sec, T3 (de
prioritate 3) perioada 1 sec, T4 (de prioritate 3) perioada 2 sec, T5 (de prioritate
4) perioada 1 sec - cer ocuparea unui led (pentru o setare specifica): T1, T2 aprind
ledul ocupat, T3, T4, T5 il sting.
Indicati modul de ocupare a resurselor si de executie a taskurilor.

Mutex
= Semafor binar implementat cu inferen de prioritate
Dac un task (T1) care intr n blocare (atunci cnd cere acces la o resurs deja
ocupat) are prioritate mai mare dect taskul ce ocup resursa (T2), atunci T2 este
temporar crescut n prioritate, pentru a grbi execuia sa i eliberarea resursei.
Mutex recursiv
= un mutex ce accept cereri recursive de la acelai task
Un task poate trimite cereri suplimentare de ocupare a unei resurse, in timp ce este
deja proprietar pe ea. Pentru fiecare cerere de ocupare va exista o cerere de eliberare
pereche.
Resursa poate fi folosita de alte taskuri dupa rezolvarea tuturor acestor cereri de
ocupare (preluate de la taskul proprietar deja pe resursa).

Exercitiu: diferenta dintre semafor binar si mutex


Semafor binar. P_T1>P_T2>P_T3.
T2 se blocheaza
(temporizare)

T2 si T1 blocate
T3 ready
T3 foloseste Take R

T3
T3

Se deblocheaza T1, T2.


T1 doreste Take R, va
intra in blocare

T1 este prioritar, dar va


astepta eliberarea resursei

T1T2
T1T2

T2T3
T2T3

T3T1
T3T1

T1
T1

T1 se blocheaza
(temporizare)

T1 T3
T1 T3

T3 I
T3 I

T3 foloseste GiveR
T1 este deblocat
(timeout nedepasit),
executa Take R, cateva
instructiuni specifice si
apoi Give R.

I
I

I
I

T3 se blocheaza
(temporizare)

Exercitiu: diferenta dintre semafor binar si mutex


Mutex. P_T1>P_T2>P_T3.

T2 si T1 blocate
T3 ready
T3 foloseste Take R

T3

Se deblocheaza T1, T2.


T1 doreste Take R, va
intra in blocare

T1 este prioritar, dar va


astepta eliberarea resursei.
T3 creste temporar in
prioritate

T2 se blocheaza
(temporizare)

T1 se blocheaza
(temporizare)

T1T3T1

T1

T1T2

T2

T2 T3

T3 foloseste GiveR
T1 este deblocat
(timeout nedepasit),
executa Take R, cateva
instructiuni specifice si
apoi Give R.

T3 I

T3 se blocheaza
(temporizare)

In continuare timeout mic poate conduce


la pierderea accesului de catre T1 prioritar

Exercitiu: diferenta dintre semafor binar si mutex


Mutex recursiv. P_T1>P_T2>P_T3.

T2 si T1 blocate
T3 ready
T3 foloseste Take R

T3

Se deblocheaza T1, T2.


T1 doreste Take R, va
intra in blocare

T1 este prioritar, dar va


astepta eliberarea resursei.
T3 creste temporar in
prioritate si poate efectua
ocupari recursive de resursa

T2 se blocheaza
(temporizare)

T1 se blocheaza
(temporizare)

T1T3T1

T1

T1T2

T2

T2 T3

T3 foloseste apeluri
recursive, ultimul GiveR
deblocheaza (timeout
nedepasit), executa Take
R, cateva instructiuni
specifice si apoi Give R.

T3 I

T3 se blocheaza
(temporizare)

timeout mic poate conduce la pierderea


accesului de catre T1 prioritar

Exercitiul 3:

Reluati exercitiul 1, folosind semafoare mutex.

Servicii API pentru lucrul cu semafoare (vezi queue.h si queue.c)


Creare semafor
vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )
xSemaphore

Handler la semafor - de tip xSemaphoreHandle.

Exemplu:
xSemaphoreHandle xSemaphore;
void vATask( void * pvParameters ){
vSemaphoreCreateBinary( xSemaphore );
if( xSemaphore != NULL ) {
// semafor creat cu succes.
}
}

xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE


uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
uxMaxCount Valoare maxima contor. Daca aceasta valoare este atinsa, operatiile Give determina
intrarea in starea de blocare
uxInitialCount Valoare initiala
Returneaz: handler la semafor (succes), NULL (esec)
Atentie: setare in FreeRTOSconfig.h

Exemplu:
void vATask( void * pvParameters ) {
xSemaphoreHandle xSemaphore;
xSemaphore = xSemaphoreCreateCounting( 10, 0 );
if( xSemaphore != NULL ) {
// semafor creat cu succes.
}
}

xSemaphoreHandle xSemaphoreCreateMutex( void )


xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )
Returneaz un handler la semafor, de tip xSemaphoreHandle

Atentie: setare in FreeRTOSconfig.h

Exemplu
xSemaphoreHandle xMutex;
void vATask( void * pvParameters )
{
xMutex = xSemaphoreCreateRecursiveMutex();
if( xMutex != NULL )
{
// mutex creat cu succes.
}
}

Operaii de tip Take


xSemaphoreTake(
xSemaphoreHandle xSemaphore,
portTickType xBlockTime
-

)
pentru semafoare de tip binar, contor, mutex

xSemaphoreTakeRecursive( xSemaphoreHandle xMutex, portTickType


xBlockTime )
- pentru semafoare mutex recursive;
- solicit configUSE_RECURSIVE_MUTEXES =1 (din FreeRTOSConfig.h)
Handler la semafor
Nr. maxim tickuri permis pentru asteptare.
Daca valoarea este 0, fr asteptare.
Daca valoarea = portMAX_DELAY i INCLUDE_vTaskSuspend =1, taskul poate rmne
orict n ateptare.
Returneaz: pdTRUE (semafor primit), pdFALSE (xBlockTime expir fr primire acces)

xSemaphor
xBlockTime

Operaii de tip Give


xSemaphoreGive( xSemaphoreHandle xSemaphore )
- pentru semafoare de tip binar, contor, mutex
xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )
- pentru semafoare mutex recursive;
- solicit configUSE_RECURSIVE_MUTEXES =1 (din FreeRTOSConfig.h)
xSemaphore
Hanlder la semafor
Returneaz: pdTRUE ( eliberare cu success), pdFALSE (eroare la eliberare)

Exemple
xSemaphoreHandle xSemaphore = NULL;
void vATask(void * pvParameters) {
xSemaphore = xSemaphoreCreateMutex();}
void vAnotherTask( void * pvParameters ) {
if( xSemaphore != NULL ) {
if( xSemaphoreTake(xSemaphore,(portTickType) 10 ) == pdTRUE ){
// ...foloseste resursa
xSemaphoreGive( xSemaphore );}
else {
// acces neprimit
}} }

xSemaphoreHandle xSemaphore = NULL;


void vATask( void * pvParameters ){
xSemaphore = xSemaphoreCreateMutex();
if( xSemaphore != NULL ) {
if( xSemaphoreGive( xSemaphore ) != pdTRUE ){
//va fi esec, nefiind un Take preliminar
}
if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) ){
if( xSemaphoreGive( xSemaphore ) != pdTRUE )
{
// aici va fi cu succes
}
}
}
}

xSemaphoreHandle xMutex = NULL;


void vATask( void * pvParameters ) {
xMutex = xSemaphoreCreateRecursiveMutex(); }
void vAnotherTask( void * pvParameters ){
if( xMutex != NULL ){
if(xSemaphoreTakeRecursive(xMutex,(portTickType)10)==pdTRUE )
{
xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
xSemaphoreGiveRecursive( xMutex );
xSemaphoreGiveRecursive( xMutex );
xSemaphoreGiveRecursive( xMutex );}
else {
// mutex recursiv neprimit
}
}
}

Protecii suplimentare pentru seciuni critice


Variante de protectie directe:
- suspendarea temporara a tuturor celorlalte taskuri
- invalidare ISR

Exemplu cu semafor binar


#include
#include
#include
#include
#include
#include

<stdio.h>
"FreeRTOS.h"
"task.h"
"queue.h"
"croutine.h"
"partest.h"

#include "semphr.h"

T1 (prioritate 2) stinge ledurile 15,14, 13, la fiecare 1 sec


(mentine aceasta setare pe perioada cat executa anumite
instructiuni)
T2 (prioritate 4) aprinde ledurile 15,14, 13, la fiecare 1 sec
(mentine aceasta setare pe perioada cat executa anumite
instructiuni)
T3 (prioritate 3) foloseste led 12 (perioada 2 sec)

_FOSCSEL(FNOSC_FRC); // Select Internal FRC at POR


_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF); // Enable Clock Switching and Configure
// FRC + PLL
unsigned int flag_corect=1;
unsigned int nr;
xSemaphoreHandle xMineSemaphore;
portTickType del;

void Task1(void *params) {


portTickType xLastTime = xTaskGetTickCount(); int i,j;
for (;;){
if( xSemaphoreTake(xMineSemaphore,(portTickType) 500 ) == pdTRUE ){
vParTestSetLED(15,1); vParTestSetLED(14,1); vParTestSetLED(13,1);
for (i=0; i<100; i++) for (j=0; j<15000; j++) ; //orice instr.
nr++;
xSemaphoreGive( xMineSemaphore );}
vTaskDelayUntil(&xLastTime,1000);}
}

void Task2(void *params) {


portTickType xLastTime = xTaskGetTickCount(); int i,j;
for (;;){
if( xSemaphoreTake(xMineSemaphore,(portTickType) 500 ) == pdTRUE ){
vParTestSetLED(15,0); vParTestSetLED(14,0); vParTestSetLED(13,0);
del=xTaskGetTickCount();
for (i=0; i<100; i++) for (j=0; j<15000; j++) ; //orice instr.
del=xTaskGetTickCount()-del;
nr++;
xSemaphoreGive( xMineSemaphore ); }
vTaskDelayUntil(&xLastTime,1000);} // vTaskDelayUntil(&xLastTime,1010);
}

void Task3(void *params) {


portTickType xLastTime = xTaskGetTickCount();
int i,j;
for (;;){
vParTestToggleLED(12);
for (i=0; i<100; i++) for (j=0; j<5000; j++); //orice instr.
vTaskDelayUntil(&xLastTime,2000);} // vTaskDelayUntil(&xLastTime,2010);
}

void initPLL(void){
// Configure PLL prescaler, PLL postscaler, PLL divisor
PLLFBD = 41;
// M = 43 FRC
CLKDIVbits.PLLPOST=0;
// N1 = 2
CLKDIVbits.PLLPRE=0;
// N2 = 2
// Initiate Clock Switch to Internal FRC with PLL (NOSC = 0b001)
__builtin_write_OSCCONH(0x01);
// FRC
__builtin_write_OSCCONL(0x01);
// Wait for Clock switch to occur
while (OSCCONbits.COSC != 0b001);
// Wait for PLL to lock
while(OSCCONbits.LOCK!=1) {};}

// FRC

void prvSetupHardware( void ){ vParTestInitialise(); initPLL();}

int main( void ){


prvSetupHardware();
vSemaphoreCreateBinary( xMineSemaphore );
xTaskCreate(Task1, (signed portCHAR *) "T1", configMINIMAL_STACK_SIZE, NULL,
tskIDLE_PRIORITY+2, NULL);
xTaskCreate(Task2, (signed portCHAR *) "T2", configMINIMAL_STACK_SIZE, NULL,
tskIDLE_PRIORITY+4, NULL);
xTaskCreate(Task3, (signed portCHAR *) "T3", configMINIMAL_STACK_SIZE, NULL,
tskIDLE_PRIORITY+3, NULL);
vTaskStartScheduler();
return 0;}

Situatii de discutat:
- cu/fara T3;
- cu timeout mai mic < del
- ce influenta poate avea valoarea lui del

Q: ce se intampla daca se foloseste mutex in loc de semafor binar.

Exemplu cu semafor de tip contor


in FreeRTOSconfig. h

#include
#include
#include
#include
#include
#include
#include

<stdio.h>
"FreeRTOS.h"
"task.h"
"queue.h"
"croutine.h"
"partest.h"
"semphr.h"

foloseste #define configUSE_COUNTING_SEMAPHORES 1

T1, T2, T3 pot accesa clusterul de leduri


14, 13. (in aceasta ordine)

_FOSCSEL(FNOSC_FRC); // Select Internal FRC at POR


_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF); // Enable Clock Switching and Configure
// FRC + PLL
unsigned int led_14=1, led_13=1; //1 - led liber, 0 - led ocupat
xSemaphoreHandle xMineSemaphore;
portTickType no_tick;

void Task1(void *params) {


portTickType xLastTime = xTaskGetTickCount();
static unsigned int led;
for (;;){
if( xSemaphoreTake(xMineSemaphore,(portTickType) 15) == pdTRUE ){
//exista sigur cel putin un led liber; le ocup in ordinea 14, 13
if (led_14 ==1) {led_14=0; led=14;} else {led=13; led_13=0;}
vParTestToggleLED(led);
vTaskDelay(10);
if (led==14) {led_14=1;} else led_13=1;
xSemaphoreGive( xMineSemaphore );}
Asigura ca taskul nu poate fi
vTaskDelayUntil(&xLastTime,1000);}
preemtat in de altul care doreste
}
acces la aceeasi resursa
void Task2(void *params) {
portTickType xLastTime = xTaskGetTickCount();
for (;;){
if( xSemaphoreTake(xMineSemaphore,(portTickType) 5) == pdTRUE ){
//exista sigur cel putin un led liber; le ocup in ordinea 14, 13
if (led_14 ==1) {led=14; led_14=0;} else {led=13; led_13=0;}
vParTestToggleLED(led);
vTaskDelay(10);
if (led==14) {led_14=1;} else led_13=1;
xSemaphoreGive( xMineSemaphore );}
vTaskDelayUntil(&xLastTime,2000);}
}

void Task3(void *params) {


portTickType xLastTime = xTaskGetTickCount();
for (;;){
if( xSemaphoreTake(xMineSemaphore,(portTickType) 5 ) == pdTRUE ){
//exista sigur cel putin un led liber; le ocup in ordinea 14, 13
if (led_14 ==1) {led=14; led_14=0;} else {led=13; led_13=0;}
vParTestToggleLED(led);
vTaskDelay(10);
if (led==14) {led_14=1;} else led_13=1;
xSemaphoreGive( xMineSemaphore );}
vTaskDelayUntil(&xLastTime,1000);
}}
void initPLL(void){
// Configure PLL prescaler, PLL postscaler, PLL divisor
PLLFBD = 41;
// M = 43 FRC
CLKDIVbits.PLLPOST=0;
// N1 = 2
CLKDIVbits.PLLPRE=0;
// N2 = 2
// Initiate Clock Switch to Internal FRC with PLL (NOSC = 0b001)
__builtin_write_OSCCONH(0x01);
// FRC
__builtin_write_OSCCONL(0x01);
// Wait for Clock switch to occur
while (OSCCONbits.COSC != 0b001);
// Wait for PLL to lock
while(OSCCONbits.LOCK!=1) {};

// FRC

}
void prvSetupHardware( void ){vParTestInitialise();initPLL();}

int main( void ){


prvSetupHardware();
xMineSemaphore=xSemaphoreCreateCounting(2,2);
xTaskCreate(Task1, (signed portCHAR *) "T1", configMINIMAL_STACK_SIZE, NULL,
tskIDLE_PRIORITY+2, NULL);
xTaskCreate(Task2, (signed portCHAR *) "T2", configMINIMAL_STACK_SIZE, NULL,
tskIDLE_PRIORITY+3, NULL);
xTaskCreate(Task3, (signed portCHAR *) "T3", configMINIMAL_STACK_SIZE, NULL,
tskIDLE_PRIORITY+4, NULL);
vTaskStartScheduler();
return (0);
}

S-ar putea să vă placă și