Complete o código baseado no sistema operacional FREERTOS abaixo de forma que os níveis lógicos nos pinos RD1, RD2, RD3 e RD4 sejam alternados a cada
e 300 ms respectivamente, como na questão 1. No caso do pino RD5, o mesmo só deverá apresentar nível lógico 1 se o botão no pino RBO estiver pressionado (nível lógico 0), sendo que a verificação do botão deverá ocorrer a cada 150 ms . (0,50 pontos)
Obs: em cada tarefa só pode ser relacionado um pino de I/O.
void main( void ){
TRISD=0b00000000;
TRISB=0b00000001;
xTaskCreate(vTASK0,(const char * const)"T0",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK ,(const char * const)"T1",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+ ), NULL);
xTaskCreate(vTASK ,(const char * const)"T2",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+ ), NULL);
xTaskCreate(vTASK ,(const char * const)"T3",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+ ), NULL);
xTaskCreate(vTASK ,(const char * const)"T4",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+ ), NULL);
vTaskStartScheduler();
}
void vTASKO(){
while(1) {
PORTDbits.RD1=! PORTDbits.RD1;
vTaskDelay(200/portTICK_RATE_MS);
}
}
Obs: em cada tarefa só pode ser relacionado um pino de I/O.
void main( void ){
TRISD=0b00000000;
TRISB=0b00000001;
xTaskCreate(vTASK0,(const char * const)"T0",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK ,(const char * const)"T1",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+ ), NULL);
xTaskCreate(vTASK ,(const char * const)"T2",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+ ), NULL);
xTaskCreate(vTASK ,(const char * const)"T3",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+ ), NULL);
xTaskCreate(vTASK ,(const char * const)"T4",configMINIMAL_STACK_SIZE,NULL,(tskIDLE_PRIORITY+ ), NULL);
vTaskStartScheduler();
}
void vTASKO(){
while(1) {
PORTDbits.RD1=! PORTDbits.RD1;
vTaskDelay(200/portTICK_RATE_MS);
}
}
Passo 1
O enunciado pede que criemos cinco tarefas no FreeRTOS, cada uma cuidando de um único pino de saída em PORTD ou de leitura em PORTB, com as seguintes características:
- vTASK0 alterna RD1 a cada 200 ms (já dada).
- vTASK1 alterna RD2 a cada 600 ms.
- vTASK2 alterna RD3 a cada 300 ms.
- vTASK3 alterna RD4 a cada 300 ms.
- vTASK4 verifica RB0 a cada 150 ms e, se estiver pressionado (nível lógico 0), coloca RD5 = 1; caso contrário, RD5 = 0.
Vamos completar as chamadas a xTaskCreate e implementar vTASK1…vTASK4.
Passo 2
Preencher as chamadas a xTaskCreate, usando a mesma prioridade para todas as tarefas:
xTaskCreate(vTASK0, "T0", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK1, "T1", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK2, "T2", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK3, "T3", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK4, "T4", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
vTaskStartScheduler();
Passo 3
Implementar as tarefas que alternam pinos RD2, RD3 e RD4 nos períodos especificados:
void vTASK1(void *pvParameters)
{
(void) pvParameters;
for(;;) {
PORTDbits.RD2 = !PORTDbits.RD2;
vTaskDelay(600 / portTICK_RATE_MS);
}
}
void vTASK2(void *pvParameters)
{
(void) pvParameters;
for(;;) {
PORTDbits.RD3 = !PORTDbits.RD3;
vTaskDelay(300 / portTICK_RATE_MS);
}
}
void vTASK3(void *pvParameters)
{
(void) pvParameters;
for(;;) {
PORTDbits.RD4 = !PORTDbits.RD4;
vTaskDelay(300 / portTICK_RATE_MS);
}
}
Passo 4
Implementar a tarefa que monitora o botão em RB0 a cada 150 ms e aciona RD5:
void vTASK4(void *pvParameters)
{
(void) pvParameters;
for(;;) {
if(PORTBbits.RB0 == 0) { // botão pressionado
PORTDbits.RD5 = 1;
} else {
PORTDbits.RD5 = 0;
}
vTaskDelay(150 / portTICK_RATE_MS);
}
}
Resposta
#include "FreeRTOS.h"
#include "task.h"
void vTASK0(void *pvParameters)
{
(void) pvParameters;
for(;;) {
PORTDbits.RD1 = !PORTDbits.RD1;
vTaskDelay(200 / portTICK_RATE_MS);
}
}
void vTASK1(void *pvParameters)
{
(void) pvParameters;
for(;;) {
PORTDbits.RD2 = !PORTDbits.RD2;
vTaskDelay(600 / portTICK_RATE_MS);
}
}
void vTASK2(void *pvParameters)
{
(void) pvParameters;
for(;;) {
PORTDbits.RD3 = !PORTDbits.RD3;
vTaskDelay(300 / portTICK_RATE_MS);
}
}
void vTASK3(void *pvParameters)
{
(void) pvParameters;
for(;;) {
PORTDbits.RD4 = !PORTDbits.RD4;
vTaskDelay(300 / portTICK_RATE_MS);
}
}
void vTASK4(void *pvParameters)
{
(void) pvParameters;
for(;;) {
if(PORTBbits.RB0 == 0) { // botão pressionado
PORTDbits.RD5 = 1;
} else {
PORTDbits.RD5 = 0;
}
vTaskDelay(150 / portTICK_RATE_MS);
}
}
void main(void)
{
TRISD = 0b00000000; // RD1..RD5 como saída
TRISB = 0b00000001; // RB0 como entrada
xTaskCreate(vTASK0, "T0", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK1, "T1", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK2, "T2", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK3, "T3", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
xTaskCreate(vTASK4, "T4", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY+1), NULL);
vTaskStartScheduler();
for(;;); // Não deve chegar aqui
}