RTOS: Uso de Queue para sincronização e comunicação de tarefas

Este post faz parte da série RTOS

Os semáforos que vimos no artigo anterior permitem a sincronização de tarefas e uma simples comunicação entre elas com apenas valores binários. Mas se seu projeto precisa de algo mais complexo para sincronização ou comunicação entre tarefas e ISRs, pode ser a vez da Queue.

O que é uma Queue e como funciona?

Queue é um buffer, uma fila de dados no formato FIFO, que permite sincronização de tarefas, como vimos em semáforos, porém é mais utilizada para comunicação entre tarefas e ISRs onde precisamos enviar valores (variáveis) para outros lugares. Usar queues visa a diminuição de variáveis globais em seu código. Mesmo ele sendo um objeto global, conta com métodos de atomicidade e timeout que podem agregar uma dinâmica muito interessante em seu projeto e produto.

Uso do Queue tipo FIFO.
Figura 1 – FIFO.
Animação de uma Queue FIFO.
Figura 2 – Animação de uma Queue FIFO.

A queue funciona na forma de um buffer FIFO, mas há funções que permitem escrever no começo do buffer em vez de apenas no fim. É tão simples que com a figura 3 já podemos entender o funcionamento da queue e testar na prática!

Escrita e leitura da queue.
Figura 3 – Escrita e leitura da queue.

As queues do FreeRTOS são objetos com capacidade e comprimento fixo. Como o exemplo da figura 3, a queue foi criada com 5 “espaços” (slots) e 2 bytes por slot. Isso implica na forma e frequência em que a queue será utilizada. Ela deve atender o tamanho máximo de suas variáveis e também ter comprimento considerável para evitar que fique lotada (a menos que seja proposital, como nas “MailBox”). Apesar da queue também funcionar para sincronização de tarefas como vimos em semáforos, o foco dessa prática será unicamente na transferência de dados entre duas tarefas. Então vamos começar!

Código do projeto:

#include <driver/gpio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <esp_system.h>
#include <esp_log.h>

QueueHandle_t buffer;//Objeto da queue

void t1(void*z)
{
    uint32_t snd = 0;
    while(1)
    {
        if (snd < 15)//se menor que 15
        {
            xQueueSend(buffer, &snd, pdMS_TO_TICKS(0));//Envia a variavel para queue
            snd++;//incrementa a variavel
        }
        else//se nao, espera 5seg para testar o timeout da outra tarefa
        {
            vTaskDelay(pdMS_TO_TICKS(5000));
            snd = 0;
        }

        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

void t2(void*z)
{
    uint32_t rcv = 0;
    while(1)
    {
        if (xQueueReceive(buffer, &rcv, pdMS_TO_TICKS(1000)) == true)//Se recebeu o valor dentro de 1seg (timeout), mostrara na tela
        {
            ESP_LOGI("Queue", "Item recebido: %u", rcv);//Mostra o valor recebido na tela
        }
        else
        {
            ESP_LOGE("Queue", "Item nao recebido, timeout expirou!");//Se o timeout expirou, mostra erro
        }
    }
}

void app_main()
{
    buffer = xQueueCreate(10, sizeof(uint32_t));//Cria a queue *buffer* com 10 slots de 4 Bytes

    xTaskCreatePinnedToCore(t1, "t1", 4096, NULL, 1, NULL, 0);//Cria a tarefa que escreve valores na queue
    xTaskCreatePinnedToCore(t2, "t2", 4096, NULL, 1, NULL, 0);//Cria a tarefa que le valores da queue
}
Tarefas se comunicando por Queues.
Figura 4 – Tarefas se comunicando por Queues.

Testando o código, podemos observar que enquanto a tarefa responsável por enviar variáveis (t1) envia valores abaixo de 15, a outra tarefa (t2) mostra o valor recebido na tela. Porém, quando t1 chega no número 15, entra em delay por 5 segundos, ocasionando no timeout da leitura na t2, mostrando na tela que o timeout de 1 segundo expirou.

Queues podem tanto funcionar como um tipo especial de semáforos, onde podemos analisar valores recebidos e sincronizar tarefas a partir disso, como também, e principalmente, efetuar a comunicação entre tarefas e ISRs.

Saiba mais

Desenvolvendo com o Zephyr RTOS: Controlando o Kernel

Primeiras impressões com o react.o

Fila circular para sistemas embarcados

Referências

https://freertos.org/Documentation/RTOS_book.html
https://esp-idf.readthedocs.io/en/latest/api-reference/system/freertos.html

RTOS

RTOS: Semáforos para sincronização de tarefas RTOS: Uso de grupo de eventos para sincronização de tarefas
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
6 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Marcos Félix
Marcos Félix
12/03/2019 07:54

Bom dia, José Morais, como faço para entrar em contato com você?

Yuri Lima
09/08/2018 23:24

Opa. Morais, blzz cara!!! ?

Cara continuar nessa abordagem de fila, acredito que tenha bastante assunto para abordar ainda. Eu venho acompanhando seus posts e acho muito significativo. Parabéns pela iniciativa. CONTINUA!!!!!!!

José Morais
José Morais
Reply to  Yuri Lima
10/08/2018 08:01

Opa! O plano inicial era parar por aqui, mas acho que vou continuar com “eventos”, “software timer” e assim por diante…

Yuri Lima
Reply to  José Morais
13/08/2018 10:40

Show de bola cara. VLWW

welington souza
welington souza
Reply to  José Morais
31/10/2018 07:59

Não para não, está muito interessante! Está muito bom!!

Home » Software » RTOS: Uso de Queue para sincronização e comunicação de tarefas

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: