Queues no Nucleus SE: Introdução e Chamadas de Serviço Centrais
Veja a série RTOS Revealed
Queues foram introduzidas em artigo anterior. Elas fornecem meio mais flexível de passar mensagens simples entre tarefas que mailboxes.
Usando Queues
No Nucleus SE, queues são configuradas em tempo de build. Máximo de 16 queues podem ser definidas para aplicação. Se nenhuma queue configurada, RTOS omite todas estruturas de dados e código API relacionados a queue, mantendo binário enxuto.
Queue é simplesmente array de slots de armazenamento, cada um grande o suficiente para conter único item de dados ADDR. Acesso sincronizado para que múltiplas tarefas possam enqueue e dequeue mensagens com segurança. Tarefas podem escrever em queue até todos slots cheios, e ler de queue em ordem first-in, first-out (FIFO). Tentativas de enviar para queue cheia ou receber de vazia disparam erro ou suspensão de tarefa, dependendo das opções da API selecionadas e configuração do Nucleus SE.
Queues vs. Pipes
Nucleus SE também suporta pipes, que diferem principalmente em tamanho de mensagem. Enquanto queue transmite único ADDR (tipicamente ponteiro), pipe carrega bloco de bytes de comprimento variável; tamanho do bloco fixo em tempo de configuração. Pipes discutidos em profundidade em artigo futuro.
Configurando Queues
Número de Queues
Configuração de queue controlada por declarações #define em nuse_config.h. Configuração-chave é NUSE_QUEUE_NUMBER, que determina quantas queues habilitadas. Padrão é 0 (sem queues). Pode definir qualquer valor 0 a 16; valor fora de faixa dispara #error em tempo de compilação produzido por nuse_config_check.h.
Definir NUSE_QUEUE_NUMBER para valor não-zero ativa subsistema de queue, alocando estruturas de dados necessárias e habilitando chamadas de API associadas.
Habilitações da API
Cada função API de queue tem símbolo #define de habilitação em nuse_config.h:
NUSE_QUEUE_SEND NUSE_QUEUE_RECEIVE NUSE_QUEUE_JAM NUSE_QUEUE_RESET NUSE_QUEUE_INFORMATION NUSE_QUEUE_COUNT
Por padrão todas FALSE, desabilitando chamadas de serviço correspondentes. Para usar API particular, defina seu símbolo como TRUE. Habilitar API enquanto nenhuma queue configurada (exceto NUSE_Queue_Count(), sempre permitida) resulta em erro de compilação. Se API chamada em código não habilitado, erro de link ocorre porque implementação omitida.
#define NUSE_QUEUE_NUMBER 0 /* Número de queues no sistema – 0‑16 */ /* Service call enablers */ #define NUSE_QUEUE_SEND FALSE #define NUSE_QUEUE_RECEIVE FALSE #define NUSE_QUEUE_JAM FALSE #define NUSE_QUEUE_RESET FALSE #define NUSE_QUEUE_INFORMATION FALSE #define NUSE_QUEUE_COUNT FALSE
Chamadas de Serviço de Queue
Nucleus RTOS oferece dez chamadas de serviço relacionadas a queue, das quais seis implementadas no Nucleus SE. Elas fornecem seguinte funcionalidade:
- Enviar mensagem – NUSE_Queue_Send()
- Receber mensagem – NUSE_Queue_Receive()
- Jam mensagem para frente – NUSE_Queue_Jam()
- Resetar queue – NUSE_Queue_Reset()
- Consultar informação de queue – NUSE_Queue_Information()
- Obter número de queues configuradas – NUSE_Queue_Count()
- Chamadas restantes (create, delete, enumerate, broadcast) não disponíveis no Nucleus SE.
Implementação de cada API discutida em detalhe nas seções seguintes.
Serviços de Escrita e Leitura
Operações centrais em queue são escrita (envio) e leitura (recebimento). Escrita na frente de queue chamada jamming. Nucleus RTOS e Nucleus SE cada expõem três chamadas de API básicas para estas ações.
Escrevendo em Queue
API RTOS NU_Send_To_Queue() altamente flexível, permitindo suspensão indefinida ou timeout se queue cheia. Nucleus SE oferece mesma função mas suspensão opcional e timeouts não suportados. RTOS também suporta operação broadcast, indisponível no SE.
API RTOS: NU_Send_To_Queue()
Protótipo:
STATUS NU_Send_To_Queue(NU_QUEUE *queue, VOID *message, UNSIGNED size, UNSIGNED suspend);
Parâmetros:
- queue – ponteiro para bloco de controle de queue fornecido pelo usuário
- message – ponteiro para dados a enviar
- size – número de elementos UNSIGNED; deve corresponder ao message size da queue
- suspend – NU_NO_SUSPEND, NU_SUSPEND, ou valor de timeout
Códigos de retorno incluem NU_SUCCESS, NU_QUEUE_FULL, NU_TIMEOUT, e vários códigos de erro para ponteiros inválidos ou estado de queue.
API SE: NUSE_Queue_Send()
Protótipo:
STATUS NUSE_Queue_Send(NUSE_QUEUE queue, ADDR *message, U8 suspend);
Parâmetros:
- queue – índice da queue (ID)
- message – ponteiro para valor ADDR a enqueue
- suspend – NUSE_NO_SUSPEND ou NUSE_SUSPEND
Valores de retorno espelham função RTOS mas refletem comportamento de blocking limitado do SE.
Visão Geral da Implementação
Quando blocking desabilitado, rotina simplesmente verifica espaço e ou escreve valor ou retorna NUSE_QUEUE_FULL. Com blocking habilitado, função loopa, suspendendo tarefa se queue cheia até slot ficar disponível ou reset ocorrer. Implementação usa NUSE_Queue_Blocking_Count para rastrear tarefas bloqueadas e NUSE_Task_Blocking_Return para retomá-las quando slot abre.
if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) { return_value = NUSE_QUEUE_FULL; } else { NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] = *message; if (NUSE_Queue_Head[queue] == NUSE_Queue_Size[queue]) NUSE_Queue_Head[queue] = 0; NUSE_Queue_Items[queue]++; return_value = NUSE_SUCCESS; }
do { if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_QUEUE_FULL; } else { NUSE_Queue_Blocking_Count[queue]++; NUSE_Suspend_Task(NUSE_Task_Active, (queue << 4) | NUSE_QUEUE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) suspend = NUSE_NO_SUSPEND; } } else { NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] = *message; if (NUSE_Queue_Head[queue] == NUSE_Queue_Size[queue]) NUSE_Queue_Head[queue] = 0; NUSE_Queue_Items[queue]++; if (NUSE_Queue_Blocking_Count[queue] != 0) { U8 index; NUSE_Queue_Blocking_Count[queue]--; for (index = 0; index < NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND);
Loop continua até mensagem enfileirada com sucesso ou tarefa desbloqueada por reset. Implementação garante acesso thread-safe e wake-up eficiente de consumidores bloqueados.
Integrado
- Fechos de Came (Cam Locks) Explicados: Como Protegem Armários Discretamente
- O Que São Parafusos Olhal? Guia Profissional para Seu Design e Usos
- Entendendo Ilhós (Grommets): Tipos, Usos e Como Protegem Seus Equipamentos
- Aço Inoxidável (Stainless Steel) Explicado: Composição, Produção e Impacto Global
- Fundamentos de C#: Essenciais de Entrada e Saída
- Mailboxes no Nucleus SE: Guia Prático de Configuração e Uso
- Semáforos no Nucleus RTOS: Serviços Utilitários e Estruturas de Dados
- Semáforos no Nucleus SE: Visão Geral, Configuração e APIs Essenciais
- Dominando Grupos de Event Flags: Serviços Utilitários e Estruturas de Dados no Nucleus RTOS/SE
- Grupos de Event Flags no Nucleus SE: Guia Introdutório de Configuração e Uso da API