12 Comentários

Arquitetura de desenvolvimento de software – parte IV

função de recepção

No modelo de máquina de estados, assim que uma função termina, o processador automaticamente passa para a próxima tarefa, independente de questões temporais. No entanto, passa a ser extremamente complicado fazer qualquer garantia de tempo de execução, pois além dos tempos serem regidos pelo tamanho da tarefa, estes tempos podem ainda variar. Um bom exemplo é a recepção de comandos pela serial. Nem sempre o sistema recebe bytes e, mesmo quando recebe, ele precisa aguardar todos os bytes chegarem para processar a mensagem. Assim, a função de recepção tem pelo menos três durações diferentes: quando não há nada na serial, quando há informação na serial a ser salva e quando há uma mensagem para ser processada.

Uma característica desejada nos sistemas embarcados é que as funções tivessem um tempo determinado de execução. Deste modo, todo o sistema se tornaria mais previsível.

A maneira mais simples de realizar este procedimento é fazer com que, nas vezes que a função for executada e terminar antes, o sistema faça com que ela aguarde até um determinado valor de tempo. Este valor tem que ser maior que o pior caso de execução da função.

Apesar de não ser ideal, já que o processador irá ficar tempo ocioso apenas para padronizar os tempos de execução das funções, o determinismo atingido por esse método traz imensas vantagens no desenvolvimento. Outra vantagem é que é possível criar uma arquitetura que faça essa garantia consumindo poucos recursos, ou seja, esta é uma abordagem possível de se implementar em sistemas que não são capazes de suportar um sistema de tempo real como o FreeRTOS.

Para isso basta ter acesso à um temporizador em hardware. Basta então inicializar a contagem no top-slot da arquitetura de máquina de estados e aguardar o fim da contagem no bottom-slot. Deste modo, toda vez que um slot terminar, o sistema ficará aguardando o tempo definido antes de iniciar o próximo slot.

No exemplo apresentado é inserida a função AguardaTimer() no bottom-slot de modo que a próxima função só executará em 5 (ms).

Como podemos notar, se a função ultrapassar 5 (ms) todo o cronograma será afetado. É necessário então garantir que todo e cada slot será executado em menos de 5 (ms). Isto pode ser ser feito através de testes de bancada.

Com base no código acima e supondo que a tarefa 1 (LeTeclado(), S.1) gasta um tempo de 2.0(ms), a tarefa 2 (RecebeSerial() , S.2) consuma  3.1 (ms), a tarefa (EnviaSerial(), S.3) apenas 1.2 (ms),  com um top-slot de 0.5 (ms) e um o bottom-slot de 0.3 (ms) temos a figura abaixo representando a linha temporal de execução do sistema.

Linha temporal função de recepção

Podemos notar que para o ciclo do primeiro slot são gastos 0.5+2.0+0.3 = 2.8(ms). Deste modo o sistema fica aguardando na função AguardaTimer() durante 2.2 (ms) sem realizar nenhum processamento útil. Para o segundo slot temos um tempo livre de (5-(0.5+3.1+0.3))=1.1 (ms). O terceiro slot é o que menos consome tempo de processamento, possuindo um tempo livre de (5-(0.5+1.2+0.3))=3.0 (ms).

Utilização do tempo livre para interrupções

Dependendo do tempo escolhido para o slot e do tempo consumido pela função, podem existir espaços vagos na linha de tempo do processador. A figura abaixo apresenta uma linha de tempo de um sistema que possui apenas 1 slot cujo temporizador foi configurado para 8 (ms).

Linha temporal função de recepção

A cada ciclo "sobram" 3(ms). Este tempo pode ser considerado perdido caso exista apenas a tarefa S.1 no sistema. Nesta situação é até mesmo possível diminuir o tempo do temporizador para 5 (ms). Isto permitiria um acréscimo na frequência de execução da tarefa S.1 que era de 125(Hz) para 200(Hz), ou 60%.

No entanto, não havendo tempo livre, qualquer alteração acabaria com o determinismo além de impossibilitar o uso de interrupção sem atrapalhar a frequência de execução. Portanto, esse tempo livre é importante por dois motivos: evitar que pequenas alterações não esperadas na execução das funções impactem na taxa de execução e, mais importante ainda, permitir que as interrupções aconteçam sem causar problema na temporização das tarefas.

A figura abaixo demonstra o mesmo sistema sendo interrompido através de interrupções assíncronas. Neste caso, a interrupção "rouba" 1(ms) a cada iteração da máquina de estados.

Linha temporal com interrupções função de recepção

Como cada interrupção gasta um tempo de 1 (ms) e temos um tempo livre de 3 (ms) em cada ciclo, basta garantir que os eventos que geram a interrupção não ultrapassem a frequência de 3 eventos a cada 8 (ms). Esta análise deve ser feita para assegurar que o sistema, apesar de "perder" tempo de processamento, tenha um modo simples de garantir o determinismo na execução das funções.

O "perder" está entre aspas pois o tempo que o processador fica aguardando no bottom-slot é uma ótima oportunidade para colocar o sistema em baixo consumo de energia e permitir que ele seja acordado com a interrupção do timer. Indo por este caminho de economia de energia, o objetivo passa de "ter uma alta taxa de execução sem tempo ocioso" para "possuir o máximo de tempo livre", reduzindo efetivamente o consumo.

Outros artigos da série

<< Arquitetura de desenvolvimento de software – parte III
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.

Software » Arquitetura de desenvolvimento de software – parte IV
Comentários:
Notificações
Notificar
guest
12 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Marcos Ribeiro
Marcos
24/11/2013 08:47

Muito bom Rodrigo Parabéns! Ficamos no aguardo dos próximos.

Marcelo Rodrigo Dos Santos Andriolli
Marcelo Andriolli
05/11/2013 11:59

Muito bom Rodrigo!! Quais seriam as referencias bibliográficas dessa série de artigos?

Rodrigo Almeida
Rodrigo Almeida
Reply to  Marcelo Andriolli
13/11/2013 14:52

Obrigado Marcelo!

Infelizmente não tenho um livro que fale especificamente sobre arquiteturas para lhe indicar. Boa parte das referências e exemplos que utilizei tirei de códigos fonte no github ou de projetos. Alguns livros interessantes e que comentam um pouco sobre isso são o "The art of programming embedded systems" do Jack Ganssle, e o Embedded systems design and applications with the 68HC12 and HCS12 do Steven Barrett.

Marcelo Rodrigo Dos Santos Andriolli
Marcelo Andriolli
Reply to  Rodrigo Almeida
14/11/2013 11:18

Obrigado Rodrigo pelas referencias passadas. Gostei muito da abordagem que foi dada ao a assunto e a organização lógica. Novamente Parabéns!

André Castelan
02/11/2013 19:41

Muito bom Rodrigo!

Felipe Neves
Felipe Neves
01/11/2013 12:02

Gostei muito dessa série artigos, acho que seria sensacional esse tipo de abordagem nas universades afim de demonstrar diferentes visões de arquitetura de sw para embarcados. E não apenas o tradicional while(1);

Abs.

Felipe

Rodrigo Almeida
Rodrigo Almeida
Reply to  Felipe Neves
13/11/2013 14:54

Até o tradicional while(1) eu não gosto muito, parece que o cara quis fazer um while(i) mas digitou errado. Os meus alunos gostam mesmo é quando eu uso forever. =)

for(;;) //ever

{

}

Fernando Almeida Stock
Fernando Almeida Stock
01/11/2013 10:20

Excelente material! Parabéns!

Matheus Quick
Matheus Quick
13/03/2017 01:02

muito bom

Rodrigo Almeida
Rodrigo Almeida
Reply to  Matheus Quick
13/03/2017 10:14

Obrigado Mateus!

trackback
23/05/2015 12:08

[…] #sharebar { padding: 0; text-align: left; list-style: none; margin: 0; } #sharebar span {float: left; padding: 0 5px; } #sharebar { display: block; margin: 0; padding: 5px 0 5px 5px; overflow: visible; text-align: center; height: 20px;} #sharebar #fb { text-align: left;} #sharebar #tww { width: 95px; overflow: hidden; } p.recommended { padding: 14px; text-align: center; } .page { position: relative; } Tweetar lang: en_US (function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/pt_BR/all.js#xfbml=1"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs'); window.___gcfg = {lang: 'pt-BR'}; (function()… Leia mais »

trackback
23/05/2015 12:07

[…] Arquitetura de desenvolvimento de software – parte IV […]

Talvez você goste:

Séries



Outros da Série

Menu

WEBINAR
 

Soluções inteligentes para acionamento de MOSFETs/IGBTs com família STDRIVE

Data: 08/10 às 15:00h - Apoio: STMicroelectronics
 
INSCREVA-SE AGORA »



 
close-link