Microprocessadores 1º Ano - LECOM Universidade do Minho Dept. De Electrónica Industrial 1 Interrupções: Motivação Pretende-se desenvolver um sistema que sintetize uma onda quadrada com um frequência de 100 KHz e que conte o número de eventos externos. Os eventos externos ocorrem sob a forma de transições negativas no pino 4 do porto A. A solução do problema acima descrito poderia ser: goto gerarperiodo contarevento 1
Interrupções: Motivação goto gerarperiodo contarevento No problema anterior, temos dispositivos que estão a executar comportamento concorrentemente com o programa. Timer: geração da onda quadrada. Porto: que é actuado por um processo externo. Mas poderíamos ainda ter o watchdog timer ou ainda a escrita na EEPROM. Interrupções: Motivação Estes dispositivos ao terminar indicam o fim da tarefa pela activação de um bit num registo. Por exemplo, no caso do timer éo bit T0IF no registo INTCON. Chamamos de polling à estratégia de periodicamente testar o bit de status dos dispositivos para verificar o fim da sua tarefa. 2
Interrupções: Motivação Problemas encontrados na solução anterior baseada em polling: Na solução anterior, teríamos que compensar o atraso da rotina contarevento no cálculo do valor a utilizar na temporização. O valor a usar para o tempo variará consoante houve ou não uma transição no pino de entrada. O que significa que este valor deve ser inicializado na rotina contarevento, embora seja usado na rotina geraronda ; ou seja, estamos a criar uma dependência de dados entre as duas rotinas, o que pode introduzir bugs subtis. goto gerarperiodo contarevento Interrupções: Motivação Imagine que pretendíamos introduzir mais uma operação, por exemplo, zerar o contador e activar uma saída quando o número de eventos externos ultrapassa certo limite. goto gerarperiodo contarevento processarcontagemdeeventos 3
Interrupções: Motivação goto gerarperiodo contarevento processarcontagemdeeventos Consequências da alteração: Teríamos que recalcular o tempo da onda quadrada, sendo que existe um limite para o qual não será possível compensar. Como na implementação das rotinas contarevento e processarcontagemdeeventos existem diferentes caminhos será cada vez mais difícil calcular o valor a usar na temporização. Interrupções: Motivação Podemos concluir que a solução baseada em polling não é indicada quando existem temporizações que temos que obedecer para que o comportamento da nossa aplicação seja correcto. 4
Como definiria interrupção? Sinal gerado por um dispositivo e enviado ao CPU. Este sinal indica ao CPU a ocorrência de um evento externo. Por exemplo, overflow do timer ou ainda a mudança de estado num pino do porto. O CPU executa uma ISR (interrupt service routine), que efectua acções específicas em resposta à interrupção. As interrupções provocam uma transferência de execução para um endereço conhecido onde reside uma rotina de serviço à interrupção (ISR). Ao executar uma ISR, o CPU coloca o endereço de retorno na pilha. Ao concluir a execução da ISR, a instrução de retorno actualiza o (IP) com o endereço de retorno presente na pilha. 5
No caso do PIC: A ISR deve terminar necessariamente com a execução da instrução retfie. Portanto a estrutura de uma ISR será a seguinte: entradadaisr ; Implementação da ISR retfie A instrução retfie é responsável por colocar o endereço de retorno que está guardado no topo da pilha no registo e por habilitar as interrupções 6
Interrupção versus Polling Vantagens do Polling Utiliza poucos recursos de Hw, e como tal é fácil de implementar A execução está sincronizada com a execução do programa, o programador sabe exactamente quando é verificado o estado do dispositivo e quanto tempo será necessário para servi-lo. Não será necessário um sistema automático para salvaguardar o estado do processador Não requer atenção à gestão da pilha Vantagens da Interrupção Não desperdiça tempo de execução na verificação contínua do estado dos dispositivos O atendimento aos dispositivos pode ser imediato, fornecendo por isso capacidade de resposta em tempo-real Interrupção versus Polling Desvantagens do Polling Desperdiça tempo de execução, reduzindo por isso tempo disponível às outras actividades Os dispositivos não podem ser atendidos de forma instantânea, tornando-se às vezes necessário mais recursos de armazenamento Dispositivos menos prioritários podem nunca ser atendidos Desvantagens da Interrupção Requer Hw extra e complexo. Introduz um overhead sempre que um dispositivo interrompe a execução do programa. A execução da ISR é assíncrona relativamente à execução do programa, dificultando a estimação da temporização da interrupção. A gestão de um número excessivo de interrupções pode tornar o sistema lento, podendo mesmo bloqueá-lo. 7
As interrupções podem ser mascaradas ou desactivadas. O CPU recebe informação para ignorar as interrupções. A maioria dos processadores apresenta uma instrução que informa o CPU para ignorar todas as interrupções macaráveis. Designado por desactivação das interrupções. O controlador de interrupções normalmente fornece facilidades para desactivar interrupções individualmente. No caso do PIC: Temos as seguintes fontes de interrupções: Interrupção externa RB0/INT. Timer 0. Transição de estado no porto B (RB7:RB4). Fim de escrita de um dado na EEPROM. 8
No caso do PIC: As interrupções são controladas pelo registo INTCON bit 3 Estes bits permitem activar ou desactivas cada uma das fontes de interrupção. A terminação indica: XXIE interrupt enable No caso do PIC: O status das interrupções são consultados no registo INTCON bit 2 Estes bits permitem identificar qual foi a fonte de interrupção, ou seja, quem provocou a interrupção (timer, interrupção externa, ) 9
Mas onde encontramos o status associado a interrupção de fim da escrita de EEPROM? Este se encontra no registo EECON1. bit 4 Quando se deve desactivar as interrupções? Quando estamos a executar uma actividade que não deve ser interrompida, ou seja, quando a actividade deve ser considerada como atómica. 10
Como é que o CPU sabe qual a ISR a executar aquando da ocorrência de uma interrupção? Cada interrupção tem associado um número de identificação. O CPU usa este número de interrupção para consultar a tabela de vectores de interrupção e obter o endereço da ISR correcta. A tabela de vectores é uma colecção de apontadores para as ISRs. O número da interrupção serve de índice na tabela de vectores de interrupção. Cada entrada da tabela de vectores de interrupção tem um número fixo de bytes que é suficientemente grande para armazenar um endereço de memória. O que acontece logo no início da ocorrência de uma interrupção? Ocorrência de Interrupção Registo de flags Outros Registos Programa em execução instr n-1 instr n instr n+1 ISR Memória de código Pilha Tabela de vectores de interrupção 11
Ocorrência de Interrupção Registo de flags Outros Registos Pilha Programa em execução instr n-1 instr n instr n+1 ISR Tabela de vectores de interrupção Uma interrupção é desencadeada durante a execução da instrução n. O sistema concluí a execução da instrução n. Como resposta, o sistema salvaguarda o actual e o registo das flags na pilha. Ocorrência de Interrupção Registo de flags Outros Registos Pilha Programa em execução instr n-1 instr n instr n+1 ISR Tabela de vectores de interrupção Uma interrupção é desencadeada durante a execução da instrução n. O sistema concluí a execução da instrução n. Como resposta, o sistema salvaguarda o actual e o registo das flags na pilha. 12
Interrupção Pilha Registo de flags Programa em execução instr n-1 instr n instr n+1 ISR Tabela de vectores de interrupção A tabela de vectores é uma colecção de apontadores para as ISRs. O número de interrupção serve de índice na tabela de vectores de interrupção Cada apontador corresponde a um número de interrupção. Interrupção Pilha Registo de flags Programa em execução instr n-1 instr n instr n+1 ISR Tabela de vectores de interrupção Alguns processadores usam uma tabela de saltos em vez da tabela de vectores de interrupção. Cada entrada na tabela deve ser capaz de armazenar uma instrução de salto. O processador salta para uma entrada da tabela e literalmente será redireccionado para a ISR dado que a entrada é uma instrução de salto. 13
Interrupção Registo de flags Outros Registos Pilha Programa em execução instr n-1 instr n instr n+1 ISR Tabela de vectores de interrupção Ao concluir a execução, a ISR restaura da pilha os registos que o programa interrompido usava Restaura também o registo Esta última operação devolve o controlo ao programa interrompido No PIC O processamento das interrupções do PIC é bastante elementar. A tabela de vectores do PIC tem apenas uma entrada no endereço 0x0004. Nesta entrada deve estar o código da ISR ou uma instrução de goto para a ISR. 14
Mas se o PIC apenas tem uma entrada na tabela de vectores como é possível distinguir qual é a fonte de interrupção (Timer, entradas dos portos, )? Como todas as interrupções do PIC partilham o mesmo vector de interrupção, o programador terá que na entrada da ISR testar os bits de status (INTCON e EECON2) para determinar quem causou a interrupção. O mapa da memória de código do PIC será então: org 0x000 goto main org 0x004 goto myisr myisr retfie main END 15
Quando se deve desactivar determinada interrupção em vez de desactivar todas as interrupções? Deve-se mascarar uma interrupção caso não seja usada, evitando deste modo a possibilidade de ocorrência de falsas interrupções. A maioria das aplicações desactivam todas as interrupções que não estejam em uso durante a inicialização. Uma ISR deve mascarar a sua própria interrupção para impedir a reentrância, activando-a posteriormente ao concluir o processamento. Tem a vantagem de desactivar apenas uma determinada interrupção, enquanto permite que outras interrupções possam ser processadas. No PIC Em geral sabemos que: Uma ISR deve mascarar a sua própria interrupção para impedir a reentrância, activando-a posteriormente ao concluir o processamento. Contudo: No PIC não é necessário desactivar a interrupção, porque por defeito o PIC desactiva todas as interrupções ao passar o controlo à ISR, voltando a realbilitá-las quando a instrução retfie é executada. 16
O que se entende por estado do CPU? Na maioria dos processadores, o estado do CPU é constituído pelos registos genéricos e pelas flags do processador Normalmente, as flags do processador são salvaguardadas na pilha juntamente com o endereço de retorno ao código interrompido A instrução retorno-da-interrupção executada no final da ISR restaura automaticamente as flags e transfere o controlo à aplicação interrompida Ao seleccionar um processador deve-se compreender o que constituí o estado do CPU, bem como se as ISRs devem preservar algo para além dos registos genéricos No caso do PIC: O estado do processador compreenderá o registo de STATUS, o registo W e o registo FSR (caso a ISR use o modo de endereçamento indirecto). Uma vez que não existe instruções de push e pop não é possível usar a stack para guardar dados, então o estado do processador deve ser armazenado na memória interna do processador. Por ex., movwf wtemp ; guarda W movf STATUS, W movwf statustemp ; guarda STATUS movf FSR, W movwf fsrtemp ; guarda FSR 17
Na saída da ISR, o estado inicial do processador deve ser reposto. Por ex., movf fsrtemp, W movwf FSR ; restaura valor de FSR movf statustemp, W movwf STATUS ; restaura valor de STATUS movf wtemp, W ; restaura valor de W Porque é que uma ISR deve preservar o estado do CPU? Se não preservar o estado do CPU, quando a ISR termina a execução e devolve o controlo à aplicação interrompida, esta encontrará valores diferentes nos registos. Repare que a aplicação não tem conhecimento de que foi interrompida. Em tais casos, a depuração da aplicação é difícil, porque o sistema começará a crashar de forma estranha e de difícil reprodução o cenário resultante do crash será único Notar que cada vez que a ISR é executada e corrompe os registos, uma secção diferente do código da aplicação estará em execução 18
Interrupções: Exemplo Problema. Sabendo que dispõe de um sistema com um microcontrolador PIC 16F84A com um cristal de 4 MHz, escreva um programa para gerar uma onda quadrada com uma frequência de 10 KHz. 19