Toda a verdade sobre o RTOS. Artigo 25. Canais de Dados: Introdução e Serviços Básicos



Após um breve intervalo, continuamos a publicar traduções de The Whole Truth About RTOS de Colin Walls. Desta vez, falaremos sobre os canais de transmissão de dados (doravante referidos como canais), que já foram mencionados em um dos artigos anteriores, principalmente no item 5 . Canais, em comparação com caixas de correio ( nº 21 e nº 22 ) ou filas ( nº 23 e nº 24 ), oferecem uma maneira mais flexível de transferir mensagens simples entre tarefas.

Artigos anteriores da série:

Artigo 24. Filas: serviços auxiliares e estruturas de dados
Artigo 23. Filas: introdução e serviços básicos
Artigo 22. Caixas de correio: serviços auxiliares e estruturas de dados
Artigo 21. Caixas de correio: Introdução e serviços básicos
Artigo 20. Semáforos: Serviços Auxiliares e Estruturas de Dados
Artigo 19. Semáforos: introdução e serviços básicos
Artigo # 18 Grupos de Sinalizadores de Eventos: Serviços Auxiliares e Estruturas de Dados
Artigo 17. Grupos de Sinalizadores de Eventos: Introdução e Serviços Básicos
Artigo 16. Signals
Artigo 15. Partições de memória: serviços e estruturas de dados
Artigo 14. Seções de memória: introdução e serviços básicos
Artigo 13. Estruturas de dados da tarefa e chamadas de API não suportadas
Artigo 12. Serviços para trabalhar com tarefas
Artigo 11. Tarefas: configuração e introdução à API
Artigo 10. Agendador: recursos avançados e preservação de contexto
Artigo 9. Agendador: implementação
Artigo 8. Núcleo SE: Projeto Interno e Implantação
Artigo # 7 Núcleo SE: Introdução
Artigo 6. Outros serviços RTOS
Artigo 5. Interação e sincronização de tarefas
Artigo 4. Tarefas, alternância de contexto e interrupções
Artigo # 3 Tarefas e planejamento
Artigo 2. RTOS: estrutura e modo em tempo real
Artigo 1. RTOS: introdução.

Usando canais


No Nucleus SE, os canais são identificados durante a fase de montagem. Cada aplicativo pode ter até 16 canais. Se nenhum canal estiver configurado no aplicativo, nem as estruturas de dados nem os códigos de chamada de serviço relacionados aos canais serão incluídos no aplicativo.

Canal de transmissão de dados - um conjunto de armazenamentos, cujo tamanho permite colocar um elemento de dados de comprimento especificado pelo usuário em bytes. O acesso aos dados é controlado de maneira que várias tarefas possam ser usadas com segurança. As tarefas podem gravar dados no canal até que todas as áreas estejam cheias. As tarefas podem ler dados do canal e os dados são recebidos de acordo com o princípio FIFO. Tentar gravar em um canal lotado ou ler um canal vazio pode resultar em erro ou suspensão da tarefa, dependendo das configurações de chamada da API selecionadas e da configuração do Nucleus SE.

Canais e Filas


O Nucleus SE também suporta filas que foram discutidas em detalhes em artigos anteriores (nº 23 e nº 24). A principal diferença entre canais e filas é o tamanho da mensagem. As filas contêm mensagens que consistem em uma única variável do tipo ADDR, geralmente ponteiros. O canal contém mensagens de tamanho arbitrário, individuais para cada canal no aplicativo e atribuídas durante as configurações dos parâmetros.

Configuração do canal


Número de canais


Como na maioria dos objetos do Nucleus SE, a personalização do canal é controlada pelas diretivas #define em nuse_config.h . O parâmetro principal é NUSE_PIPE_NUMBER , que determina o número de canais configurados no aplicativo. Por padrão, esse valor é zero (ou seja, não há canais no aplicativo) e pode levar valores até 16. Um valor incorreto levará a um erro de compilação, que será gerado pela verificação no arquivo nuse_config_check.h (esse arquivo está incluído no nuse_config.c e compila junto com ele), que acionará a diretiva #error .

A seleção de um valor diferente de zero serve como o principal ativador dos canais. Este parâmetro é usado para determinar estruturas de dados e seu tamanho depende de seu valor (mais sobre isso no próximo artigo). Além disso, um valor diferente de zero ativa as configurações da API.

Ativar chamadas de API


Cada função de API (chamada de utilitário) no Nucleus SE possui uma diretiva #define de ativação em nuse_config.h . Para canais, esses símbolos são:

NUSE_PIPE_SEND
NUSE_PIPE_RECEIVE
NUSE_PIPE_JAM
NUSE_PIPE_RESET
NUSE_PIPE_INFORMATION
NUSE_PIPE_COUNT

Por padrão, eles são definidos como FALSE , portanto, todas as chamadas de serviço são desativadas, bloqueando a inclusão do código que as implementa. Para configurar canais no aplicativo, você precisa selecionar as chamadas de serviço da API necessárias e configurá-las como TRUE .

A seguir, um trecho de código do arquivo nuse_config.h padrão.

#define NUSE_PIPE_NUMBER 0 /* Number of pipes in the system - 0-16 */ /* Service call enablers */ #define NUSE_PIPE_SEND FALSE #define NUSE_PIPE_RECEIVE FALSE #define NUSE_PIPE_JAM FALSE #define NUSE_PIPE_RESET FALSE #define NUSE_PIPE_INFORMATION FALSE #define NUSE_PIPE_COUNT FALSE 

Se as funções da API estiverem ativadas, mas não houver canais no aplicativo (exceto NUSE_Pipe_Count () , que sempre está ativado), ocorrerá um erro de compilação. Se o seu código usar uma chamada de API que não foi ativada, ocorrerá um erro de layout porque o código de implementação não foi incluído no aplicativo.

Chamadas de canal indiretas


O núcleo RTOS suporta dez sobrecargas de canal que fornecem a seguinte funcionalidade:

  • Enviando uma mensagem para o canal. O núcleo SE é implementado na função NUSE_Pipe_Send () .
  • Receba mensagens do canal. O núcleo SE é implementado na função NUSE_Pipe_Receive () .
  • Envie uma mensagem para o topo do canal. O núcleo SE é implementado em NUSE_Pipe_Jam () .
  • Restaurando o canal para um estado não utilizado com a liberação de todas as tarefas suspensas (redefinição). No Nucleus SE, implementado em NUSE_Pipe_Reset () .
  • Obtendo informações sobre um canal específico. O Núcleo SE é implementado usando NUSE_Pipe_Information () .
  • Retorna o contador dos canais atualmente configurados no aplicativo. O Núcleo SE é implementado usando NUSE_Pipe_Count () .
  • Adicionando um novo canal ao aplicativo (criação). Não implementado no Nucleus SE.
  • Removendo um canal de um aplicativo. Não implementado no Nucleus SE.
  • Retorne os ponteiros para todos os canais no aplicativo. Não implementado no Nucleus SE.
  • Enviando uma mensagem para todas as tarefas suspensas no canal (transmissão). Não implementado no Nucleus SE.

Considere a implementação de cada uma dessas chamadas de serviço com mais detalhes.

Chamadas de serviço para escrever e ler de canais


As operações básicas executadas nos canais são de gravação (também chamada de envio) e leitura (também conhecidas como recebimento de mensagens). Além disso, é possível gravar dados no início do canal (interferência). O Nucleus RTOS e o Nucleus SE fornecem três chamadas principais de API para essas operações, que serão discutidas abaixo.

Gravação de canal


A chamada do utilitário da API Nucleus RTOS para gravar no canal é muito flexível, o que permite suspender tarefas implicitamente ou com um tempo limite se a operação não puder ser concluída imediatamente (por exemplo, ao tentar gravar em um canal lotado). O Núcleo SE tem um desafio semelhante, mas a pausa da tarefa é opcional e o tempo limite não é implementado.

O Nucleus RTOS também fornece um serviço de transmissão de canal, mas não é suportado no Nucleus SE. Ele será descrito na seção Chamadas de API não realizadas do próximo artigo.

Ligue para enviar mensagens para um canal no Nucleus RTOS

Protótipo de chamada de serviço:

STATUS NU_Send_To_Pipe (NU_PIPE * canal, mensagem VOID *, tamanho NÃO ASSINADO, suspensão NÃO ASSINADA);

Parâmetros:

pipe - um ponteiro para o bloco de controle de canal fornecido pelo usuário;
message - ponteiro para a mensagem a ser enviada;
tamanho - o número de bytes na mensagem. Se o canal suportar mensagens de tamanho variável, esse parâmetro deverá ser igual ou menor que o tamanho da mensagem suportada pelo canal. Se o canal suportar mensagens de tamanho fixo, esse parâmetro deverá ser igual ao tamanho da mensagem suportada pelo canal;
suspender - a especificação de suspensão da tarefa, pode assumir os valores NU_NO_SUSPEND , NU_SUSPEND ou o valor do tempo limite.

Valor de retorno:

NUSE_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_PIPE - ponteiro inválido para o canal;
NU_INVALID_POINTER - ponteiro nulo para uma mensagem ( NULL );
NU_INVALID_SIZE - o tamanho da mensagem não é compatível com o tamanho da mensagem suportado pelo canal;
NU_INVALID_SUSPEND - tente suspender de um thread não relacionado à tarefa;
NU_PIPE_FULL - o canal está cheio e o tipo de suspensão da tarefa não foi especificado;
NU_TIMEOUT - o canal está cheio mesmo depois que a tarefa é suspensa por um período especificado;
NU_PIPE_DELETED - o canal foi excluído enquanto a tarefa estava suspensa;
NU_PIPE_RESET - O canal foi redefinido enquanto a tarefa estava suspensa.

Ligue para enviar mensagens para um canal no Nucleus SE

Esta chamada de serviço da API suporta a funcionalidade principal da API Nucleus RTOS.

Protótipo de chamada de serviço:

STATUS NUSE_Pipe_Send (canal NUSE_PIPE, mensagem U8 *, suspensão U8);

Parâmetros:

pipe - index (ID) do canal usado;
message - um ponteiro para a mensagem a ser enviada (uma sequência de bytes de comprimento permitida para um determinado canal);
suspender - a especificação de suspensão da tarefa, pode assumir os valores NUSE_NO_SUSPEND e NUSE_SUSPEND .

Valor de retorno:

NUSE_SUCCESS - a chamada foi concluída com sucesso;
NUSE_INVALID_PIPE - índice de canal inválido;
NUSE_INVALID_POINTER - ponteiro nulo para uma mensagem ( NULL );
NUSE_INVALID_SUSPEND - tente suspender de um thread não relacionado à tarefa ou quando o bloqueio de tarefas estiver desativado;
NUSE_PIPE_FULL - o canal está cheio e o tipo de suspensão da tarefa não foi especificado;
NUSE_PIPE_WAS_RESET - O canal foi redefinido enquanto a tarefa estava suspensa.

Implementando postagem de canal no Nucleus SE

A versão do código de função da API NUSE_Pipe_Send () (após verificar os parâmetros) é selecionada usando a compilação condicional, dependendo se o suporte a chamadas da API está ativado para bloquear (pausar) tarefas ou não. Abaixo, consideramos as duas opções.

Se o bloqueio estiver desativado, o código para esta chamada de API é bastante simples:

 if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { return_value = NUSE_PIPE_FULL; } else /* pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS; } 

A função verifica se há espaço livre no canal e usa o índice NUSE_Pipe_Head [] para colocar a mensagem na área de dados do canal.

Se o bloqueio de tarefas estiver ativado, o código se tornará mais complexo:

 do { if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_FULL; } else { /* block task */ NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else /* pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; /* check whether a task is blocked on this pipe */ NUSE_Pipe_Blocking_Count[pipe]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

Alguns esclarecimentos podem ser úteis.

O código é colocado em um loop do ... while , que é executado enquanto o parâmetro de pausa da tarefa é NUSE_SUSPEND .

Se o canal estiver cheio e o parâmetro de suspensão for NUSE_NO_SUSPEND , a chamada da API termina com o valor NUSE_PIPE_FULL . Se o parâmetro de suspensão for NUSE_SUSPEND , a tarefa será interrompida. Após a conclusão (ou seja, quando a tarefa é retomada), se o valor de retorno for NUSE_SUCCESS , ou seja, a tarefa foi retomada porque a mensagem foi lida (e não porque o canal foi redefinido), o código retornará ao início do loop.

Se o canal não estiver cheio, a mensagem fornecida será salva usando o índice NUSE_Pipe_Head [] na área de dados do canal. Ele verifica se o canal pausou tarefas (mensagens pendentes). Se houver tais tarefas, a primeira delas será retomada. A variável de suspensão está definida como NUSE_NO_SUSPEND e a chamada da API é concluída com o valor NUSE_SUCCESS .

Lendo do canal


A chamada do utilitário Nucleus RTOS API para leitura do canal é muito flexível, o que permite pausar tarefas implicitamente ou com um tempo limite se a operação não puder ser concluída imediatamente (por exemplo, quando você tenta ler um canal vazio). O Nucleus SE tem uma chamada de utilitário semelhante, mas a pausa da tarefa é opcional e um tempo limite não é implementado.

Desafio de leitura de canal no núcleo RTOS

Protótipo de chamada de serviço:

STATUS NU_Receive_From_Pipe (canal NU_PIPE *, mensagem VOID *, tamanho NÃO ASSINADO, NÃO ASSINADO, NÃO ASSINADO * tamanho real, suspensão NÃO ASSINADA);

Parâmetros:

pipe - um ponteiro para o bloco de controle de canal fornecido pelo usuário;
mensagem - um ponteiro para o armazenamento da mensagem recebida;
tamanho - o número de bytes na mensagem. Deve corresponder ao tamanho da mensagem especificado ao criar o canal;
suspender - a especificação de suspensão da tarefa, pode levar NU_NO_SUSPEND , NU_SUSPEND ou valores de tempo limite.

Valor de retorno:

NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_PIPE - ponteiro inválido para o canal;
NU_INVALID_POINTER - ponteiro nulo para uma mensagem ( NULL );
NU_INVALID_SUSPEND - tente pausar uma tarefa de um thread não associado à tarefa;
NU_PIPE_EMPTY - o canal está vazio e o tipo de suspensão da tarefa não foi especificado;
NU_TIMEOUT - o canal está vazio mesmo depois que a tarefa é suspensa pelo valor de tempo limite especificado;
NU_PIPE_DELETED - o canal foi excluído enquanto a tarefa estava suspensa;
NU_PIPE_RESET - O canal foi excluído enquanto a tarefa estava suspensa.

Desafio de leitura de canal no Nucleus SE

Esta chamada de serviço da API suporta a funcionalidade principal da API Nucleus RTOS.

Protótipo de chamada de serviço:

STATUS NUSE_Pipe_Receive (canal NUSE_PIPE, mensagem U8 *, suspensão U8);

Parâmetros:

pipe - index (ID) do canal usado;
message - ponteiro para o armazenamento da mensagem recebida (uma sequência de bytes, cujo comprimento coincide com o tamanho da mensagem do canal);
suspender - a especificação de suspensão da tarefa, pode assumir os valores NUSE_NO_SUSPEND e NU_SUSPEND .

Valor de retorno:

NUSE_SUCCESS - a chamada foi concluída com sucesso;
NUSE_INVALID_PIPE - índice de canal inválido;
NUSE_INVALID_POINTER - ponteiro nulo para uma mensagem ( NULL );
NUSE_INVALID_SUSPEND - uma tentativa de suspender uma tarefa de um encadeamento não associado à tarefa ou com o suporte à suspensão de tarefas desabilitado;
NUSE_PIPE_EMPTY - o canal está vazio e o tipo de suspensão da tarefa não foi especificado;
NUSE_PIPE_WAS_RESET - O canal foi redefinido enquanto a tarefa estava suspensa.

Implementando o leitor de feeds no Nucleus SE

A versão do código de função da API NUSE_Pipe_Receive () (após verificar os parâmetros) é selecionada por compilação condicional, dependendo se o suporte para chamadas da API para bloquear (suspender tarefas) está ativado ou não. Vamos considerar as duas opções abaixo.

Se o bloqueio estiver desativado, o código para esta chamada de API é bastante simples:

 if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty */ { return_value = NUSE_PIPE_EMPTY; } else { /* message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]--; *actual_size = msgsize; return_value = NUSE_SUCCESS; } 

A função verifica uma mensagem no canal e usa o índice NUSE_Pipe_Tail [] para recuperar a mensagem da área de dados do canal e retorna os dados pelo ponteiro da mensagem.

Se o bloqueio de tarefas estiver ativado, o código se tornará mais complexo:

 do { if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_EMPTY; } else { /* block task */ NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else { /* message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]--; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; /* check whether a task is blocked */ /* on this pipe */ NUSE_Pipe_Blocking_Count[pipe]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } *actual_size = msgsize; return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

Alguns esclarecimentos podem ser úteis.

O código é colocado em um loop do ... while , que é executado enquanto o parâmetro de pausa da tarefa é NUSE_SUSPEND .

Se o canal estiver vazio e o parâmetro de suspensão for NUSE_NO_SUSPEND , a chamada da API termina com o valor NUSE_PIPE_EMPTY . Se o parâmetro de suspensão for NUSE_SUSPEND , a tarefa será interrompida. Após a conclusão (ou seja, quando a tarefa é retomada), se o valor de retorno for NUSE_SUCCESS , ou seja, a tarefa foi retomada porque a mensagem foi enviada (e não porque o canal foi redefinido), o código retornará ao início do loop.

Se o canal contiver mensagens, a mensagem armazenada será retornada usando o índice NUSE_Pipe_Tail [] . Verifica se há alguma tarefa pausada (aguardando envio) neste canal. Se houver tais tarefas, a primeira delas será retomada. A variável de suspensão está definida como NUSE_NO_SUSPEND e a chamada da API termina com o código NUSE_SUCCESS .

Grave no início do canal


A chamada do utilitário Nucleus RTOS API para gravar no início do canal é muito flexível, o que permite pausar tarefas implicitamente ou com um tempo limite se a operação não puder ser concluída imediatamente (por exemplo, ao tentar gravar em um canal completo). O Nucleus SE tem uma chamada de utilitário semelhante, mas a pausa da tarefa é opcional e um tempo limite não é implementado.

Ligue para escrever para o início do canal no Nucleus RTOS

Protótipo de chamada de serviço:

STATUS NU_Send_To_Front_Of_Pipe (canal NU_PIPE *, mensagem VOID *, tamanho NÃO ASSINADO, suspensão NÃO ASSINADA);

Parâmetros:

pipe - um ponteiro para o bloco de controle de canal fornecido pelo usuário;
message - ponteiro para a mensagem a ser enviada;
tamanho - o número de bytes na mensagem. Se o canal suportar mensagens de tamanho variável, esse parâmetro deverá ser igual ou menor que o tamanho da mensagem suportada pelo canal. Se o canal suportar mensagens de tamanho fixo, esse parâmetro deverá corresponder ao tamanho da mensagem suportada pelo canal;
suspender - a especificação de suspensão da tarefa pode levar NU_NO_SUSPEND , NU_SUSPEND ou valores de tempo limite.

Valor de retorno:

NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_PIPE - ponteiro inválido para o canal;
NU_INVALID_POINTER - ponteiro nulo para uma mensagem ( NULL );
NU_INVALID_SIZE - o tamanho da mensagem é incompatível com o tamanho da mensagem suportado pelo canal;
NU_INVALID_SUSPEND - tente suspender de um thread não relacionado à tarefa
NU_PIPE_FULL - o canal está cheio e o tipo de suspensão da tarefa não foi especificado;
NU_TIMEOUT - o canal está cheio mesmo depois que a tarefa é suspensa por um período especificado;
NU_PIPE_DELETED - o canal foi excluído enquanto a tarefa estava suspensa;
NU_PIPE_RESET - O canal foi redefinido enquanto a tarefa estava suspensa.

Ligue para escrever para o início do canal no Nucleus SE

Essa chamada de utilitário suporta a funcionalidade principal da API Nucleus RTOS.

Protótipo de chamada de serviço:

STATUS NUSE_Pipe_Jam (canal NUSE_PIPE, mensagem ADDR *, suspensão U8);

Parâmetros:

pipe - index (ID) do canal usado;
message - um ponteiro para a mensagem a ser enviada, que é uma sequência de bytes igual ao tamanho da mensagem configurada no canal;
suspender - a especificação de suspensão da tarefa pode ser NUSE_NO_SUSPEND ou NUSE_SUSPEND .

Valor de retorno:

NUSE_SUCCESS - a chamada foi concluída com sucesso;
NUSE_INVALID_PIPE - índice de canal inválido;
NUSE_INVALID_POINTER - ponteiro nulo para uma mensagem ( NULL );
NUSE_INVALID_SUSPEND - uma tentativa de suspender uma tarefa de um encadeamento não associado à tarefa ou quando o bloqueio da tarefa está desativado;
NUSE_PIPE_FULL - o canal está cheio e o tipo de suspensão da tarefa não foi especificado;
NUSE_PIPE_WAS_RESET - O canal foi redefinido enquanto a tarefa estava suspensa.

Implementando a gravação de entrada de canal no Nucleus SE

O código variante da função NUSE_Pipe_Jam () é muito semelhante ao NUSE_Pipe_Send () , exceto que o índice NUSE_Pipe_Tail [] é usado para armazenar dados, portanto:

 if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { return_value = NUSE_PIPE_FULL; } else /* pipe element available */ { if (NUSE_Pipe_Tail[pipe] == 0) { NUSE_Pipe_Tail[pipe] = (NUSE_Pipe_Size[pipe] - 1) * msgsize; } else { NUSE_Pipe_Tail[pipe] -= msgsize; } data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS; } 

No próximo artigo, consideraremos chamadas de serviço adicionais relacionadas a canais, bem como as estruturas de dados correspondentes.

Sobre o autor: Colin Walls trabalha na indústria eletrônica há mais de trinta anos, dedicando a maior parte de seu tempo ao firmware. Ele agora é engenheiro de firmware na Mentor Embedded (uma divisão da Mentor Graphics). Colin Walls frequentemente fala em conferências e seminários, autor de vários artigos técnicos e dois livros sobre firmware. Vive no Reino Unido. Blog profissional de Colin , e-mail: colin_walls@mentor.com.

Source: https://habr.com/ru/post/pt433046/


All Articles