Você está na página 1de 19

SISTEMAS EMBARCADOS

AULA 3

Prof. Rafael Vilas Boas Wiecheteck


CONVERSA INICIAL

Nesta aula, serão apresentados os conceitos de interrupção e


temporização utilizados em sistemas computacionais e em sistemas
embarcados.
A interrupção é um mecanismo presente na grande maioria dos sistemas
embarcados, pois permite que a execução normal do código principal seja
suspensa temporariamente para que o processador possa realizar outra
atividade.
O sistema de temporização também é um recurso de extrema
importância, visto que um sistema computacional precisa de um controle de
tempo para organizar, gerenciar e executar as diversas atividades e recursos.
Além de gerenciar toda a atividade interna de um controlador, os
temporizadores são utilizados nos softwares desenvolvidos e no controle de
tempo decorrido em eventos externos.

TEMA 1 – INTERRUPÇÕES: CONCEITOS

A utilização de interrupções é uma forma mais elaborada de gerenciar o


relacionamento do processador com outros periféricos, tanto internos ao
processador quanto os dispositivos externos. É um aspecto importante no
desenvolvimento de softwares embarcados, pois os microcontroladores, além de
apresentarem menor poder de processamento em relação aos
microprocessadores, realizam um intenso contato com o meio externo,
monitorado e controlado.
As interrupções devem ser estudadas com cuidado para que aplicações
eficientes possam ser criadas. Por isso, é importante entender o que acontece
quando há uma interrupção e como ela deve ser processada.
Uma interrupção pode ser usada para uma grande variedade de eventos.
Por exemplo, sinalizar a chegada de uma informação que deve ser lida, que um
tempo pré-determinado passou ou que um usuário pressionou um botão.
A interrupção permite ao desenvolvedor separar operações críticas do
programa principal e garantir que sejam tratadas de maneira correta e no tempo
certo.
O disparo de uma interrupção pode ser feito de forma intencional, via
software, por um erro, em função de uma condição não usual ou por um evento
externo não planejado.
Conhecer o funcionamento interno deste mecanismo permite ao
programador tomar melhores decisões sobre quando utilizá-lo, além de
desenvolver softwares que tratem essas exceções corretamente.
Falando na forma construtiva, há duas maneiras de utilizar as interrupções
nos processadores: na primeira, os periféricos são ligados diretamente aos pinos
de interrupção do processador. Neste caso, o processador apresenta um
controlador interno para gerenciar a chegada das interrupções (Figura 1A). Na
segunda, os periféricos são conectados a um controlador externo. Este
controlador recebe vários sinais de interrupção e os multiplexa em uma única
saída para o processador (Figura 1B). Em ambos os casos, é possível que as
interrupções sejam desabilitadas individualmente.

Figura 1 – Forma de controla das interrupções

Fonte: Adaptado de Barr, 2009.

1.1 Interrupções e exceções

As interrupções e exceções são quaisquer eventos que interrompam a


execução normal do processador e o forcem a executar instruções especiais em
um modo privilegiado.
Esses eventos são chamados em diferentes circunstâncias e tratados
pelo programador de diferentes maneiras. Basicamente, podemos dividi-los em
exceção e interrupção.

3
1.1.1 Exceção

Uma exceção é uma sinalização de detecção de erro que ocorre devido a


eventos internos, ou seja, eventos gerados pela execução de alguma instrução
do processador.
Este tipo de evento é caracterizado como síncrono, pois resulta de outro
evento interno ao sistema, e, portanto, sua ocorrência pode ser prevista.

1.1.2 Interrupção

Uma interrupção está associada a eventos externos ao processador. Na


maioria dos casos, relaciona-se a sinais elétricos de outros periféricos ou
dispositivos que precisam se comunicar com o processador.
Este evento é caracterizado como assíncrono, ou seja, é imprevisível. Não
está relacionado a qualquer outro evento conhecido dentro do sistema e pode
ocorrer a qualquer momento durante a execução do programa principal.

1.1.3 Aplicações das exceções e interrupções

De modo geral, as interrupções e exceções são aplicadas em três áreas


principais:

• Gerenciamento de erros internos e condições especiais: o


processador precisa manipular e recuperar adequadamente os erros sem
que o sistema pare de funcionar. Se uma condição imprevista ocorre, por
exemplo, causada por uma divisão por zero, overflow ou erro matemático,
a aplicação deve ser comunicada. Nestes casos, uma rotina especial é
inicializada para tratar o erro.
• Concorrência de hardware: há situações em que o processador pode
delegar tarefas específicas para outros dispositivos, permitindo que sejam
executadas tarefas de forma paralela. Nestes casos, como os dispositivos
externos precisam de uma intervenção mínima do processador, quando
finalizam determinada tarefa, é enviada uma interrupção ao processador
para sinalizar o término da sua execução.
• Gerenciamento de requisição de serviços: outro uso é fornecer um
mecanismo de comunicação para que um dispositivo externo requisite um
serviço do processador. Por exemplo, uma interface de comunicação usa

4
a interrupção para indicar que um pacote de dados chegou e está
disponível para ser lido.

1.2 Prioridades

Cada processador tem suas características particulares de


funcionamento, por isso é fundamental que os datasheets dos sistemas
selecionados sejam estudados para ter certeza de que atendem às
necessidades exigidas.
Vários processadores utilizam prioridades para determinar a interrupção
que deve ser tratada primeiro. Há níveis de prioridade para os diferentes tipos
de interrupções.
Quando uma interrupção ocorre, o processador desabilita todas as
interrupções de mesma prioridade e de prioridades menores. O método de
manipulação das interrupções varia entre os diversos processadores.
Se uma interrupção de baixa prioridade estiver sendo executada e uma
interrupção de alta prioridade entrar, a primeira será interrompida para que a
segunda possa ser iniciada. Ao término de sua execução, a primeira retorna ao
processador para terminar suas instruções. Este procedimento de parar uma
interrupção em detrimento de outra para depois voltar à primeira é chamado de
interrupt nesting. A figura 2 apresenta graficamente o conceito de interrupt
nesting.

Figura 2 – Exemplificação de uma interrupt nesting

Fonte: Yiu, 2016.

5
TEMA 2 – INTERRUPÇÕES: FUNCIONAMENTO

2.1 Níveis e bordas

As interrupções podem ser detectadas de duas formas: pela sensibilidade


ao nível de tensão e pela sensibilidade à mudança de tensão, ou seja, pelas
bordas de subida e de descida.
Na interrupção sensível a nível, a ação do processador ocorre quando há
mudança no nível de sinal dessa sinalização. Ela pode ser sensível a nível alto
ou baixo, ou seja, quando é sensível a nível alto a interrupção ocorre enquanto
o sinal estiver em nível 1 (com tensão), por outro lado, quando é sensível a nível
baixo, a interrupção ocorre enquanto o sinal estiver em nível 0 (sem tensão). A
figura 3 apresenta uma interrupção ativada por nível de tensão alto (nível 1).

Figura 3 – Interrupção sensível a nível de tensão alto

Fonte: Adaptado de Barr, 2009.

A interrupção sensível à borda é acionada sempre que houver uma


transição de estado, podendo ser pela transição do nível baixo para o nível alto,
chamada de borda de subida (figura 4-B1), ou pela transição do nível alto para
o nível baixo, chamada de borda de descida (figura 4-B1).

6
Figura 4 – Interrupção sensível à borda: (B1) Sensível à borda de subida / (B2)
Sensível à borda de descida

Fonte: Adaptado de Barr, 2009.

Alguns processadores permitem que uma interrupção possa ser


configurada tanto como sensível a nível como sensível à borda. Essa
configuração é feita por meio da programação de seus registradores e
normalmente é selecionada com base em um bit que, quando setado, atende a
uma sensibilidade e, quando resetado, atende à outra.
A definição de qual modo de detecção utilizar depende da aplicação
desenvolvida e deve ser bem planejada, pois isso pode afetar a detecção de
interrupções que chegarem posteriormente.

2.2 Habilitando e desabilitando as interrupções

As interrupções podem ser mascaráveis ou não-mascaráveis. As


mascaráveis podem ser habilitadas/desabilitadas via software, enquanto as não-
mascaráveis não podem ser desabilitadas. Exemplo: falha de energia e reset.
As interrupções mascaráveis podem ser habilitadas e desabilitadas de
forma individual ou global. Essas máscaras são aplicadas por meio de um
registrador que faz o controle das interrupções. A figura 5 apresenta, como
exemplo, um registrador utilizado no controlador de cache da arquitetura ARM.
Pode-se verificar que os 9 primeiros bits são utilizados para mascaramento de
alguns erros de memória. Neste caso, o bit 1 habilita o sinal de interrupção e o
bit 0 desabilita.

7
Figura 5 – Um dos registradores utilizados para mascaramento de sinal no
processador ARM

Fonte: ARM Information Center.

Quando se trabalha com periféricos externos, o processo é o mesmo, há


um registrador que permite habilitá-los e desabilitá-los.
É importante ressaltar que a habilitação da interrupção no software após
sua desabilitação não pode ser esquecida, pois um problema comum é
desabilitar a interrupção ao entrar em uma função e esquecer de habilitá-la
novamente ao terminar de executar o código. Esta falha pode levar a
comportamentos inesperados do sistema.

2.3 Mapa de interrupções

Quando um processador inicia o ciclo de energização, tanto no boot


quanto no reset, as interrupções são desabilitadas. Um dos trabalhos do código
de inicialização é habilitar todas as interrupções assim que o sistema esteja
pronto para elas.
Uma Rotina de Serviço de Interrupção (ISR – Interrupt Service Routine)
executa as ações necessárias para lidar com essas interrupções.
Para que o processador possa executar a ISR corretamente, realiza-se o
mapeamento das interrupções. Este mapa de interrupção é uma tabela que
contém a lista de interrupções e a quais dispositivos elas se referem,
normalmente representado em um formato de tabela de vetores.
Essa tabela de vetores faz referência a um endereço de memória
conhecido pelo hardware, sendo normalmente um array de ponteiros para as
funções que tratam cada interrupção. O processador utiliza o número da
interrupção como um índice dentro desta array.
8
A figura 6 apresenta o mapa de interrupção principal do processador ARM
Cortex-A 53 que equipa o kit Raspberry Pi 3.
Vale ressaltar que, devido à complexidade desse processador, o mapa de
interrupção da figura 6 apresenta somente o mapa principal que engloba todos
os tipos de interrupções do sistema. Várias dessas interrupções são de uso
exclusivo do fabricante do chip.

Figura 6 – Mapa da memória de interrupções do processador ARM Cortex-A 53

Fonte: ARM Technical Reference Manual.

De modo geral, o desenvolvedor deve implantar uma ISR mesmo que as


interrupções não sejam utilizadas pelo sistema, pois isto evita que uma
interrupção ocorra e a sua execução se torne indefinida, o que pode causar
alguma falha.
A ISR garante que todas as interrupções serão conhecidas e
processadas.

2.4 Rotina de Serviço de Interrupção (ISR – Interrupt Service Routine)

A Rotina de Serviço de Interrupção (ISR) é a função chamada quando


determinada interrupção ocorre. O propósito é processar a interrupção e retornar
o controle para o programa principal.
Normalmente, as funções ISR não possuem argumentos e não retornam
valor algum.
Uma ISR é responsável pelas seguintes atividades:

9
• Salvar o contexto que está no processador: como os mesmos
registradores são utilizados tanto pelo programa principal quanto pelo
ISR, é função deste último salvar o estado do processador antes de
executar qualquer processo de interrupção. Vale lembrar que um contexto
consiste em ponteiros, registradores e flags. Normalmente, este passo é
realizado automaticamente.
• Reconhecimento da interrupção: executa as ações necessárias para a
interrupção e também limpa a interrupção existente para sinalizar que
esta já foi tratada.
• Restaurar o contexto no processador: após finalizar o processamento
da interrupção, os valores salvos antes de realizar a troca de contexto são
restaurados no processador para que o programa principal continue sua
execução. Normalmente, os processadores realizam este passo
automaticamente.

Quando o software está sendo desenvolvido, é interessante incluir o ISR


de determinado dispositivo no driver do periférico. Isso permite que este código
específico fique isolado em um módulo.
Um conceito importante associado às interrupções é a latência. A latência
da interrupção é o tempo entre a ocorrência da interrupção e o início do ISR pelo
processador. Este é um item importante em sistemas de tempo real.

TEMA 3 – APLICAÇÃO DE INTERRUPÇÕES

Quando se utiliza um sistema operacional em aplicações de sistemas


embarcados, muitos dos conceitos vistos nessa aula ficam transparentes ao
desenvolvedor devido à utilização das bibliotecas disponíveis que realizam todo
o tratamento necessário.

3.1 Utilização de interrupções no Raspberry Pi

Vamos considerar que, ao desenvolver uma aplicação para Raspberry Pi,


com a utilização da linguagem de programação Python, seja necessário
identificar quando um botão é pressionado.
O modo mais simples de realizar essa tarefa é conforme mostrado na
figura 7, em que, dentro da instrução while true, há a linha 11, responsável por

10
verificar se houve alteração no pino externo número 12 da placa. Portanto, se o
botão for pressionado, será executado o código que se encontra dentro do if not.

Figura 7 – Código em Python apresentando o monitoramento de um botão


(verificando se o botão foi pressionado)

Este código, apesar de atender ao problema proposto, não é a solução


ideal para uma aplicação de sistema embarcado, pois ficará testando o pino de
entrada a todo o instante e, consequentemente, consumindo ciclos de execução
desnecessariamente.
Para resolver o mesmo problema de forma mais eficiente, podemos
utilizar os conceitos sobre interrupções em nosso código. A figura 8 apresenta o
mesmo código para detectar que o botão foi pressionado, porém com a utilização
da interrupção.
Nas linhas 11 e 12 está a função que será chamada quando o evento
ocorrer; na linha 17, é configurado como o evento será detectado. Neste caso,
quando for detectada a borda de descida no pino 12, haverá um desvio para a
função muda_evento.
Dessa forma, junto ao código principal, há a linha 21, que sinalizará
quando ocorrer uma borda de descida no pino 12, não sendo mais necessário
checar a todo o instante como está a situação do pino monitorado.

11
Figura 8 – Utilização de interrupção para monitorar a mudança de estado do
botão

3.2 Utilização de exceções

Vimos, nesta aula, que as exceções são um tipo de interrupção que


ocorrem de forma síncrona ou previsível, e são geradas por erros ou falhas
internas. Portanto, é possível incluir em nossos códigos formas de identificá-las
e tratá-las.
A figura 9 apresenta o tratamento de exceções em Python. Este programa
simples solicita que o usuário digite um número qualquer. Na linha 10, o valor
digitado é convertido para float, porém, se o usuário digitar qualquer caractere
que não seja um número, a conversão não poderá ser realizada e um erro será
sinalizado.
Como desenvolvedores, devemos tratar esse erro, e podemos fazê-lo
conforme pode se vê na linha 12, que é para onde o código é desviado nessa
situação. Assim, o usuário é alertado de que não digitou um número
corretamente e é gerada nova tentativa.
Outro ponto em que podemos verificar a utilização do tratamento de
exceções no código é na linha 19. Neste caso, o tratamento é feito quando o
programa for finalizado abruptamente pelo usuário (utilizando o comando ctrl+c).

12
Um exemplo desta utilização no Raspberry Pi é quando se realiza a
limpeza dos pinos do GPIO (pinos externos) quando o programa é finalizado
repentinamente, pois, fazendo isso, previne-se que um comportamento não
esperado ocorra nos periféricos controlados.

Figura 9 – Exemplo da utilização de tratamento de exceção

TEMA 4 – TIMERS E SERVIÇOS DE TEMPORIZAÇÃO

Sistemas embarcados frequentemente necessitam de mecanismos para


contar ocorrências de determinado evento e realizar tarefas em intervalos
regulares. Além disso, em aplicações que utilizam sistemas operacionais de
tempo real e que são multitarefas, é comum que as tarefas utilizem o
agendamento (escalonamento) ou realizem alguma atividade após determinado
período de tempo.
Estes tipos de atividades são realizados por meio da utilização de timers,
que fazem parte de praticamente todos os tipos de sistemas embarcados.
Sistemas mais complexos podem utilizar dois tipos diferentes de timers: o
hard-timer e o soft-timer.

13
Um hard-timer é um timer via hardware, ou seja, há um circuito específico
para realizar essa tarefa. Este tipo de timer interrompe diretamente o
processador quando precisa sinalizar que o período expirou.
São utilizados em situações onde há a necessidade de precisão ou
quando é necessário que a latência seja previsível.
Por outro lado, o soft-timer é um evento agendado via software e, por isso,
não possui a mesma precisão que um hard-time.
Algumas aplicações necessitam de timers com alta precisão e com
resolução na ordem de microssegundos e até mesmo nano segundos. Nestes
casos, o hard-time é mais indicado.
Nos casos em que há maior tolerância com a precisão dos timers, é
recomendada a utilização de soft-timers. Outra razão para o uso do soft-timer é
a redução da sobrecarga no sistema de interrupção. A latência e a sobrecarga
podem aumentar de forma substancial com o crescimento exagerado do uso de
timers via hardware.

4.1 Programmable interval timer

Programmable internal timer (PIT), também conhecido como timer chip, é


um dispositivo desenvolvido especificamente para funcionar como um contador
de eventos, indicador de tempo decorrido, gerador de eventos periódicos entre
outras aplicações para resolver problemas de controle de tempo.
Normalmente, esta funcionalidade é incorporada no processador. Estes
circuitos dedicados têm o objetivo de reduzir a sobrecarga da CPU.

4.2 Tick – Unidade de tempo

Cada interrupção do temporizador é chamada de tick e representa uma


unidade de tempo. A taxa de interrupção do temporizador é o número de
interrupções geradas por segundo. Por exemplo, se a taxa é de 100 ticks, o
tempo decorrido é de 100ms. Essa taxa é calculada em função da frequência do
clock de entrada e é gerenciada pelo circuito controlador de tempo.

14
TEMA 5 – APLICAÇÃO DO SISTEMA DE TEMPORIZAÇÃO

A utilização de um sistema operacional em sistemas embarcados permite


que todo o sistema de temporização visto anteriormente fique transparente ao
desenvolvedor pela utilização de bibliotecas e funções pré-definidas na
linguagem de programação utilizada.
Na maioria das aplicações, a utilização dessas funções é suficiente para
o desenvolvimento dos projetos. Nos casos específicos em que as restrições de
tempo ou temporização forem mais rígidas, pode ser necessário combinar tais
funções padrão com códigos de baixo nível para que os resultados desejados
sejam obtidos.
É importante lembrar que o sistema operacional pode criar vários
temporizadores lógicos, por exemplo, a implementação de tarefas periódicas,
time-outs e watch-dogs. Porém, todos são baseados nas interrupções geradas
pelo controlador de timer implementado em hardware que os atualiza
periodicamente.

5.1 Função sleep

A função sleep pode ser utilizada na maioria das linguagens de


programação. Entretanto, esta função pausa a execução do programa durante o
período especificado, ou seja, nenhuma outra instrução é executada nesse
período. Esta função utiliza o hardware de temporização para monitorar o tempo
de pausa.
A figura 10 apresenta um pequeno código escrito em Python, para o
Raspberry Pi, para fazer com que um LED fique piscando. Neste código, é
possível ver, nas linhas 14 e 16, a função time.sleep(1) que especifica uma
pausa de 1 segundo antes de realizar a próxima instrução.

Figura 10 – Exemplo de utilização de temporização em Python para uma


aplicação em Raspberry Pi

15
Fonte: RasPiNews, 2017.

Para aplicações onde o tempo e a ociosidade do processador não são um


problema, essa solução pode ser utilizada. Segundo a documentação da
linguagem Python, para um sistema operacional Linux, a taxa de interrupção
(tick) pode chegar próximo a 1 milissegundo. Para tempos menores, é
necessário a utilização de outras soluções.
Uma alternativa para evitar que o código fique bloqueado durante o tempo
do comando sleep é a utilização de funções e eventos. Segundo o Python Brasil,
é possível desenvolver códigos de diferentes formas, de modo a atender às
necessidades de cada aplicação.

FINALIZANDO

Nesta aula, vimos os conceitos de interrupção, exceção e temporização.


Para aplicações em que se utiliza um sistema operacional comercial e de uso
geral, esses conceitos podem passar despercebidos, pois a utilização das
funções disponíveis nas bibliotecas deixa muito desses conceitos transparentes
para o desenvolvedor de aplicações.

16
17
Por outro lado, para um desenvolvedor do sistema como um todo, pode
ser necessário implementar funções de baixo nível e, em alguns casos, até
mesmo desenvolver um sistema operacional específico para determinada
aplicação em particular. Nestes casos, além dos conceitos apresentados nesta
aula, será necessário também um conhecimento mais aprofundado do
microcontrolador e de suas características particulares.

18
REFERÊNCIAS

ARM Cortex-A53 MPCore Processor. Technical Reference Manual. Disponível


em: <https://static.docs.arm.com/ddi0500/f/DDI0500.pdf>. Acesso em: 29 nov.
2017.

BARR, M.; MASSA, A. Programming embedded systems. 2. ed. O’ Reilly


Media, 2009.

LI, Q.; YAO, C. Real time concepts for embedded systems. CMP Books, 2003.

PYTHON Central. Disponível em: <http://pythoncentral.io>. Acesso em: 29 nov.


2017.

RASPINEWS. LED intermitente em Raspberry Pi usando Python. GPIO, 27 jun.


2017. Disponível em: <https://www.raspinews.com/blinking-led-on-raspberry-pi-
using-python>. Acesso em: 29 nov. 2017.

YIU, J. Guia do iniciante sobre latência de interrupção e interrupção da latência


dos processadores Arm Cortex-M. Arm Community, 1 abr. 2016. Disponível em:
<https://community.arm.com/processors/b/blog/posts/beginner-guide-on-
interrupt-latency-and-interrupt-latency-of-the-arm-cortex-m-
processors?CommentId=ca856dbb-6ed1-425d-b72a-b42c7766262a>. Acesso
em: 29 nov. 2017.

19

Você também pode gostar