MINISTERUL EDUCAŢIEI, CULTURII ȘI CERCETĂRII AL REPUBLICII MOLDOVA Universitatea Tehnică a Moldovei Facultatea Calculatoare, Informatică și Microelectronică Departamentul Ingineria Software și Automatică
Sisteme de Operare Lucrare de laborator nr.2
Student: Coordonator: Dubac Serghei, asistent universitar
Chişinău, 2020
Sarcina Realizarea unei aplicații pentru MCU care va rula minim 3 task-uri în două versiuni: Secvențial și cu FreeRTOS. Aplicația va rula minim 3 task-uri printre care: 1. Button Led – schimbare stare LED la detecția unei apăsări pe buton; 2. Button Led – intermitent, în faza în care LED-ul de la primul task e stins; 3. Incrementare/decrementare – valoare a unei variabile la apăsarea a două butoane care va reprezenta numărul de recurențe/timp în care LED-ul de la al doilea task se va afla într-o stare; 4. Idle – afișarea stărilor din program, cum ar fi, afișare stare LED, și afișare mesaj la detecția apăsării butoanelor, o implementare fiind ca la apăsarea butonului să se seteze o variabilă, iar la afișare mesaj – resetare, implementând mecanismul provider/consumer.
Indicații 1. Să se implementeze comunicarea între task-uri ca provider/consumer, adică:
task-ul care generează date, provider, stochează rezultatele într-o variabilă globală/semnal;
task-ul care utilizează aceste date, consumer, citește aceasta variabilă/semnal.
Exemplu: task de UI (LCD sau Serial) preia informația din niște variabile-semnale globale și raportează. 2. A se urma principiile prezentate la curs Sisteme Secvențiale:
stabilirea rezonabilă a recurenței pentru a diminua încărcarea procesorului;
stabilirea offset-ului, întru a activa în ordinea cuvenită task-urilor.
3. Task-ul de raportare pentru Secvențial cu utilizare STDIO printf() către LCD va fi rulat în bucla infinita/IDLE deoarece este bazat pe un spin lock și ar putea bloca întreruperile, deci secvențial clasic – printf&delay în main loop, în FreeRtos – un task separat. 4. Versiune cu FreeRtos.
Etapele Pentru aplicația (anume MCU) noastră vom utiliza un sistem compus din mai multe componente, care le analizăm din schema 1. Treptat vom testa fiecare din acestea, dând la execuție la programul nostru.
Schema 1. Schema aplicației pentru MCU După exacutarea în prima priză, LED-ul de culoare roșie este cu statut de stins, iar LED-ul verde este intermitent timp de 1 secundă.
Schema 2. Executarea în primă repriză Acțiunea următoare va fi, apăsarea butonului „BTM INCREMENT”. Acesta va mări timpul de ardere intermitent (de exemplu, 2 secunde arde și 2 secunde în regim stins). În terminal (schema 3) analizăm valoarea recurenței, LED-ul verde timp de 4 secunde se va afla în regim ON, iar apoi OFF.
Schema 3. Valoarea recurenței pentru Green LED Testăm butonul „BTN RED LED”, vedem că automat LED-ul de culoare verde se stinge și se aprinde cel de culoare roșie. De asemenea, acordăm atenție că atât timp cât roșu este activat, LED-ul verde va fi inactiv (schema 4).
Schema 4. Testarea butonului „BTN RED LED” Testăm butonul „BTN RESET” (schema 5) – toate valorile anterioare afișate după executări sunt restate și întreg sistem revine la starea inițială. La final, avem afișat mesajul precum sistemul nostru a trecut cu succes prin resetare.
Schema 5. Testarea butonului „BTN RESET”
Concluzie În cadrul lucrării de laborator nr.2, am lucrat la realizarea unei aplicații pentru MCU. În baza unei scheme, am programat și testat fiecare componentă. Am demontrat schimbarea de stări al unui buton la detectarea unei acțiuni similare cu altă componentă. În proiect s-a pus accent pe numărul de recurențe per timp. Fiecare buton are programul său, iar după resetare avem un mesaj afișat, datorită implimentării mecanismul de provider per consumer.
ANEXA 1 Cod sursă. Sistem FreeRTOS #include
#include #include
#define BUTTON_PIN 13 #define BUTTON_LED_INCR 10 #define BUTTON_LED_DECR 11 #define #define #define #define #define #define int int int int int int
void void void void void
LED_PIN 4 LED_BLINK_PIN 5 LED_ON 1 LED_OFF 0 TASK_REC 2 TASK_OFFSET 5
led2Rec; ledState; led2State; buttonState; led2ReadRec; btnResetState;
GreenLEDblink( void *pvParameters ); IncDecRecLED( void *pvParameters ); PrintStates( void *pvParameters ); RedLEDstatus( void *pvParameters); Reset( void *pvParameters);
void setup() { led2Rec=0; ledState=0; led2State=0; buttonState=0; led2ReadRec = 1000; pinMode(BUTTON_LED_DECR, INPUT); pinMode(BUTTON_LED_INCR, INPUT); pinMode(LED_BLINK_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT); pinMode(LED_PIN, OUTPUT); pinMode(9, INPUT); Serial.begin(9600); xTaskCreate(GreenLEDblink, "GreenLedBlink", 128, NULL, 3, NULL); xTaskCreate(IncDecRecLED, "RecForLed", 128, NULL, 2, NULL); xTaskCreate(PrintStates, "Print", 128, NULL, 3, NULL); xTaskCreate(RedLEDstatus, "RedLED", 128, NULL, 1, NULL); xTaskCreate(Reset, "ResetEverything", 128, NULL, 3, NULL); vTaskStartScheduler(); } void loop() {
} /*--------------------------------------------------*/ /*---------------------- Tasks ---------------------*/ /*--------------------------------------------------*/
void GreenLEDblink(void *pvParameters){ (void) pvParameters;
for(;;){ if(ledState == 0) { if(led2State == 0) { led2State = 1; digitalWrite(LED_BLINK_PIN, HIGH); } else { led2State = 0; digitalWrite(LED_BLINK_PIN, LOW); } } vTaskDelay(led2ReadRec / portTICK_PERIOD_MS); } } void IncDecRecLED(void *pvParameters){ (void) pvParameters;
for(;;){ if(digitalRead(BUTTON_LED_INCR) == 0) { led2ReadRec=led2ReadRec+1000; } if(digitalRead(BUTTON_LED_DECR) == 0) { led2ReadRec=led2ReadRec-1000; } vTaskDelay(15); } } void PrintStates(void *pvParameters){ (void) pvParameters; for(;;){ Serial.println(); Serial.print("Red LED status:"); if(ledState==1){ Serial.println("ON"); } else Serial.println("OFF");
Serial.print("Green LED status:"); if(led2State==1){ Serial.println("ON"); } else Serial.println("OFF"); Serial.print("Green LED rec:"); Serial.print(led2ReadRec/1000); Serial.println("s");
vTaskDelay(1000 / portTICK_PERIOD_MS); } }
void RedLEDstatus( void *pvParameters){ (void) pvParameters;
for(;;){ buttonState = digitalRead(BUTTON_PIN); if(buttonState == 0) { if(ledState == 1) { ledState = 0; } else { ledState = 1; led2State=0; digitalWrite(LED_BLINK_PIN, LOW); } digitalWrite(LED_PIN, ledState); } vTaskDelay(15); } } void Reset(void *pvParameters){ (void) pvParameters;
for(;;){ btnResetState = digitalRead(9); if(btnResetState == 0){ led2Rec=0; ledState=0; led2State=0; digitalWrite(LED_PIN, LOW); digitalWrite(LED_BLINK_PIN, LOW); led2ReadRec = 1000; Serial.println("System Reseted!"); } vTaskDelay(35); }
}
ANEXA 2 Cod sursă. Sistem secvențial #include #include "timer-api.h" #include #define #define #define #define #define #define #define #define #define #define #define int int int int int
BUTTON_PIN 13 BUTTON_LED_INCR 10 BUTTON_LED_DECR 11 BUTTON_PRESSED 0 BUTTON_NOT_PRESSED 1 LED_PIN 4 LED_BLINK_PIN 5 LED_ON 1 LED_OFF 0 TASK_REC 2 TASK_OFFSET 5
led2Rec = 0; ledState = 0; led2State = 0; buttonState = 0; led2ReadRec = 0;
void setup() { // put your setup code here, to run once: pinMode(LED_PIN, OUTPUT); pinMode(LED_BLINK_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT); pinMode(BUTTON_LED_DECR, INPUT); pinMode(BUTTON_LED_INCR, INPUT); //timer_init_ISR_1Hz(TIMER_DEFAULT); timer_init_ISR_2Hz(TIMER_DEFAULT); Serial.begin(9600); led2Rec = TASK_OFFSET; }
void taskLedWithButton() // change led1 state when press button { buttonState = digitalRead(BUTTON_PIN); if(buttonState == BUTTON_PRESSED) { if(ledState == 1) { ledState = 0; } else {
ledState = 1; digitalWrite(LED_BLINK_PIN, LOW); } digitalWrite(LED_PIN, ledState); } } void taskLedBlink() // blinking led { if(ledState == 0) { if(led2State == 0) { led2State = 1; digitalWrite(LED_BLINK_PIN, HIGH); } else { led2State = 0; digitalWrite(LED_BLINK_PIN, LOW); } } } void taskButton2LedReadRec() // read recurency for blink led { if(digitalRead(BUTTON_LED_INCR) == BUTTON_PRESSED) { led2ReadRec++; } if(digitalRead(BUTTON_LED_DECR) == BUTTON_PRESSED) { led2ReadRec--; } } void timer_handle_interrupts(int timer) { taskLedWithButton(); taskButton2LedReadRec(); if(--led2Rec <= 0){ taskLedBlink(); led2Rec = led2ReadRec; } } void loop() { Serial.println(); Serial.print("Led state: "); Serial.println(ledState); Serial.print("Led 2 state: "); Serial.println(led2State); Serial.print("Led2 offset: "); Serial.println(led2Rec); Serial.print("Read rec for led2: "); Serial.println(led2ReadRec); delay(1000); // put your main code here, to run repeatedly: }