
Este artigo continua a revisão do Nucleus SE.
Serviços
O Nucleus SE fornece um conjunto de ferramentas que podem ser esperadas de qualquer RTOS.
Em primeiro lugar, o Nucleus SE contém um agendador bastante simples; no entanto, graças às quatro opções disponíveis, ele fornece flexibilidade. O agendador suporta os algoritmos Run to Completion, Round Robin, Carrossel, Time Slice e Priority.
A API do Nucleus SE inclui cerca de 50 chamadas de utilidade que fornecem aos desenvolvedores acesso ao gerenciamento de tarefas, seções de memória, sinais, grupos de sinalizadores de eventos, semáforos, caixas de correio, filas, pipelines, hora do sistema, cronômetros de aplicativos e diagnósticos.
Além do simples agendamento de tarefas, o Nucleus SE (opcional) suporta a pausa de tarefas. Essa função pode ser "limpa" (por exemplo, como resultado de uma chamada de API do serviço de suspensão explicitamente definida), pode ser uma função "inativa" (quando uma tarefa é pausada por um determinado período de tempo) ou pode ser o resultado de outra chamada de API na qual a tarefa está bloqueada (a chamada suspensão "condicional"), aguardando acesso ao recurso do kernel. Ao contrário do Nucleus RTOS, o Nucleus SE não suporta tempos limite ao bloquear chamadas de API.
A variedade de mecanismos apresentados permite escolher entre uma hierarquia de meios de sincronização e comunicação entre tarefas: de semáforos a sinais, sinalizadores de eventos, caixas de correio e filas / pipelines.
Artigos anteriores da série:
Artigo # 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.
Verificação de parâmetros
Ao escolher a configuração
NUSE_API_PARAMETER_CHECKING , o código para verificação de parâmetros é
incluído em todas as funções da API: verificação de ponteiros nulos, índices de objetos, etc. Como esse é um código adicional que requer memória adicional, seria aconselhável habilitar essa função durante a depuração, mas desativá-la no assembly de liberação.
Configuração
O núcleo SE possui uma estrutura flexível, o que nos dá dois pontos positivos. Por um lado, o kernel pode ter uma configuração refinada que satisfaça as tarefas de um aplicativo específico devido à configuração simples da funcionalidade disponível e ao gerenciamento simples do uso de memória. Por outro lado, o código Nucleus SE é facilmente transportável entre as ferramentas e entre os processadores.
Convenções de nomenclatura
Como a clareza e a facilidade de entendimento foram importantes no desenvolvimento do Nucleus SE, as convenções de nomenclatura foram cuidadosamente pensadas. Cada caractere no código é prefixado com
NUSE_. Tudo o que segue esse prefixo obedece a um conjunto de regras simples.
Chamadas de API
Cada função de chamada de API no Nucleus SE começa com
NUSE_, que quase sempre é seguido por um tipo de objeto, seguido por uma operação de maiúsculas e minúsculas, separada por sublinhados. Um exemplo é a função
NUSE_Queue_Send () , que
enfileira mensagens.
Outras funções e variáveis
O restante das funções e variáveis (globais) no código Nucleus SE também usam o prefixo NUSE_, mas o restante do nome nem sempre tem uma "estrutura". Isso não é importante para o usuário médio do kernel, pois ele terá funções de API suficientes.
Símbolos de configuração
Como o Nucleus SE é configurado com #define caracteres, eles também obedecem às convenções de nomenclatura. Eles são escritos apenas em maiúsculas. Os nomes dos ativadores das chamadas da API são iguais aos nomes das funções e também são escritos em maiúsculas, por exemplo,
NUSE_QUEUE_SEND.Outros #define caracteres
Quaisquer outros caracteres
#define (por exemplo, parâmetros de chamada da API e valores de status de retorno) que podem ser usados pelo código do aplicativo obedecem às mesmas regras, eles começam com
NUSE_ e são escritos em maiúsculas. Por exemplo,
NUSE_SUCCESS.Estruturas de dados
Todos os RTOSs têm um conjunto de estruturas de dados que descrevem objetos do kernel. Na maioria das implementações, são estruturas de dados em C que formam listas vinculadas, geralmente com comunicação bidirecional e até circular. Isso é lógico, pois os dados importantes são convenientemente encapsulados e os itens da lista podem ser adicionados ou excluídos à medida que os objetos são criados e excluídos.
No Nucleus SE, todos os objetos são estáticos; portanto, organizar todas as estruturas de dados desses objetos em uma lista simples era a solução óbvia. Isso reduz o volume e a complexidade dos ponteiros para frente e para trás. No entanto, decidi fortalecer a otimização do sistema e me recusei a usar estruturas. No Nucleus SE, todos os dados dos objetos do kernel são representados por várias matrizes simples (também chamadas de tabelas) de vários tipos, um ou mais para cada tipo de objeto. Existem vários argumentos a favor desta decisão:
- O Nucleus SE foi projetado tendo em mente a compatibilidade com estruturas de 8 bits. A maioria das pequenas CPUs não possui ferramentas ideais para implementar estruturas de dados em um compilador C. Matrizes simples são muito mais eficientes.
- Como o número máximo permitido de objetos de cada tipo é 16 e o acesso aos elementos de cada matriz requer quatro bits, um byte é frequentemente usado. Isso é mais eficiente que um endereço, que geralmente leva 16 ou 32 bits.
- Dados de objetos permanentes devem ser armazenados na ROM e não copiados para a RAM. Como a estrutura não pode ser dividida entre ROM e RAM (no C portátil tradicional), cada tipo de objeto pode ter duas estruturas, que são excessivamente complexas. No Nucleus SE, as tabelas de descrição do objeto podem ser encontradas na ROM e na RAM, conforme necessário.
- Devido à alta configurabilidade do Nucleus SE (“ultra-alta escalabilidade”), alguns dados de descrição do objeto podem ser opcionais, dependendo das ferramentas selecionadas. Isso leva ao uso generalizado da compilação condicional. Uma definição estrutural com diretivas de compilação condicional internas é muito difícil de entender. O controle da instanciação de matrizes individuais usando esse método é, por sua vez, bastante fácil de entender.
Todas as tabelas de dados de objetos estão sujeitas à convenção de nomeação hierárquica mencionada acima. Portanto, é muito fácil entender quais tabelas estão relacionadas logicamente.
Principais diferenças em relação ao Nucleus RTOS
Embora o Nucleus SE tenha sido projetado com um alto grau de compatibilidade com o Nucleus RTOS, algumas diferenças pequenas e maiores não puderam ser evitadas. Eles serão descritos em detalhes nos artigos relevantes, e uma breve descrição é fornecida abaixo.
Dados do objeto
No Nucleus RTOS, os objetos são criados e excluídos a pedido. No Nucleus SE, todos os objetos são criados estaticamente e determinados durante a montagem.
Número de objetos
O núcleo RTOS suporta um número indefinido de objetos de cada tipo. O Núcleo SE suporta no máximo dezesseis objetos de cada tipo.
Nomes de objetos
O Nucleus RTOS permite atribuir tipos de texto a alguns tipos de objetos que podem ser usados para depuração. O Nucleus SE não possui esse recurso.
Mecanismo de bloqueio de tarefas
O mecanismo para bloquear tarefas com uma chamada de API no Nucleus SE é bastante simples. Quando um recurso é liberado, todas as tarefas pendentes são retomadas e competem entre si (usando o agendador de tarefas) por recursos. As tarefas perdidas são novamente suspensas (bloqueadas). No Nucleus RTOS, o mecanismo é mais complexo, apenas tarefas importantes continuam nele, o que é mais eficaz.
Tempo limite da chamada da API
Ao chamar a API de bloqueio, o Nucleus RTOS permite que o desenvolvedor especifique um período de tempo limite após o qual a chamada será retomada, mesmo que o recurso não seja liberado. O Nucleus SE não possui esse recurso.
Agendamento de tarefas
O Nucleus RTOS Scheduler é flexível, eficiente e bem definido. O Nucleus SE oferece um conjunto de agendadores, cada um dos quais é simples e eficaz o suficiente para um número reduzido de tarefas suportadas: de 1 a 16.
Prioridades das tarefas
Um sistema que usa o Nucleus RTOS pode ter um número arbitrário de tarefas que podem receber um dos 256 níveis de prioridade, enquanto várias tarefas podem ter um nível de prioridade. Os níveis de prioridade da tarefa também podem mudar em tempo de execução. No Nucleus SE, se um agendador de prioridades for selecionado, cada tarefa deverá ter um nível de prioridade exclusivo que não possa ser alterado dinamicamente. Só pode haver um nível de prioridade por tarefa.
Manuseio de interrupção
O Nucleus RTOS suporta a arquitetura sofisticada de um manipulador de interrupção de duas camadas que permite interoperabilidade eficiente de manipulador de interrupção e serviços de kernel. O Nucleus SE usa uma abordagem semelhante que suporta manipuladores de interrupção simples que não são do kernel (interrupções não gerenciadas) e manipuladores de interrupção totalmente sensíveis ao contexto que podem usar chamadas de API (interrupções gerenciadas).
Drivers de dispositivo
O Nucleus RTOS possui uma arquitetura de driver de dispositivo bem projetada. O Nucleus SE não possui essa arquitetura, deixando ao desenvolvedor a tarefa de distribuir o controle do dispositivo entre as tarefas e o código do manipulador de interrupções.
Distribuição do Núcleo SE
Os códigos-fonte do Núcleo SE serão publicados à medida que esta série de artigos se desenvolver. Os arquivos disponíveis estarão disponíveis mediante solicitação por e-mail. No final da série de artigos, um repositório será criado para o download de todos os arquivos publicados.
Sobre o autorColin Walls trabalha na indústria eletrônica há mais de trinta anos, passando a maior parte do tempo em 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.
Email do blog profissional de Colin