TickAttack: um gerenciador de tarefas simples para um ARM Cortex-M0

TickAttack
Este post faz parte da série TickAttack - gerenciador de tarefas para ARM Cortex-M0. Leia também os outros posts da série:

Ao fazer um projeto utilizando sistemas embarcados, deve-se garantir sobretudo que as chances de travamento e falhas sejam as menores possíveis. Afinal, um sistema embarcado normalmente está envolvido em operações em que funcionam por anos a fio, podendo ser altamente críticas ou não. Para conseguir projetar um sistema embarcado mais imune a erros e falhas, uma ótima pedida é isolar as funcionalidades e fazer com que uma não interfira diretamente na outra.

 

Uma forma de fazer isso é utilizar a abordagem de escalonamento / agendamento de tarefas e um núcleo principal. Este artigo fala sobre um projeto nesta abordagem: TickAttack. O TickAttack trata-se de um gerenciador de tarefas simples a ser aplicado, com ótimo desempenho, a um microcontrolador ARM Cortex-M0. 

 

 

Definição do TickAttack

 

A ideia original veio de um projeto mais simples, de minha autoria, destinado ao uso em microcontroladores Microchip PIC de 8 bits. Tal projeto e artigo podem ser vistos em detalhes neste link. Tal projeto consistia no desenvolvimento de um núcleo (que nada mais é que um simples Kernel cooperativo) e tarefas diversas, executadas segundo temporização das mesmas. Observe o diagrama do núcleo / Kernel e tarefas na figura 1.

 

Diagrama do núcleo/Kernel e tarefas do gerenciador de tarefas TickAttack para PIC 8-bits
Figura 1 - Diagrama do núcleo/Kernel e tarefas do gerenciador de tarefas para PIC 8-bits

 

O TickAttack, portanto, consiste em uma portabilidade do gerenciador em questão. O "Tick" do nome veio do seguinte: pelo fato do gerenciador ser orientado à temporização (utilizando das interrupções de Timer, os Timer Ticks, como mecanismo de disparo das tarefas).

 

O TickAttack conta com as seguintes melhorias e modificações em relação ao gerenciador de tarefas original:

  • Melhor encapsulamento de funções / métodos e variáveis do Kernel;
  • Foi acrescentado um mecanismo para melhor gerenciar dados de memória compartilhada entre tarefas;
  • Foi acrescentado um mecanismo para medir o tempo gasto (em ms) de cada tarefa, destinado a avaliações de desempenho do TickAttack;
  • Preparado para uso em microcontroladores ARM Cortex-M0 (no caso, a primeira versão foi preparada para microcontroladores STM32F0).

 

Em suma, o TickAttack trata-se de uma versão melhorada do gerenciador.

 

 

Kernel - TickAttack

 

Em termos de mecanismo / forma de funcionamento, quase nada mudou em relação ao gerenciador de tarefas original. O que merece destaque / sofreu modificações é de onde são "tirados" os Timers Ticks e como o Kernel organiza seus métodos e variáveis e as encapsula.

 

No TickAttack, o Timer Tick é exatamente o SysTick. O SysTick consiste em um Timer Tick gerado a cada milissegundo. O interessante é que este Timer Tick já é previsto em vários HAL (Hardware Abstract Layer) de vários fabricantes de microcontroladores ARM, o que leva a uma economia dos Timers disponíveis no microcontrolador (já que o SysTick não utiliza nenhum dos Timers disponíveis ao programador / desenvolvedor / de uso geral).

Outra informação interessante é que os RTOS de mercado normalmente utilizam o SysTick, o que dá indícios que o TickAttack está no caminho certo.

 

No TickAttack, tudo que é relevante para o Kernel funcionar está agora encapsulado num único "pacote" (chamado aqui de SetupGerenciadorDeTarefas), facilitando seu uso e isolando-o melhor das demais variáveis de escopo global do projeto. Observe o Header File do Kernel / gerenciador de tarefas do TickAttack:

 

 

Agora, o código-fonte (.c) do Kernel / gerenciador de tarefas:

 

 

Mecanismo para gerenciar dados compartilhados entre tarefas

 

Quando é utilizada a abordagem mais modularizada de um sistema embarcado (como a do gerenciador aqui retratado, modularizado basicamente em núcleo/Kernel cooperativo e tarefas), é de fundamental importância que o acesso a dados em geral (memória RAM) seja controlado. Se a devida atenção a isto não for dada, inúmeros problemas de difícil diagnóstico e/ou solução podem ocorrer, como por exemplo:

  • Invasão de memória: variáveis (ou espaços de memória RAM) são indevidamente sobrescritos, afetando todas as tarefas que dependem destes dados;
  • Utilização de variáveis globais e locais com mesmo nome: embora pareça absurdo, há compiladores que não "reclamam" (ou que estão com suas configurações de warning em níveis baixos) se for declarada uma variável local e global com mesmo nome. Se isto ocorrer, é confusão na certa: uma tarefa / processo pode "pensar" escrever ou ler numa variável e, na verdade, estar realizando a ação em outra, causando um caos na lógica de seu sistema como um todo;
  • Utilização de variáveis de mesmo nome em módulos diferentes: aqui o caso é similar ao anterior, porém com um agravante: por módulos distintos interferirem entre si, o problema / transtorno pode ser bem maior.

 

Para mais informações sobre controles de acesso à memória RAM, recomendo a leitura do artigo "Porque evitar as variáveis globais e como", de Lincoln Uehara.

 

No TickAttack, há também um mecanismo para gerenciar dados que são compartilhados entre as tarefas. Embora muito simples se comparado a alguns de mercado, este garante que problemas comuns em acesso compartilhados não ocorram.

 

Basicamente, o mecanismo desenvolvido trata-se de gets e sets (funções de leitura e escrita, respectivamente) para informações de uso comum e o encapsulamento das mesmas em uma só estrutura, por fins de organização. Portanto, se você desejar acrescentar ou remover alguma informação de uso comum, será necessário fazer isto no arquivo .h (DadosCompartilhados.h) deste módulo e acrescentar ou remover os gets e sets correspondentes no arquivo .c (DadosCompartilhados.c). Observe o código-fonte neles contidos a seguir:

 

Arquivo DadosCompartilhados.c:

 

Arquivo DadosCompartilhados.h:

 

 

Medição do tempo gasto em cada tarefa

 

Outra melhoria acrescentada no TickAttack em relação ao gerenciador de tarefas original foi a possibilidade de se medir o tempo gasto em cada tarefa (em ms). Trata-se de um recurso muito interessante, pois reflete diretamente o desempenho do projeto como um todo e, além disso, dá indícios de onde no seu código é preciso melhorar o algoritmo/lógica de programação e codificação.

 

Analogamente aos outros mecanismos, isto também é feito de maneira simples, porém eficaz:

  1. Antes da execução de uma tarefa, é armazenado o valor do Tick (Tick Inicial) do Timer que temporiza o gerenciador de tarefas (nesse caso, obtido diretamente do SysTick). Este "Tick" consiste no número de milisegundos que o microcontrolador está executando o software, desde o momento que foi ligado;
  2. Uma vez terminada a tarefa, outro valor de Tick é requisitado (Tick Final) e a subtração de Tick Final e Tick Inicial define o tempo gasto (em milisegundos) da tarefa em questão. 

 

Em termos de codificação, há um array com N posições, cada uma contendo a última temporização de cada tarefa, permitindo assim acompanhamento em real-time dos tempos de execução.

 

Este mecanismo já está embutido no código do Núcleo / Kernel cooperativo, sendo que suas partes de destaque são:

 

 

Código-fonte do projeto

 

O projeto do TickAttack feito no MDK Keil 5 e já preparado para rodar na evaluation board STM32F072RBDISCOVERY pode ser acessado através de meu GitHub. Para isso, clique aqui. Baixe e use como quiser!

 

 

Um exemplo de aplicação

 

Abaixo, segue um exemplo de aplicação do TickAttack com componentes da própria evaluation board STM32072RBDISCOVERY.

Nele, os quatro LEDs da placa piscam de forma independente (ou seja, cada um é controlado por uma tarefa distinta), sendo que os LEDs alteram seus estados a cada 1000ms (LED superior, vermelho), 500ms (LED inferior, azul), 333ms (LED à esquerda, laranja) e 250ms (LED à direita, verde).

 

Exemplo de aplicação na eval board STM32072RB rodando o TickAttack
Exemplo de aplicação na eval board STM32072RB

 

 

Agradecimentos

 

Agradeço ao Eder Tadeu, meu amigo e articulista do Embarcados, pela ajuda, revisão, sugestões de implementação e testes do TickAttack.

 

 

Referências

Outros artigos da série

Exemplo de aplicação com TickAttack >>
Este post faz da série TickAttack - gerenciador de tarefas para ARM Cortex-M0. Leia também os outros posts da série:
NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Pedro Bertoleti
Sou engenheiro eletricista formado pela Faculdade de Engenharia de Guaratinguetá (FEG - UNESP) e trabalho com Android embarcado em Campinas-SP. Curioso e viciado em tecnologia, sempre busco me aprimorar na área de sistemas embarcados (modalidades bare-metal, RTOS, Linux embarcado e Android embarcado). Para mais informações, acesse minha página no Facebook:https://www.facebook.com/pbertoleti

2
Deixe um comentário

avatar
 
1 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
phfbertoletiEder Andrade Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Eder Andrade
Visitante
Eder

Parabéns pelo artigo Pedro e obrigado!

phfbertoleti
Visitante
phfbertoleti

Eder, muito obrigado! Eu que agradeço o apoio, trabalho e atenção!