
Este artigo continua a descrever grupos de sinalizadores de eventos.
Artigos anteriores da série:
Artigo 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.
Serviços auxiliares do grupo de sinalizadores de eventos
O Nucleus RTOS possui três chamadas de API que fornecem funções auxiliares para grupos de sinalizadores de eventos: recuperar informações do grupo, recuperar informações sobre o número de grupos de sinalizadores de eventos em um aplicativo e recuperar ponteiros para todos os grupos de sinalizadores de eventos. Os dois primeiros desafios são implementados no Nucleus SE.
Recuperando informações do grupo de sinalizadores de eventos
Essa chamada de utilitário retorna informações sobre o grupo de sinalizadores de eventos. A implementação dessa chamada no Nucleus SE difere da implementação no Nucleus RTOS, pois menos informações são retornadas, pois a nomeação de objetos e a ordem de pausa da tarefa não são suportadas, e a própria pausa da tarefa pode ser desativada.
Uma chamada para recuperar informações do grupo de eventos no Nucleus RTOSProtótipo de chamada de serviço:
STATUS NU_Event_Group_Information (grupo NU_EVENT_GROUP *, CHAR * nome, UNSIGNED * event_flags, UNSIGNED * tasks_waiting, NU_TASK ** first_task);Parâmetros:
group - um ponteiro para um bloco de controle fornecido pelo usuário para um grupo de sinalizadores de eventos;
nome - um ponteiro para a região de 8 caracteres para o nome do grupo de sinalizadores de eventos, isso também inclui o zero final;
event_flags - ponteiro para uma variável que aceita o valor atual do grupo especificado de sinalizadores de eventos;
tasks_waiting - um ponteiro para uma variável que aceita o número de tarefas suspensas nesse grupo de sinalizadores de eventos;
first_task - um ponteiro para uma variável do tipo
NU_TASK , que levará um ponteiro para a primeira tarefa suspensa.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_GROUP - ponteiro inválido para um grupo de sinalizadores de eventos.
Uma chamada para recuperar informações do grupo de eventos no Nucleus SEEsta chamada suporta a funcionalidade principal da API Nucleus RTOS.
Protótipo de chamada de serviço:
STATUS NUSE_Event_Group_Information (grupo NUSE_EVENT_GROUP, U8 * bandeiras do evento, U8 * tarefas_a espera, NUSE_TASK * primeira_tarefa);Parâmetros:
group - o índice do grupo de sinalizadores de eventos sobre quais informações são solicitadas;
event_flags - ponteiro para uma variável que aceita o valor atual do grupo especificado de sinalizadores de eventos;
tasks_waiting - um ponteiro para uma variável que aceita o número de tarefas suspensas nesse grupo de sinalizadores de eventos (nada será retornado se a suspensão da tarefa estiver desativada);
first_task - um ponteiro para uma variável do tipo
NUSE_TASK que receberá o índice da primeira tarefa suspensa (nada será retornado se a suspensão da tarefa estiver desativada).
Valor de retorno:
NUSE_SUCCESS - a chamada foi concluída com sucesso;
NUSE_INVALID_GROUP - índice do grupo de sinalizadores de eventos inválido.
Implementação de informações do grupo de eventos no Nucleus SEA implementação desta chamada de API é bastante simples:
*event_flags = NUSE_Event_Group_Data[group]; #if NUSE_BLOCKING_ENABLE *tasks_waiting = NUSE_Event_Group_Blocking_Count[group]; if (NUSE_Event_Group_Blocking_Count[group] != 0) { U8 index; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_EVENT_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == group)) { *first_task = index; break; } } } else { *first_task = 0; } #else *tasks_waiting = 0; *first_task = 0; #endif return NUSE_SUCCESS;
A função retorna o valor do grupo de sinalizadores de eventos. Em seguida, se as chamadas da API de bloqueio de tarefas estiverem ativadas, o número de tarefas pendentes e o índice da primeira delas serão retornados (caso contrário, esses dois parâmetros serão definidos como zero).
Obtendo o número de grupos de sinalizadores de eventos
Essa chamada de utilitário retorna o número de grupos de sinalizadores de eventos no aplicativo. No Nucleus RTOS, esse valor muda com o tempo e o valor de retorno mostra o número atual de grupos, enquanto no Nucleus SE esse valor é determinado durante a montagem e não muda com o tempo.
Chamando o contador de grupos de sinalizadores de eventos no Nucleus RTOSProtótipo de chamada de serviço:
NU_Establised_Event_Groups UNSIGNED (VOID);Parâmetros:
Estão ausentes.
Valor de retorno:
O número atual de grupos de sinalizadores de eventos criados.
Chamando o contador de grupos de sinalizadores de eventos no Nucleus SEProtótipo de chamada de serviço:
U8 NUSE_Event_Group_Count (nulo);Parâmetros:
Estão ausentes.
Valor de retorno:
O número de grupos de sinalizadores de eventos configurados.
Implementando um contador de grupo de sinalizadores de eventos no Nucleus SEA implementação desta chamada de API é bastante trivial: o valor do símbolo
#define NUSE_EVENT_GROUP_NUMBER é
retornado .
Estruturas de dados
Como todos os outros objetos do Nucleus SE, os grupos de sinalizadores de eventos usam uma ou duas matrizes de estruturas de dados (ambas localizadas na RAM), o tamanho das matrizes depende do número de grupos definido nas configurações.
Eu recomendo fortemente que o código do aplicativo não use acesso direto a essas estruturas de dados, mas faça referência a elas através das funções de API fornecidas. Isso evitará incompatibilidade com versões futuras do Nucleus SE e efeitos colaterais indesejados, além de simplificar a portabilidade do aplicativo para o Nucleus RTOS. Para uma melhor compreensão do código de chamada de serviço e depuração, é fornecida uma visão geral detalhada das estruturas de dados abaixo.
Dados RAM
Esses dados têm a seguinte estrutura:
NUSE_Event_Group_Data [] - uma matriz de dados do tipo
U8 com um registro para cada grupo configurado de sinalizadores; armazena dados do sinalizador de evento.
NUSE_Event_Group_Blocking_Count [] - uma matriz do tipo
U8 que contém um contador de tarefas bloqueadas em cada grupo de sinalizadores de eventos. Essa matriz existe apenas quando a funcionalidade de bloqueio na API está ativada.
Essas estruturas de dados são inicializadas com zeros na função
NUSE_Init_Event_Group () quando o Nucleus SE é iniciado. Um dos seguintes artigos fornecerá uma descrição completa dos procedimentos de inicialização do Nucleus SE.
A seguir, é apresentada uma descrição dessas estruturas de dados no arquivo
nuse_init.c :
RAM U8 NUSE_Event_Group_Data[NUSE_EVENT_GROUP_NUMBER]; #if NUSE_BLOCKING_ENABLE RAM U8 NUSE_Event_Group_Blocking_Count[NUSE_EVENT_GROUP_NUMBER]; #endif
Dados ROM
Para implementar grupos de sinalizadores de eventos, os dados na ROM não são usados.
Tamanho da memória para grupos de sinalizadores de eventos
Como em todos os objetos de núcleo do Nucleus SE, a quantidade de memória necessária para grupos de sinalizadores de eventos é previsível.
A quantidade de dados na ROM para todos os grupos de sinalizadores de eventos no aplicativo é 0.
A quantidade de memória na RAM para todos os grupos de sinalizadores de eventos com a funcionalidade de bloqueio de API ativada é
NUSE_EVENT_GROUP_NUMBER * 2 .
Caso contrário, é
NUSE_EVENT_GROUP_NUMBER .
Chamadas de API não realizadas
Três chamadas de API para grupos de sinalizadores de eventos que podem ser encontradas no Nucleus RTOS não foram implementadas no Nucleus SE.
Criando um grupo de sinalizadores de eventos
Essa chamada de API cria um grupo de sinalizadores de eventos. O Núcleo SE não precisa dessa chamada porque os grupos de sinalizadores de eventos são criados estaticamente.
Protótipo de chamada de serviço:
STATUS NU_Create_Event_Group (NU_EVENT_GROUP * group, CHAR * name);Parâmetros:
group - um ponteiro para um bloco de controle fornecido pelo usuário para um grupo de sinalizadores de eventos; Usado como um descritor para gerenciar grupos de sinalizadores de eventos em outras chamadas de API
nome - um ponteiro para o nome de 8 caracteres do grupo de sinalizadores de eventos com um byte nulo final incluído nesta área.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_GROUP - ponteiro nulo para a unidade de controle do grupo de sinalizadores de eventos (
NULL ) ou já em uso.
Excluindo um grupo de sinalizadores de eventos
Essa chamada de API remove o grupo de sinalizadores de eventos criado anteriormente. O Núcleo SE não precisa dessa chamada porque os grupos de sinalizadores de eventos são criados estaticamente e não podem ser excluídos.
Protótipo de chamada de serviço:
STATUS NU_Delete_Event_Group (NU_EVENT_GROUP * group);Parâmetros:
group - um ponteiro para o bloco de controle do grupo de sinalizadores de eventos.
Valor de retorno:
NU_SUCCESS - a chamada foi concluída com sucesso;
NU_INVALID_GROUP - ponteiro inválido para um grupo de sinalizadores de eventos.
Ponteiros de grupo de sinalizadores de eventos
Essa chamada de API compõe uma lista seqüencial de ponteiros para todos os grupos de sinalizadores de eventos no sistema. O Núcleo SE não precisa dessa chamada porque os grupos de sinalizadores de eventos têm índices simples, não ponteiros.
Protótipo de chamada de serviço:
UNSIGNED NU_Event_Group_Pointers (NU_EVENT_GROUP * pointer_list, UNSIGNED maximum_pointers);Parâmetros:
pointer_list - um ponteiro para uma matriz de ponteiros
NU_EVENT_GROUP , essa matriz é preenchida com ponteiros para grupos de sinalizadores de eventos criados no sistema;
maximum_pointers - o número máximo de ponteiros na matriz.
Valor de retorno:
O número de ponteiros
NU_EVENT_GROUP na matriz.
Compatível com núcleo RTOS
Ao desenvolver o Nucleus SE, meu objetivo era garantir o nível máximo de compatibilidade de código com o Nucleus RTOS. Grupos de sinalizadores de eventos não foram exceção e, do ponto de vista do desenvolvedor, eles são implementados quase da mesma maneira que no Nucleus RTOS. Existem algumas incompatibilidades que considerei válidas, uma vez que o código final se tornará mais compreensível e mais eficiente em termos da quantidade de memória necessária. Caso contrário, as chamadas da API do Nucleus RTOS podem ser usadas quase diretamente como as chamadas do Nucleus SE.
Identificadores de objeto
No Nucleus RTOS, todos os objetos são descritos por estruturas de dados (unidades de controle) de um tipo específico. Um ponteiro para esta unidade de controle é um identificador para um grupo de sinalizadores de eventos. Decidi que no Nucleus SE é necessária uma abordagem diferente para o uso eficiente da memória: todos os objetos do kernel são descritos por várias tabelas na RAM e / ou ROM. O tamanho dessas tabelas é determinado pelo número de objetos configurados de cada tipo. O identificador de um objeto específico é o índice nesta tabela. Então, eu defini
NUSE_EVENT_GROUP como o equivalente a
U8 , uma variável desse tipo (não um ponteiro) serve como um identificador para um grupo de sinalizadores de eventos. Essa pequena incompatibilidade é fácil de lidar se o código for portado do Nucleus SE para o Nucleus RTOS e vice-versa. Normalmente, nenhuma operação é executada nos identificadores de objeto além de mover e armazenar.
O núcleo RTOS também suporta grupos de sinalizadores de eventos de nomeação. Esses nomes são usados apenas para depuração. Excluí-os do Nucleus SE para economizar memória.
O número de sinalizadores no grupo
No Nucleus RTOS, os grupos de sinalizadores de eventos contêm 32 sinalizadores cada, no Nucleus SE eu reduzi seu número para oito, pois isso é suficiente para aplicativos simples e economiza RAM. O Núcleo SE pode ser facilmente modificado se grupos maiores de sinalizadores de eventos forem necessários.
Função de absorção da bandeira
O núcleo RTOS tem uma função para limpar (absorver) sinalizadores de eventos depois de lê-los. Decidi excluir essa função do Nucleus SE para simplificar o sistema, pois a absorção (remoção) de sinalizadores ocorre quando todas as tarefas bloqueadas recebem sinalizadores para leitura, e isso seria difícil de implementar. Se necessário, uma tarefa de leitura de sinalizador sempre pode limpá-las usando uma chamada de API separada.
Chamadas de API não realizadas
O núcleo RTOS suporta sete chamadas de utilidade para trabalhar com grupos de sinalizadores de eventos. Destes, três não estão implementados no Nucleus SE. Os detalhes desses desafios, bem como a decisão de excluí-los do Nucleus SE, foram descritos acima.
O próximo artigo analisará os semáforos.
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.