
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 dadosArtigo 23. Filas: introdução e serviços básicosArtigo 22. Caixas de correio: serviços auxiliares e estruturas de dadosArtigo 21. Caixas de correio: Introdução e serviços básicosArtigo 20. Semáforos: Serviços Auxiliares e Estruturas de DadosArtigo 19. Semáforos: introdução e serviços básicosArtigo # 18 Grupos de Sinalizadores de Eventos: Serviços Auxiliares e Estruturas de DadosArtigo 17. Grupos de Sinalizadores de Eventos: Introdução e Serviços BásicosArtigo 16. SignalsArtigo 15. Partições de memória: serviços e estruturas de dadosArtigo 14. Seções de memória: introdução e serviços básicosArtigo 13. Estruturas de dados da tarefa e chamadas de API não suportadasArtigo 12. Serviços para trabalhar com tarefasArtigo 11. Tarefas: configuração e introdução à APIArtigo 10. Agendador: recursos avançados e preservação de contextoArtigo 9. Agendador: implementaçãoArtigo 8. Núcleo SE: Projeto Interno e ImplantaçãoArtigo # 7 Núcleo SE: IntroduçãoArtigo 6. Outros serviços RTOSArtigo 5. Interação e sincronização de tarefasArtigo 4. Tarefas, alternância de contexto e interrupçõesArtigo # 3 Tarefas e planejamentoArtigo 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_SENDNUSE_PIPE_RECEIVENUSE_PIPE_JAMNUSE_PIPE_RESETNUSE_PIPE_INFORMATIONNUSE_PIPE_COUNTPor 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 RTOSProtó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 SEEsta 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 SEA 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 RTOSProtó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 SEEsta 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 SEA 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 RTOSProtó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 SEEssa 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 SEO 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.