/*
Atividade da disciplina de Sistemas de Tempo Real
video do INPE sobre Semaforos
Aluno: André Penha Soares Silva
Matrícula: 20212EE0013
*/
/*Biblioteca do Arduino*/
#include <Arduino.h>
/*Bibliotecas FreeRTOS */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
//protótipos das tarefas
void tarefa(void* parametro);
void gerenciador(void* parametro);
//declaracao dos handles das tarefas
TaskHandle_t tarefa1 = NULL;
TaskHandle_t tarefa2 = NULL;
//Declaração da handel do semáforo
SemaphoreHandle_t semaforoSerial;
void setup() {
//Serial.begin(115200);
Serial.begin(300); // teste em 300bps para verificar as tarefas disputando o uso do recurso da porta serial
//Criação do Semáforo
semaforoSerial = xSemaphoreCreateMutex();
Serial.println("Hello, ESP32!");
xTaskCreatePinnedToCore(
tarefa, //função executada
"Tarefa 1", //nome da tarefa
1000, //stack alocada para a tarefa
NULL, //parâmetro passado para a tarefa
1, //prioridade da tarefa
&tarefa1, //handle da tarefa
APP_CPU_NUM //processador que irá executar a tarefa
);
xTaskCreatePinnedToCore(
tarefa, //função executada
"Tarefa 2", //nome da tarefa
1000, //stack alocada para a tarefa
NULL, //parâmetro passado para a tarefa
1, //prioridade da tarefa
&tarefa2, //handle da tarefa
APP_CPU_NUM //processador que irá executar a tarefa
);
xTaskCreatePinnedToCore(
gerenciador, //funcao executada
"Gerenciador ", //nome da tarefa
1000, //stack alocada para a tarefa
NULL, //parametro passado para a tarefa
2, //prioridade da tarefa
NULL, //handle da tarefa
APP_CPU_NUM //processador que irá executar a tarefa
);
}
void loop() {
vTaskDelete(NULL);
}
void gerenciador(void* parametro) {
while(1){
vTaskDelay(15000);
if (tarefa1 == NULL || tarefa2 == NULL){
if(xSemaphoreTake(semaforoSerial, portMAX_DELAY)) {
Serial.println("Handle nulo.");
xSemaphoreGive(semaforoSerial);
}
} else {
if (xSemaphoreTake(semaforoSerial, portMAX_DELAY)){
vTaskSuspend(tarefa2);
Serial.println("Tarefa 2 Suspensa");
xSemaphoreGive(semaforoSerial);
}
vTaskDelay(15000);
if (xSemaphoreTake(semaforoSerial, portMAX_DELAY)){
vTaskSuspend(tarefa1);
vTaskResume(tarefa2);
Serial.println("Tarefa 1 suspena, Tarefa 2 Retomada");
xSemaphoreGive(semaforoSerial);
}
vTaskDelay(15000);
if (xSemaphoreTake(semaforoSerial, portMAX_DELAY)){
vTaskResume(tarefa1);
Serial.println("Tarefa 1 retomada");
xSemaphoreGive(semaforoSerial);
}
}
}
}
void tarefa(void* parametro){
while(1){
if (xSemaphoreTake(semaforoSerial,portMAX_DELAY)){
Serial.print(pcTaskGetTaskName(NULL)); //o nome da tarefa em execucao
Serial.print(" executando no core:");
Serial.print(xPortGetCoreID()); //identicar o core que tá executando a tarefa
Serial.print(" .");
Serial.print(uxTaskGetStackHighWaterMark(NULL)); //informar o numero de bytes disponivies na stack
Serial.println(" bytes livres na stack");
xSemaphoreGive(semaforoSerial);
}
}
}
/*
ao rodar, inicialmente as tarefas 1 e 2 ficam alternado a execucao
depois de 5s apenas a tarefa 1 fica sendo executada (pois a tarefa 2 foi suspensa)
apos 5s apenas a tarefa 2 fica sendo executada (pois a tarefa 1 foi suspensa)
apos mais 5s as duas tarefas voltam a entrar em execucao
depois, trocar a velocidade da comunicacao serial de 115200 bps para 300 bps
e rodar novamente, vai dá para obsercar a escrita da serial hora com a tarefa 1 escrevendo
e sendo interrompida pela tarefa 2, ja que o recurso em comum usados pelas tarefas nao
foi gerenciado usando um semáforo
*/