Arduino Interrup Coes

6
Interrupções no Arduino: uma breve análise Escrito por Gabriel Yoshiaki Hotta em 2013/12/17, sugestões, correções, comentários, etc, podem ser enviadas para [email protected] Requisitos Este artigo supõe que o leitor já possui o conhecimento básico sobre interrupções: o que é uma interrupção, como trata-las (attachInterrupt() e detachInterrupt()). Também é recomendado o conhecimento básico da linguagem Assembly para melhor compreensão, embora não seja estritamente necessário. Introdução Interrupções no Arduino são simples de usar e na maioria das vezes não precisamos nos preocupar com muitos detalhes. Entretanto, quando passam a ser utilizadas várias interrupções, características importantes e que não são tão evidentes passam a possuir grande relevância. Uma delas é a prioridade das interrupções, bem como a necessidade de interrupções aninhadas (nested interruptions). Pouco material sobre o assunto está disponível, e de forma dispersa e fragmentada. Este artigo tenta reunir informações sobre o tema, boa parte do material se baseia na tradução/interpretação do Datasheet. Terminologia Capturar interrupção: tratamento de um evento associado a uma interrupção. Condição de interrupção: circunstancias na qual uma interrupção deve ser efetuada. Habilitação de interrupção: circunstancias na qual o processador é capaz de efetuar a captura de uma interrupção. Rotina de interrupção: conjunto de comandos/instruções que serão executados quando houver captura de interrupção. Os tipos de interrupção Existem basicamente dois tipos de interrupção. O primeiro tipo é capturado por um evento que seta o respectivo bit na "Flag Interrupt". Quando isso acontece a rotina de interrupção associada é executada e o bit na "Flag Interrupt" é limpo (zerado). Se durante a execução da rotina de interrupção houver uma nova condição de interrupção, o bit será novamente setado e manterá seu valor até a interrupção ser novamente habilitada (também é possível limpar o bit explicitamente dentro da rotina, impedindo a execução posterior da rotina de interrupção). O segundo tipo de interrupção é capturado tão logo a condição de interrupção esteja presente, elas não utilizam necessariamente a "Flag Interrupt". Se a condição de interrupção

Transcript of Arduino Interrup Coes

Page 1: Arduino Interrup Coes

Interrupções no Arduino: uma breve análise

Escrito por Gabriel Yoshiaki Hotta em 2013/12/17, sugestões, correções, comentários, etc,

podem ser enviadas para [email protected]

Requisitos Este artigo supõe que o leitor já possui o conhecimento básico sobre interrupções: o que é

uma interrupção, como trata-las (attachInterrupt() e detachInterrupt()).

Também é recomendado o conhecimento básico da linguagem Assembly para melhor

compreensão, embora não seja estritamente necessário.

Introdução Interrupções no Arduino são simples de usar e na maioria das vezes não precisamos nos

preocupar com muitos detalhes.

Entretanto, quando passam a ser utilizadas várias interrupções, características importantes e

que não são tão evidentes passam a possuir grande relevância. Uma delas é a prioridade das

interrupções, bem como a necessidade de interrupções aninhadas (nested interruptions).

Pouco material sobre o assunto está disponível, e de forma dispersa e fragmentada. Este artigo

tenta reunir informações sobre o tema, boa parte do material se baseia na

tradução/interpretação do Datasheet.

Terminologia Capturar interrupção: tratamento de um evento associado a uma interrupção.

Condição de interrupção: circunstancias na qual uma interrupção deve ser efetuada.

Habilitação de interrupção: circunstancias na qual o processador é capaz de efetuar a captura

de uma interrupção.

Rotina de interrupção: conjunto de comandos/instruções que serão executados quando

houver captura de interrupção.

Os tipos de interrupção Existem basicamente dois tipos de interrupção. O primeiro tipo é capturado por um evento

que seta o respectivo bit na "Flag Interrupt". Quando isso acontece a rotina de interrupção

associada é executada e o bit na "Flag Interrupt" é limpo (zerado). Se durante a execução da

rotina de interrupção houver uma nova condição de interrupção, o bit será novamente setado

e manterá seu valor até a interrupção ser novamente habilitada (também é possível limpar o

bit explicitamente dentro da rotina, impedindo a execução posterior da rotina de interrupção).

O segundo tipo de interrupção é capturado tão logo a condição de interrupção esteja

presente, elas não utilizam necessariamente a "Flag Interrupt". Se a condição de interrupção

Page 2: Arduino Interrup Coes

surgir e desaparecer antes da interrupção estar habilitada a rotina de interrupção associada

não será executada.

Se duas ou mais condições de interrupção ocorrerem simultaneamente haverá uma prioridade

de execução entre as interrupções.

Ao sair de uma rotina de interrupção o AVR irá retornar ao programa principal e executar uma

instrução antes de executar a próxima rotina de interrupção.

Ou seja, se houver duas condições de interrupção, a rotina de interrupção da primeira (com

maior prioridade) será executada, em seguida uma, e somente uma, instrução do programa

principal será executado e apenas depois disso a segunda rotina de interrupção será

executada.

O "Status Register" não é automaticamente armazenado ao entrar em uma rotina de

interrupção, nem é restaurado ao sair da Rotina de interrupção. Cabe ao programador faze-lo

caso seja do seu interesse.

Prioridade de interrupções A prioridade de execuções é dada pela posição no "Interruption Vector", quanto menor a

posição ocupada, maior a prioridade. Para o ATmega2560 (usado no Arduino Mega 2560, em

outros modelos deve-se consultar o respectivo Datasheet) temos a seguinte tabela:

Page 3: Arduino Interrup Coes
Page 4: Arduino Interrup Coes

Interrupções aninhadas (nested interruptions) Quando uma interrupção é capturada a flag de interrupção global "SREG" é zerada,

desabilitando todas interrupções.

Page 5: Arduino Interrup Coes

Ao sair de uma rotina de interrupção é executada a instrução "RETI" que reabilita as

interrupções.

Este é o comportamento desejado na maioria das vezes, pois espera o termino de uma rotina

de interrupção para, em seguida, executar uma outra rotina de interrupção.

Entretanto, se o programador desejar pode-se reabilitar a captura de interrupção dentro de

uma rotina de interrupção. A isso dá-se o nome de interrupções aninhadas (nested

interruptions).

Para habilitar interrupções aninhadas o programador deve explicitamente utilizar a instrução

responsável por habilitar interrupções: sei().

Note ainda que o uso incorreto pode acarretar em infinitas interrupções recursivas.

Ainda há outro porém, mesmo utilizado a instrução "sei()" no início de uma rotina de

interrupção ainda permanecem algumas instruções geradas pelo compilador antes da

instrução Assembly "SEI", ou seja, algumas poucas instruções ainda são executadas com a

interrupção desativada.

O código em C

ISR(TIM0_OVF_vect) { sei(); //do nothing }

Gera o seguinte código assembly:

PUSH R1 ; \ PUSH R0 ; | IN R0, 0x3F ; | interrupcao ainda desativada PUSH R0 ; | CLR R1 ; / SEI ; <<-- reabilita interrupcoes globais POP R0 OUT 0x3F, R0 POP R0 POP R1 RETI ; retorna ao programa principal

Melhor forma de utilizar a instrução SEI A avr-libc permite a inserção da instrução "SEI" antes de qualquer instrução na rotina de

interrupção através da seguinte declaração:

ISR(XXX_vect, ISR_NOBLOCK) {

}

onde XXX_vect é uma interrupção valida no vetor de interrupções.

Por exemplo, o seguinte código C

ISR(TIM0_OVF_vect, ISR_NOBLOCK) { //do nothing }

Page 6: Arduino Interrup Coes

Gera o código Assembly

SEI ; <<-- habilita interrupcoes globais PUSH R1 PUSH R0 IN R0, 0x3F PUSH R0 CLR R1 POP R0 OUT 0x3F, R0 POP R0 POP R1

RETI ; retorna ao programa principal

Fontes Datasheet do ATmega2560

http://www.carlosdelfino.eti.br/eletronica/item/89-prioridade-das-

interrup%C3%A7%C3%B5es-em-microcontroladores-atmega

http://stackoverflow.com/questions/5111393/do-interrupts-interrupt-other-interrupts-on-

arduino

http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

http://ucexperiment.wordpress.com/2013/05/20/nested-interrupts/