home | ||
Como o X Real-Time Kernel pode me ajudar?Durante os últimos anos, os microcontroladores de 32 bits trouxeram muito mais poder de computação para sistemas embarcados que anteriormente usavam apenas 8 bits. Ao mesmo tempo, as aplicações tornaram-se mais complexas, exigindo muito mais dos seus desenvolvedores. Tipicamente, uma aplicação embarcada precisa monitorar e controlar uma grande quantidade de eventos, de forma precisa e temporizada. O início de um projeto deste tipo normalmente envolve uma questão fundamental: como estruturar o software? O X Real-Time Kernel, ou simplesmente X Kernel, é um RTOS (Real-Time Operating System) que oferece uma solução prática e elegante para a estruturação e o projeto de um sistema embarcado. Entretanto, é comum que desenvolvedores que iniciam na área tenham dúvidas sobre seu uso e sua função dentro do sistema. Algumas perguntas freqüentes são:
Para responder a estas perguntas, um exemplo será bem ilustrativo. Este exemplo será implementado de duas formas. A primeira usando apenas a programação básica e a segunda usando o X Kernel. O objetivo aqui é apresentar através de um exemplo simplificado que a utilização do X Kernel traz diversos benefícios como:
O ExemploUm sistema hipotético deve continuamente monitorar o estado de 3 chaves mecânicas. Um aviso deve ser enviado por um canal de comunicação sempre que uma delas mudar de posição. Para tornar o problema um pouco mais interessante, vamos adicionar algumas características:
Para dar ênfase às diferenças entre as duas implementações, não vamos considerar detalhes de implementação do hardware. As seguintes funções serão usadas como se estivessem definidas em uma biblioteca externa:
A implementação deste sistema usará duas “tarefas”:
Implementação sem o X Real-Time KernelPara implementar este sistema sem apoio do X Kernel, vamos utilizar a estratégia do laço principal ativado por interrupções do temporizador. O temporizador do sistema é programado para gerar uma interrupção a cada 10 ms. A única atividade da rotina de tratamento de interrupção é atribuir o valor true à variável clock_tick. O laço principal do programa continuamente espera que a variável clock_tick esteja em true. Quando isto ocorre, o temporizador global é incrementado (faz a função de relógio do sistema), e as funções que implementam as duas tarefas são chamadas. O valor do incremento é definido pela constante c_clock_tick_period que neste caso vale 10 ms (período da interrupção). int main (void) //
Incrementa o temporizador global //
Dá a cada tarefa uma chance de executar A função DebounceKeys faz a leitura e o debounce das teclas. Quando uma transição é detectada, ela deve enviar esta informação para a função CommChannel. Entretanto, é preciso lembrar que o canal de comunicação pode não estar disponível quando a informação é enviada. Por esse motivo, uma fila será usada para ligar as duas tarefas e também armazenar as informações até que possam ser transmitidas. Esta fila foi implementada através de um vetor dinâmico (“vector”da biblioteca STL do C++).
A implementação da função CommChannel exige uma máquina de estados. Dependendo da situação do canal, a função deve ter um comportamento diferente:
Clique aqui para ver o código fonte completo deste exemplo. Implementação com o X KernelEste mesmo exemplo implementado com auxílio do X Kernel também utiliza as duas funções DebounceKey e CommChannel. Mas, nesta nova situação, elas implementam threads do sistema operacional. Com isso, o sistema operacional pode escalonar as tarefas, ou seja, pode determinar quando é hora de cada uma delas executar. A comunicação entre as duas threads é realizada através de um pipe, uma estrutura do X Kernel que implementa uma fila de comunicação, capaz de armazenar mensagens enviadas de uma thread para outra. No exemplo, o pipe MessageQueue conecta as duas threads, armazenando mensagens enviadas pela DebounceKey até que o canal esteja conectado e CommChannel possa transmitir. A função main, nesta aplicação,
tem apenas a função de iniciar o hardware e as threads.
} Para criar uma thread no X Kernel usa-se o método CreateThread. Seus parâmetros indicam o nome da função que implementa a thread, dois valores definidos pelo programador que serão passados para a thread, o nome “legível” desta thread, o tamanho da pilha reservada para a sua execução, um conjunto de flags que informam o tipo de código (ARM ou Thumb) e habilitação de interrupções e a prioridade de execução desta thread. A thread DebounceKeys usa os serviços do X Kernel para “adormecer” por 20 ms e, periodicamente, fazer a leitura das chaves. As mensagens com informações sobre transições nas chaves são inseridas diretamente no pipe.
} A thread CommChannel torna-se bem mais simples. O X Kernel permite que cada thread execute como se tivesse o processador apenas para si, sem precisar memorizar seu estado enquanto outra thread executa.
} Clique aqui para ver o código fonte completo deste exemplo. ComparaçõesApesar de extremamente simples, este exemplo permite fazer comparações que são válidas para aplicações maiores. Observando as duas implementações, fica mais fácil responder as perguntas do início do artigo: Por que preciso de um RTOS? A medida que a aplicação fica mais complexa, envolvendo mais eventos e atividades independentes, torna-se muito difícil gerenciar “manualmente” todas as interações que existem entre estas atividades. O sistema operacional vai encarregar-se de tratar estas atividades de forma padronizada. Como um RTOS pode me ajudar? O sistema operacional permitiu retirar do código toda a lógica que anteriormente era necessária para controlar quando e como a aplicação deveria executar. Observando a implementação sem o sistema operacional, nota-se que esta lógica estava entrelaçada com a funcionalidade “real” da aplicação. Todo esse controle passou a ser executado pelo próprio sistema operacional e assim o programador pode focar o trabalho no desenvolvimento do seu produto. Minha aplicação ficará mais complexa? Mais cara? A praticidade de tratamento de temporizações e interações entre threads pode ser notada claramente na comparação entre os dois exemplos. No exemplo sem o X Kernel foi necessária uma estrutura complexa para administrar a espera pelos eventos. Com o X RTOS isto fica muito mais simples e claro. Note também que a função CommChannel tornou-se praticamente seqüencial, dispensando a técnica da máquinas de estado utilizada no primeiro exemplo. O programa sem o X RTOS precisou de mais código para executar a mesma atividade. Na implementação com o X RTOS, a implementação das threads precisou de menos esforço de programação. Esta é exatamente a vantagem de se utilizar o sistema operacional: o código repetitivo, que pode ser reutilizado, é retirado da sua aplicação e disponibilizado em uma biblioteca para reuso. O esforço e o custo de programar esta parte comum não precisa ser repetido a cada nova aplicação. |
| quem somos
| produtos
| serviços
| treinamento
| contatos
| notícias
| | busca | política de privacidade | termos de uso | |
© Copyright 2008 - eSystech |