Temporização em Máquinas de estados

Temporização em Máquinas de Estados

O desenvolvimento de software usando uma topologia de máquina de estados (cooperative multitasking), como já foi descrita no artigo Arquitetura de desenvolvimento de software – parte III, permite o desenvolvimento de software com um elevado grau de complexidade.

Qualquer microcontrolador tem um número limitado de timers de hardware, sendo que por vezes esses timers são compartilhados com outros periféricos (PWM, capture, etc). Na topologia de máquina de estados existem várias tarefas em execução “paralela”, tarefas essas que não podem ser bloqueantes e poderão ao “mesmo tempo” necessitar realizar temporizações.

Dado o número limitado de timers por hardware, não é possível atribuir a cada tarefa um timer. Veja o exemplo seguinte, onde existe um led a comutar a cada segundo e o ADC é lido a cada 100ms. Neste exemplo como referido, cada máquina de estados usa um timer por hardware, solução essa que apesar de ser exequível, rapidamente o deixará de ser assim que o sistema aumentar de complexidade.

A solução para este problema é a utilização de um único timer por hardware para a realização de múltiplos timers por software, à semelhança do que acontece num sistema com RTOS (Real-Time Operating System). Esta solução foi aliás pensada pela ARM quando desenhou os núcleos ARM Cortex-M e incorporou o timer dedicado SysTick, timer esse que será o timer de base do nosso exemplo.

A solução apresentada será o mais simplista possível, de modo a não só simplificar a implementação e utilização, bem como a minimizar os recursos necessários e o tempo de execução da interrupção do timer. A solução apresentada consiste numa variável global que incrementa continuamente a cada tick do timer, tick esse definido na configuração do timer SysTick (deverá ser menor que o tempo mínimo desejável), e que pelo fato de ser uma variável de 64 bits de dimensão levará muito tempo para voltar a ser 0 (zero), tomando por exemplo um tick de 100us, será necessária a passagem de mais de 58 milhões de anos (264 *100us) para que esta variável volte a 0.

Quando é necessário um timer, é criada uma variável estática do tipo T_TimerTicks, na qual é armazenado o valor atual do tick mais o número de ticks necessários para a passagem do tempo desejado. É essa a utilidade das funções TimerTicks_setTimerXXX, calcular o valor futuro do tick na base de tempo que pretendermos (segundos, milissegundos, etc.). O próximo passo na nossa máquina de estados é fazer polling ao valor do tick e aguardar que iguale o valor da variável estática, assinalando assim a passagem do tempo desejado.

Esta abordagem tem a limitação da utilização de uma variável de 64 bits poder não ser suportada pela arquitetura, limitando assim o tempo máximo de funcionamento contínuo do timer. Esta limitação não é significativa se o tempo máximo de execução contínuo do firmware não ultrapassar o tempo máximo contabilizável pela variável global.

Uma abordagem diferente passa pela utilização de uma variável dedicada a cada timer na interrupção do SysTick, como no exemplo seguinte, tendo como contrapartida o aumento do tempo de execução da interrupção.

Um fator importante em qualquer temporização é a sua precisão, e nas propostas acima apresentadas o erro máximo é igual ao valor de base do tick. Isto é, pelo fato de o SysTick estar sempre em funcionamento, os seus registros estão em constante atualização. No momento em que ativamos um timer a interrupção do SysTick pode estar prestes a disparar, o que faz com que o primeiro tick no nosso timer seja mal contabilizado, como demonstra a figura seguinte.

Entra aqui a importância da correta seleção do tick de base. Se pretendermos, por exemplo, que o nosso timer contabilize tempos de 5s e usarmos um tick de base de 10ms, será igual contar 5s ou 4,99s (5s-10ms). No entanto, se utilizarmos um tick de base de 1s, já não é igual. Poderemos contar 5s ou 4s (5s-1s).

Temporização em Máquinas de Estados
Figura 1 – Diagrama Temporal

Conclusão

Como pretendido, esta solução é não-bloqueante, escalonável e universal, e o seu desempenho independente do aumento do número de timers simultâneos (apenas na primeira proposta). Apesar de algumas limitações, estas pouco influenciam o resultado final.

Veja + conteúdo

Engenheiro Electrónico pela Escola Superior de Tecnologia de Setúbal - Instituto Politécnico de Setúbal desde 2008. Com 8 anos de experiência no desenvolvimento de sistemas embarcados (hardware e firmware), tendo me especializado no desenvolvimento de firmware para sistemas microcontrolados, com especial foco em microcontroladores Microchip PIC e ARM Cortex-Mx (Freescale, NXP, etc.).

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

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

Comentários:
Notificações
Notificar
guest
2 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Cassiano Campes
Cassiano Campes
27/05/2016 10:19

Muito bom o artigo Mário, parabéns!

Uma questão importante e que deve se levar em consideração é quanto a precisão dos temporizadores, como tu citou. Em microcontroladores com osciladores internos, como poderíamos resolver o problema de precisão resultante de um grande tempo de operação do circuito, por exemplo:

– A cada 1 hora de execução, percebe-se que o delay acumulado é de 1 segundo;

Tu já passou por algum caso deste tipo?

Mário Marques
Mário Marques
Reply to  Cassiano Campes
27/05/2016 13:13

Obrigado pelo comentário. Tipicamente uso esta implementação em casos em que não tem problema contar 5,01ms em vez de 5ms, ou seja tarefas não criticas, se precisas de facto desse grau de precisão é recomendável a utilização de um oscilador externo devidamente calibrado ou um timer de hardware dedicado à tarefa que necessitas. Recentemente tive um problema parecido com o que descreves, precisava de gerar um pulso com uma largura de 5ms e usava esta biblioteca com uma máquina de estados. Esporadicamente o pulso tinha uma duração superior aos 5ms o que fazia o sistema falhar, o problema detectei mais… Leia mais »

Talvez você goste:

Séries

Menu