Tasks
Tasks são pequenos programas executados pelo sistema operacional, cada tarefa possui uma stack
reservada para ela e é gerenciada pelo sistema operacional. Notem que toda task é uma função que não retorna e possui laço infinito (while (1)
), tasks em um RTOS não devem retornar, elas executam como se estivessem exclusividade da CPU (assim como um código bare-metal que não deve retornar da função main
). A seguir um exemplo de duas tarefas.
void led_1_task(void *p) {
gpio_init(LED_PIN_R);
gpio_set_dir(LED_PIN_R, GPIO_OUT);
int delay = 250;
while (true) {
gpio_put(LED_PIN_R, 1);
vTaskDelay(pdMS_TO_TICKS(delay));
gpio_put(LED_PIN_R, 0);
vTaskDelay(pdMS_TO_TICKS(delay));
}
}
void led_2_task(void *p) {
gpio_init(LED_PIN_G);
gpio_set_dir(LED_PIN_G, GPIO_OUT);
int delay = 500;
while (true) {
gpio_put(LED_PIN_G, 1);
vTaskDelay(pdMS_TO_TICKS(delay));
gpio_put(LED_PIN_G, 0);
vTaskDelay(pdMS_TO_TICKS(delay));
}
}
vTaskDelay
A função vTaskDelay()
faz com que o RTOS libere processamento para outras tarefas durante o tempo especificado em sua chamada. Esse valor é determinado em ticks
. Podemos traduzir ticks para ms
, usando o define portTICK_PERIOD_MS
como no exemplo a seguir }
Criando uma task
Criar uma tarefa é similar ao de inicializar um programa em um sistema operacional, mas no caso devemos indicar para o RTOS quais "funções" irão se comportar como pequenos programas (tarefas). Para isso devemos chamar a função xTaskCreate
que possui a seguinte estrutura:
Leitura necess[aria]
Acesse e leia a documenta;áo do freertos sobre cria;áo de tasks:
xTaskCreate
pode ser utilizada para criar tarefas que têm acesso irrestrito a todo o mapa de memória do microcontrolador. Em sistemas que suportam MPU (Unidade de Proteção de Memória), tarefas com restrições de MPU podem ser criadas usando-se xTaskCreateRestricted
como alternativa.
A criação das tasks led_1_task
e led_2_task
são feitas da seguinte maneira (na função main
):
int main() {
stdio_init_all();
printf("Start RTOS \n");
xTaskCreate(led_1_task, "LED_Task 1", 256, NULL, 1, NULL);
xTaskCreate(led_2_task, "LED_Task 2", 256, NULL, 1, NULL);
vTaskStartScheduler();
// Programa nunca deve chegar aqui!
// vTaskStartScheduler() passa o comando do core para o FreeRTOS!
while (true)
;
}
A função xTaskCreate
possui os seguintes argumentos:
- TaskFunction_t pvTaskCode: Este é um ponteiro para a função que será executada pela tarefa. Essa função deve aderir a um protótipo específico e não retornar (ou seja, deve ser um loop infinito).
- const char* const pcName: Uma string que representa o nome da tarefa. Esse nome é útil para fins de depuração.
- uint16_t usStackDepth: O tamanho da pilha (stack) atribuída à tarefa, especificado em palavras. Isso depende do microcontrolador e da complexidade da tarefa.
- void* pvParameters: Um ponteiro para os parâmetros que a tarefa deve receber. Se a tarefa não necessitar de parâmetros, NULL pode ser passado.
- UBaseType_t uxPriority: A prioridade da tarefa. Tarefas com prioridades mais altas são executadas preferencialmente em relação às tarefas com prioridades mais baixas.
- TaskHandle_t* pvCreatedTask: Um ponteiro para uma variável do tipo
TaskHandle_t
que será preenchida com o identificador da tarefa criada. Esse identificador pode ser utilizado para se referenciar à tarefa após sua criação.
Snippets
A seguir um código bem simples de como criar duas tarefas.
#include "pico/stdlib.h"
#include <FreeRTOS.h>
#include <stdio.h>
#include <task.h>
const int LED_PIN_R = 4;
const int LED_PIN_G = 5;
void led_1_task(void *p) {
gpio_init(LED_PIN_R);
gpio_set_dir(LED_PIN_R, GPIO_OUT);
int delay = 250;
while (true) {
gpio_put(LED_PIN_R, 1);
vTaskDelay(pdMS_TO_TICKS(delay));
gpio_put(LED_PIN_R, 0);
vTaskDelay(pdMS_TO_TICKS(delay));
}
}
void led_2_task(void *p) {
gpio_init(LED_PIN_G);
gpio_set_dir(LED_PIN_G, GPIO_OUT);
int delay = 250;
while (true) {
gpio_put(LED_PIN_G, 1);
vTaskDelay(pdMS_TO_TICKS(delay));
gpio_put(LED_PIN_G, 0);
vTaskDelay(pdMS_TO_TICKS(delay));
}
}
int main() {
stdio_init_all();
printf("Start RTOS \n");
xTaskCreate(led_1_task, "LED_Task 1", 256, NULL, 1, NULL);
xTaskCreate(led_2_task, "LED_Task 2", 256, NULL, 1, NULL);
vTaskStartScheduler();
while (true)
;
}