
As filas foram mencionadas em um dos artigos anteriores (nº 5). Eles fornecem uma maneira mais flexível de transferir mensagens simples entre tarefas em comparação com caixas de correio.
Artigos anteriores da série:
Artigo 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 filas
No Nucleus SE, as filas são definidas durante a fase de construção. Um aplicativo pode ter até 16 filas. Se não houver filas no aplicativo, nem estruturas de dados nem código de serviço relacionados a filas serão incluídos no aplicativo.
Uma fila é um conjunto de áreas na memória que são grandes o suficiente para um elemento do tipo
ADDR e que podem ser acessadas com segurança para que várias tarefas possam usá-lo. As tarefas podem gravar dados na fila até que todas as áreas estejam cheias. As tarefas podem ler dados da fila, com os dados geralmente chegando em uma base FIFO (primeiro a entrar, primeiro a sair). Tentar gravar dados em uma fila cheia ou ler dados de uma fila vazia pode resultar em erro ou pausa na tarefa, dependendo dos parâmetros de chamada da API selecionados e da configuração do Nucleus SE.
Filas e links de dados
O Núcleo SE suporta canais de dados, que também foram mencionados em um artigo anterior (nº 5) e serão discutidos em detalhes em um dos seguintes. A principal diferença entre filas e canais é 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 de fila
Número de filas
Como na maioria dos objetos do Nucleus SE, a configuração da fila é controlada principalmente pelas diretivas
#define no arquivo
nuse_config.h . O parâmetro principal é
NUSE_QUEUE_NUMBER , que determina o número de filas configuradas no aplicativo. O valor padrão é zero (ou seja, não há filas no aplicativo) e pode levar valores até 16. Um valor incorreto levará a um erro durante a compilação, que será gerado durante a verificação no arquivo
nuse_config_check.h (incluído no arquivo
nuse_config.c e compilado junto com ele), que acionará a diretiva
#error .
A seleção de um valor diferente de zero serve como o principal ativador para as filas. Este parâmetro é usado ao definir 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 filas, essas diretivas são:
NUSE_QUEUE_SEND NUSE_QUEUE_RECEIVE NUSE_QUEUE_JAM NUSE_QUEUE_RESET NUSE_QUEUE_INFORMATION NUSE_QUEUE_COUNT
Por padrão, eles são definidos como
FALSE , desativando todas as chamadas de serviço e bloqueando a inclusão do código que as implementa. Para configurar as filas no aplicativo, você precisa selecionar as chamadas de API necessárias e defini-las como
TRUE .
A seguir, há um trecho de código do arquivo
nuse_config.h :
#define NUSE_QUEUE_NUMBER 0 /* Number of queues in the system - 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
Se as funções da API da fila estiverem ativadas, mas não houver filas no aplicativo (exceto
NUSE_Queue_Count () , que sempre está ativado), um erro de compilação será exibido. Se o seu código usar uma chamada de API que não foi ativada, isso causará um erro de layout, porque o código de implementação não foi incluído no aplicativo.
Enfileiramento de chamadas
O núcleo RTOS suporta dez chamadas de serviço de fila que fornecem a seguinte funcionalidade:
- Enfileirando uma mensagem. O núcleo SE é implementado na função NUSE_Queue_Send () .
- Aceitando uma mensagem da fila. O núcleo SE implementa a função NUSE_Queue_Receive () .
- Postagem no início da fila. No Nucleus SE, implementado em NUSE_Queue_Jam () .
- Restaurando a fila para um estado não utilizado com a liberação de todas as tarefas suspensas (redefinição). O núcleo SE é implementado em NUSE_Queue_Reset () .
- Fornecendo informações sobre uma fila específica. Núcleo SE implementado em NUSE_Queue_Information () .
- Retorna o número de filas atualmente configuradas no aplicativo. No Nucleus SE, implementado em NUSE_Queue_Count () .
- Adicionando uma nova fila ao aplicativo (criando uma fila). O núcleo SE não está implementado.
- Removendo uma fila de um aplicativo. O núcleo SE não está implementado.
- Retorne os ponteiros para todas as filas no aplicativo. O núcleo SE não está implementado.
- Enviando uma mensagem para todas as tarefas suspensas na fila (transmissão). O núcleo SE não está implementado.
A implementação de cada uma dessas chamadas indiretas é descrita em detalhes abaixo.
Chamadas de serviço para gravação e leitura de filas
As operações básicas que são executadas nas filas são de gravação (às vezes chamada de mensagens na fila) e leitura (também conhecida como recebimento de mensagens). Também é possível gravar no início da fila (congestionamento). O Nucleus RTOS e o Nucleus SE fornecem três chamadas de API básicas para essas operações, que serão discutidas abaixo.
Filas
A chamada do utilitário da API Nucleus RTOS para gravação na fila é muito flexível e permite pausar a tarefa implicitamente ou com um tempo limite específico se a operação não puder ser concluída imediatamente (por exemplo, ao tentar gravar em uma fila completa). O Nucleus SE oferece os mesmos recursos, mas a pausa da tarefa é opcional e o tempo limite não é implementado.
Enfileiramento de chamadas no núcleo RTOSProtótipo de chamada de serviço:
STATUS NU_Send_To_Queue (fila NU_QUEUE *, mensagem VOID *, tamanho NÃO ASSINADO, suspensão NÃO ASSINADA);Parâmetros:
fila - um ponteiro para o bloco de controle de fila fornecido pelo usuário;
message - ponteiro para a mensagem a ser enviada;
tamanho - o número de elementos de dados
NÃO ASSINADOS na mensagem. Se a fila suportar mensagens de tamanho variável, esse parâmetro deverá ser igual ao tamanho da mensagem ou menor que o tamanho da mensagem suportada pela fila. Se a fila suportar mensagens de tamanho fixo, esse parâmetro deverá corresponder exatamente ao tamanho da mensagem suportada pela fila;
suspender - a especificação da suspensão da tarefa pode assumir os valores
NU_NO_SUSPEND ou
NU_SUSPEND ou um valor de tempo limite.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_QUEUE - ponteiro de fila inválido;
NU_INVALID_POINTER - ponteiro nulo para uma mensagem (
NULL );
NU_INVALID_SIZE - o tamanho da mensagem é incompatível com o tamanho da mensagem suportado pela fila;
NU_INVALID_SUSPEND - a suspensão foi realizada a partir de um encadeamento não relacionado à tarefa;
NU_QUEUE_FULL - a fila está cheia e a suspensão não foi especificada;
NU_TIMEOUT - a fila está cheia mesmo depois que a tarefa é suspensa pelo tempo limite especificado;
NU_QUEUE_DELETED - a fila foi excluída enquanto a tarefa estava suspensa;
NU_QUEUE_RESET - A fila foi redefinida enquanto a tarefa estava suspensa.
Enfileirando uma mensagem no Nucleus SEEsta chamada de serviço da API suporta a funcionalidade principal da API Nucleus RTOS.
Protótipo de chamada de serviço:
ESTADO NUSE_Queue_Send (fila NUSE_QUEUE, mensagem ADDR *, suspensão U8);Parâmetros:
fila - índice da
fila (ID);
message - um ponteiro para a mensagem a ser enviada, é uma variável do tipo
ADDR ;
suspender - especificação para pausar tarefas; pode assumir os valores
NUSE_NO_SUSPEND ou NUSE_SUSPEND .
Valor de retorno:
NUSE_SUCCESS - a chamada foi concluída com sucesso;
NUSE_INVALID_QUEUE - índice de fila inválido;
NUSE_INVALID_POINTER - ponteiro nulo para uma mensagem (
NULL );
NUSE_INVALID_SUSPEND - tente pausar uma tarefa de um encadeamento não associado à tarefa ou quando as chamadas de serviço da API estiverem desabilitadas para bloquear tarefas;
NUSE_QUEUE_FULL - a fila está cheia e a suspensão não foi especificada;
NUSE_QUEUE_WAS_RESET - A fila foi redefinida enquanto a tarefa estava suspensa.
Implementar enfileiramento no Nucleus SEA versão do código de função da API
NUSE_Queue_Send () (após verificar os parâmetros) é selecionada usando a compilação condicional, dependendo se o suporte para bloqueio de tarefas está ativado ou não. Vamos considerar as duas opções.
Se o bloqueio de tarefas não estiver ativado, o código para esta chamada de serviço é bastante simples:
if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) /* queue full */ { return_value = NUSE_QUEUE_FULL; } else /* queue element available */ { 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; }
A função simplesmente verifica se há espaço livre na fila e usa o índice
NUSE_Queue_Head [] para armazenar a mensagem na área de dados da fila.
Se o bloqueio de tarefas estiver ativado, o código se tornará mais complexo:
do { if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) /* queue full */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_QUEUE_FULL; } else { /* block task */ 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 { /* queue element available */ 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; /* check whether a task is blocked on this queue */ 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);
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 a fila estiver cheia e a
suspensão for
NUSE_NO_SUSPEND , a chamada da API termina com
NUSE_QUEUE_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 continuar), se o valor de retorno for
NUSE_SUCCESS , ou seja, a tarefa foi retomada porque a mensagem foi lida (e não porque a fila foi redefinida), o código retornará ao início do loop.
Se a fila não estiver cheia, a mensagem fornecida será armazenada usando o índice
NUSE_Queue_Head [] na área de dados da fila. Ele verifica se há tarefas suspensas (mensagens em espera) na fila. 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 da fila
A chamada do utilitário Nucleus RTOS API para ler da fila é muito flexível e permite pausar tarefas implicitamente, ou com um tempo limite específico, se a operação não puder ser concluída imediatamente (por exemplo, ao tentar ler de uma fila vazia). O Nucleus SE fornece a mesma funcionalidade, mas a pausa da tarefa é opcional e o tempo limite não é implementado.
Ligue para receber mensagens da fila no Nucleus RTOSProtótipo de chamada de serviço:
STATUS NU_Receive_From_Queue (fila NU_QUEUE *, mensagem VOID *, tamanho NÃO ASSINADO, NÃO ASSINADO, NÃO ASSINADO * tamanho real, suspensão NÃO ASSINADA);Parâmetros:
fila - um ponteiro para o bloco de controle de fila fornecido pelo usuário;
mensagem - um ponteiro para o armazenamento de mensagens recebidas;
tamanho - o número de elementos de dados
NÃO ASSINADOS na mensagem. Esse número deve corresponder ao tamanho da mensagem definido quando a fila foi criada;
suspender - a especificação da suspensão da tarefa pode assumir os valores
NU_NO_SUSPEND ou
NU_SUSPEND ou um valor de tempo limite.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_QUEUE - ponteiro de fila inválido;
NU_INVALID_POINTER - ponteiro nulo para uma mensagem (
NULL );
NU_INVALID_SUSPEND - tenta pausar uma tarefa de um thread não relacionado à tarefa;
NU_QUEUE_EMPTY - a fila está vazia e a suspensão não foi especificada;
NU_TIMEOUT - indica que a fila ainda está vazia, mesmo após a suspensão da tarefa por um período especificado;
NU_QUEUE_DELETED - a fila foi excluída enquanto a tarefa estava suspensa;
NU_QUEUE_RESET - A fila foi redefinida enquanto a tarefa estava suspensa.
Ligue para receber mensagens da fila do Nucleus SEEssa chamada de API suporta a funcionalidade principal da API do Nucleus RTOS.
Protótipo de chamada de serviço:
STATUS NUSE_Queue_Receive (fila NUSE_QUEUE, mensagem ADDR *, suspensão U8);Parâmetros:
fila - índice da
fila (ID);
message - um ponteiro para o repositório das mensagens recebidas, é uma variável do tipo
ADDR ;
suspender - a especificação da suspensão da tarefa pode assumir os valores
NUSE_NO_SUSPEND ou
NUSE_SUSPEND .
Valor de retorno:
NUSE_SUCCESS - a chamada foi concluída com sucesso;
NUSE_INVALID_QUEUE - índice de fila 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 desabilitado para bloqueio de tarefas;
NUSE_QUEUE_EMPTY - a fila está vazia e a suspensão não foi especificada;
NUSE_QUEUE_WAS_RESET - A fila foi redefinida enquanto a tarefa estava suspensa.
Implementação de recebimento de mensagens de filas no Nucleus SEA versão do código de função da API
NUSE_Queue_Receive () (após verificar os parâmetros) é selecionada usando a compilação condicional, dependendo se o suporte para bloqueio de tarefas está ativado ou não. Considere as duas opções.
Se o suporte a bloqueio estiver ativado, o código para esta chamada de API é bastante simples:
if (NUSE_Queue_Items[queue] == 0) /* queue empty */ { return_value = NUSE_QUEUE_EMPTY; } else { /* message available */ *message = NUSE_Queue_Data[queue][NUSE_Queue_Tail[queue]++]; if (NUSE_Queue_Tail[queue] == NUSE_Queue_Size[queue]) { NUSE_Queue_Tail[queue] = 0; } NUSE_Queue_Items[queue]--; return_value = NUSE_SUCCESS; }
A função simplesmente verifica se há uma mensagem na fila e usa o índice
NUSE_Queue_Tail [] para recuperar a mensagem da fila e retornar dados usando um ponteiro para a mensagem.
Se o bloqueio de tarefas estiver ativado, o código se tornará mais complexo:
do { if (NUSE_Queue_Items[queue] == 0) /* queue empty */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_QUEUE_EMPTY; } else { /* block task */ 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 { /* message available */ *message = NUSE_Queue_Data[queue][NUSE_Queue_Tail[queue]++]; if (NUSE_Queue_Tail[queue] == NUSE_Queue_Size[queue]) { NUSE_Queue_Tail[queue] = 0; } NUSE_Queue_Items[queue]--; if (NUSE_Queue_Blocking_Count[queue] != 0) { U8 index; /* check whether a task is blocked */ /* on this queue */ 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);
Alguns esclarecimentos serão úteis.
O código é colocado em um
loop do ... while , que é executado enquanto o parâmetro de pausa da tarefa é
NUSE_SUSPEND .
Se a fila estiver vazia e a suspensão for
NUSE_NO_SUSPEND , a chamada da API termina com
NUSE_QUEUE_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 continuar), se o valor de retorno for
NUSE_SUCCESS , ou seja, a tarefa foi retomada porque a mensagem foi enviada (e não porque a fila foi redefinida), o código retornará ao início do loop.
Se a fila contiver mensagens, a mensagem armazenada será retornada usando o índice
NUSE_Queue_Tail [] . Ele verifica se há alguma tarefa pausada (pendente) nessa fila. 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 .
Escreva para o início da fila
A chamada do utilitário Nucleus RTOS API para gravar uma mensagem no cabeçalho da fila é muito flexível e permite pausar a tarefa implicitamente, ou com um tempo limite específico, se a operação não puder ser concluída imediatamente (por exemplo, ao tentar gravar em uma fila cheia). O Nucleus SE fornece a mesma funcionalidade, mas a pausa da tarefa é opcional e o tempo limite não é implementado.
Ligue para escrever uma mensagem na cabeça da fila do Nucleus RTOSProtótipo de chamada de serviço:
STATUS NU_Send_To_Front_Of_Queue (fila NU_QUEUE *, mensagem VOID *, tamanho NÃO ASSINADO, suspensão NÃO ASSINADA);Parâmetros:
fila - um ponteiro para o bloco de controle de fila fornecido pelo usuário;
message - ponteiro para a mensagem a ser enviada;
tamanho - o número de elementos de dados
NÃO ASSINADOS na mensagem. Se a fila suportar mensagens de tamanho variável, esse parâmetro deverá ser igual ao tamanho da mensagem ou menor que o tamanho da mensagem suportada pela fila. Se a fila suportar mensagens de tamanho fixo, esse parâmetro deverá corresponder exatamente ao tamanho da mensagem suportada pela fila;
suspender - a especificação da suspensão da tarefa pode assumir os valores
NU_NO_SUSPEND ou
NU_SUSPEND ou um valor de tempo limite.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_QUEUE - ponteiro de fila inválido;
NU_INVALID_POINTER - ponteiro nulo para uma mensagem (
NULL );
NU_INVALID_SIZE - o tamanho da mensagem é incompatível com o tamanho da mensagem suportada pela fila;
NU_INVALID_SUSPEND - tenta pausar a partir de um fluxo que não é tarefa
NU_QUEUE_FULL - a fila está cheia e a suspensão não foi especificada;
NU_TIMEOUT - a fila está cheia, mesmo depois que a tarefa é suspensa por um certo tempo limite;
NU_QUEUE_DELETED - a fila foi excluída enquanto a tarefa estava suspensa;
NU_QUEUE_RESET - A fila foi redefinida enquanto a tarefa estava suspensa.
Uma chamada para escrever uma mensagem na cabeça de uma fila no Nucleus SEEssa chamada de API suporta a funcionalidade principal da API do Nucleus RTOS.
Protótipo de chamada de serviço:
STATUS NUSE_Queue_Jam (fila NUSE_QUEUE, mensagem ADDR *, suspensão U8);Parâmetros:
fila - índice da
fila (ID);
message - um ponteiro para uma mensagem, é uma variável do tipo
ADDR ;
suspender - a especificação da suspensão da tarefa pode assumir os valores
NUSE_NO_SUSPEND ou
NUSE_SUSPEND .
Valor de retorno:
NUSE_SUCCESS - a chamada foi concluída com sucesso;
NUSE_INVALID_QUEUE - índice de fila 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 desabilitado para bloqueio de tarefas;
NUSE_QUEUE_FULL - a fila está cheia e a suspensão não foi especificada;
NUSE_QUEUE_WAS_RESET - A fila foi redefinida enquanto a tarefa estava suspensa.
Implementando um registro superior da fila no Nucleus SEA variante de código de função da API
NUSE_Queue_Jam () é muito semelhante a
NUSE_Queue_Send () , apenas os dados são armazenados usando o índice
NUSE_Queue_Tail [] , portanto:
if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) /* queue full */ { return_value = NUSE_QUEUE_FULL; } else /* queue element available */ { if (NUSE_Queue_Tail[queue] == 0) { NUSE_Queue_Tail[queue] = NUSE_Queue_Size[queue] - 1; } else { NUSE_Queue_Tail[queue]--; } NUSE_Queue_Data[queue][NUSE_Queue_Tail[queue]] = *message; NUSE_Queue_Items[queue]++; return_value = NUSE_SUCCESS; }
O próximo artigo analisará chamadas de API adicionais associadas a filas, bem como estruturas de dados.
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.