Você está na página 1de 33

Entradas/Saídas

Programação por interrupções


Conceitos gerais
Programação da porta série
Transmissão
Problemas a resolver
Como identificar a interrupção?
 Motivo da interrupção
 Que rotina executar?

Como lidar com múltiplas interrupções?


 Uma rotina de tratamento de interrupções pode ser,
por sua vez, interrompida?

Arquitectura de Computadores (2008/2009): Entradas/Saídas 668


Como identificar a interrupção?
Interrogação por software?
 Consulta-se o registo de estado de todos os
controladores? Lento!

Uma linha diferente para cada controlador?


 Limita o número de controladores (e periféricos) ao
número de linhas de interrupção no CPU

Identificação por hardware?


 Existe um dispositivo capaz de identificar o
controlador que interrompeu

Arquitectura de Computadores (2008/2009): Entradas/Saídas 669


Controlador de Interrupções
 Arbitra a linha de interrupção do CPU

 Funcionamento do CPU e Controlador de


Interrupções:
1. Quando de um interrupção o CI activa a linha de
interrupção do CPU
2. CPU aceita a interrupção e activa a linha de
“interrupt acknowledge”
3. O controlador coloca um valor no “bus” de dados; o
CPU usa esse valor para identificar a interrupção e
qual deve ser a rotina de tratamento a chamar

Arquitectura de Computadores (2008/2009): Entradas/Saídas 670


Controlador de Interrupções

Controlador
CPU de interrupções
Int (1)

(2) Controlador
Int Ack periférico

(3)
Linhas de dados do “bus” de entrada/saída

Arquitectura de Computadores (2008/2009): Entradas/Saídas 671


Interrupções vectorizadas
O número da interrupção Vector Interrupções
serve como índice numa (memória)
tabela com endereços de
rotinas (o vector de
interrupções)
Endereço da
3 rotina de
Cada posição do vector tratamento

contém o endereço da interrupção 2


número 3
rotina a chamar para
1
essa interrupção
0

Arquitectura de Computadores (2008/2009): Entradas/Saídas 672


Inicialização do vector de interrupções
Por segurança, quando o CPU começa a funcionar o
sistema de interrupções está desligado

Os controladores só começam a lançar interrupções


depois de instruídos pelo CPU (pelos programas)
para o começarem a fazer

Tipicamente é o SO que inicializa o vector de


interrupções, antes de ocorrer a 1a. interrupção

Arquitectura de Computadores (2008/2009): Entradas/Saídas 673


O estado do sistema de interrupções
O estado do CPU contém uma “flag” Interrupt Flag
(IF) que indica se as interrupções estão ou não
habilitadas

Inicialmente a IF está a 0 – interrupções não


permitidas

Há instruções máquina para ligar e desligar as


interrupções
 São naturalmente instruções privilegiadas

Arquitectura de Computadores (2008/2009): Entradas/Saídas 674


Ciclo de execução de instruções
CICLO {
Fetch:
IR  Mem[PC] -- obtém a instrução na posição de memória
-- apontada pelo P.C.
PC  PC +1 -- actualiza P.C.

Decode/Execute: -- descodifica e executa a instrução em IR

se ( IF && INTR ) { -- interrupções activas e chega interrupção


salva o P.C. e as “flags” (push para o “stack”)
IF  0
passa CPU ao "modo supervisor"
identifica a origem da interrupção (via C.I.)
P.C.  vect_intr[número_da_interrupção]
-- semelhante a um call ao endereço do interrupt handler
}
}

Arquitectura de Computadores (2008/2009): Entradas/Saídas 675


Fim da rotina de tratamento
Quando a rotina de tratamento de interrupção
termina é executada a instrução máquina Interrupt
Return

Esta instrução
 Desempilha o PC, o que faz retomar a execução no
ponto em que a execução “normal” foi interrompida
 Também restaura o valor das “flags”. Isto permite:
 Retomar a execução no ponto onde se encontrava com as
“flags” como se encontravam na altura em ocorreu a
interrupção
 O bit de modo é restaurado. O modo volta a ser “modo
utilizador”

Arquitectura de Computadores (2008/2009): Entradas/Saídas 676


Fim da rotina de tratamento
Nos Intel há uma instrução máquina que se
encarrega disso:
IRET  Interrupt Return

A instrução faz o equivalente a:


POP flags
RET

A execução retoma no ponto onde se encontrava


quando ocorreu a interrupção e com as flags no
estado em que estavam

Arquitectura de Computadores (2008/2009): Entradas/Saídas 677


Salvaguarda/restauro do estado da computação
O hardware só salva automaticamente o PC e as
flags
É a rotina de tratamento de interrupções que tem a
obrigação de salvar os registos do CPU que
“estraga”. Alguns CPUs têm instruções máquina
para empilhar / desempilhar todos os registos

Interrupt_handler:
pushall ; empilha todos os regs
... ; tratamento da interrupção
popall ; restaura todos os registos
iret ; interrupt return

Arquitectura de Computadores (2008/2009): Entradas/Saídas 678


Troca de contexto
Processamento normal: Rotina de tratamento:
(modo utilizador) (modo supervisor)
pushall
Empilhar
PC e flags

INT

Restaura
PC e flags popall
iret

Arquitectura de Computadores (2008/2009): Entradas/Saídas 679


Interromper interrupções
Quando se entra na rotina de tratamento, IF está a 0

Se nada for feito, só será colocada a 1 quando do


“interrupt return”

Mas as interrupções devem estar fechadas o menos


tempo possível –- podem-se perder dados que
cheguem ou tornar a sua saída mais lenta.

A rotina de tratamento deve fazer IF  1 assim que


seja seguro.

Arquitectura de Computadores (2008/2009): Entradas/Saídas 680


Interrupções de múltiplos controladores
As necessidades dos controladores diferem:
 Tempo máximo ao fim do qual têm de receber atenção
 Duração do processamento da interrupção

O processamento de uma interrupção de um


periférico lento pode levar mais tempo do que o
tempo máximo entre interrupções de um periférico
rápido

Para satisfazer estas diferenças são atribuídas


prioridades diferentes aos controladores

Arquitectura de Computadores (2008/2009): Entradas/Saídas 681


Prioridade das interrupções (1)
Múltiplos níveis de interrupção ou múltiplas
prioridades para as interrupções
O CPU (e o seu controlador de interrupções) definem
vários níveis para as prioridades
A cada periférico é atribuída um nível (N):
 Exemplo:
maior (N)  prioridade mínima
0  prioridade máxima
A rotina de atendimento de interrupções do nível i
pode ser interrompida para executar a rotina de
atendimento de um periférico de nível j, se j < i

Arquitectura de Computadores (2008/2009): Entradas/Saídas 682


Prioridade das interrupções: Exemplo
Periférico rápido (disco)
Programa
prioridade/nível 1 (nível N)
Rotina
Periférico lento (impressora) impressora
prioridade/nível 2 (nível 2)
Se estamos a executar a
rotina de tratamento da
impressora e chega uma
interrupção do disco: vai-se
executar a do disco.
Rotina
Quando esta acaba voltamos disco
à rotina da impressora; (nível 1)
quando esta acaba volta-se
ao programa que estava a
correr (nível N)
Arquitectura de Computadores (2008/2009): Entradas/Saídas 683
Tipos de interrupções
Externas: ligadas ao hardware:
 Dispositivos de entrada/saída (I/O)
 Falha no hardware

Internas: ligadas ao software (devido à instrução


executada):
 Excepções (exemplos: divisão por 0, overflow, acesso a
memória não autorizada, execução de instrução
privilegiada em modo utilizador, ...)
 Interrupção por software: existe uma instrução
máquina que provoca deliberadamente uma interrupção
 Pode ser usada para fazer chamadas ao sistema

Arquitectura de Computadores (2008/2009): Entradas/Saídas 684


Mascarar interrupções
Algumas interrupções podem ser mascaradas
(ignoradas)

Tipo de interrupção Mascarável?

Externa Sim

Excepção Algumas

Por software Não

Arquitectura de Computadores (2008/2009): Entradas/Saídas 685


Exemplo – Intel - PC
80x86/Pentium têm uma linha de interrupções
gerais
 A flag IF é alterada pelas instruções
 STI  Set interrupts
 CLI  Clear interrupts
 O retorno da rotina de tratamento é feito pela instrução
IRET
 Instrução de interrupção por software: INT nº

Suportam até 255 tipos de interrupções,


vectorizadas
 O vector está na memória a partir do endereço 0

Arquitectura de Computadores (2008/2009): Entradas/Saídas 686


Relembrando o primeiro exemplo
SYS_EXIT equ 1
LINUX_SYSCALL equ 0x80
global _start
section .data
A: dd 24
B: dd 1
C: dd 0
section .text
_start: mov eax, [A]
add eax, [B]
mov [C], eax
mov eax, SYS_EXIT
mov ebx, 0
int LINUX_SYSCALL
Arquitectura de Computadores (2008/2009): Entradas/Saídas 687
Exemplo – Intel - PC
Usam um controlador de interrupções programável --
PIC (8259A ou equivalente)
 Define as prioridades entre interrupções
 O identificador de cada interrupção, usado como índice
no vector de interrupções

IRQ0
INTR reg. Máscara IRQ1

Controladores
0x21 IRQ2
INTA IRQ3
CPU
IRQ4
reg. Comando IRQ5
CPU bus dados (8bits) IRQ6
0x20
IRQ7

Arquitectura de Computadores (2008/2009): Entradas/Saídas 688


Controlador 8259A (PIC)
Registo de máscara: cada bit i a 1 indica que a linha
IRQi está mascarada (ignorada)

Cada IRQ tem associado no PIC um número de


identificação

No passado existiam apenas 8 designações de IRQ


(0-7)

Actualmente existem mais 8: IRQ 8 a 15

Arquitectura de Computadores (2008/2009): Entradas/Saídas 689


Controlador 8259A (PIC)
Registo de comando
 Permite programar a forma de atendimento, os
identificadores, etc.
 Comando: End of Interrupt (EOI) informa o PIC que a
rotina de atendimento acabou (código 0x20)

IRQ0 IRQ8
reg. Máscara IRQ1 reg. Máscara IRQ9
0x21 0x21 IRQ10
IRQ3 IRQ11
IRQ4 IRQ12
reg. Comando IRQ5 reg. Comando IRQ13
IRQ6 IRQ14
0x20 0x20
IRQ7 IRQ15

Arquitectura de Computadores (2008/2009): Entradas/Saídas 690


Máscara de IRQs
Registo de máscara, indica IRQ ignorados pelo PIC
 8 bits  se 1 - nível (IRQ) desligado
se 0 – nível ligado
 Exemplos:
 Desligar o nível IRQ3
cli
in al, 0x21
or al, 0000 1000B
out 0x21,al
sti
 Ligar o nível IRQ4
cli
in al, 0x21
and al, 1110 1111B
out 0x21,al
sti
Arquitectura de Computadores (2008/2009): Entradas/Saídas 691
Prioridades no PIC
Cada IRQ é um nível de prioridade de interrupções:
 0 mais prioritário; 7 menos prioritário
 O segundo controlador está ligado ao 2
 Logo a ordem de prioridades é: 0-1, 8-15, 3-7
Quando uma interrupção é aceite pelo CPU todas as
IRQ de maior nível ficam pendentes
Cada rotina de tratamento deve terminar com o
comando EOI: out 0x20, 0x20
 Indica que todos os IRQ ligados podem voltar a ser
atendidos
RotAtendimento:
sti
...
out 0x20, 0x20
iret
Arquitectura de Computadores (2008/2009): Entradas/Saídas 692
Interrupções na Porta Série 1
COM1: tem atribuído o IRQ4; identificação 12

PIC
IRQ0
INTR reg. Máscara IRQ1 UART
(controlador
0x21 IRQ2
INTA da porta
CPU IRQ3 série)
IRQ4
reg. Comando IRQ5 IER 0x3F9
IRQ6
0x20 IRQ7 MCR 0x3FC

Arquitectura de Computadores (2008/2009): Entradas/Saídas 693


Interrupções na Porta Série 1
Para a UART gerar interrupções é preciso:
 Colocar a 1 o bit 3 do registo MCR (Modem Control
Register) - 0x3FC

Depois é necessário indicar quando é que queremos


que sejam geradas:
 Para tal modificamos o registo IER (Interrupt Enable
Register) – 0x3F9:
Interrupção quando chega um carácter (RBR READY) 
colocar a 1 o bit 0
Interrupção quando o buffer de transmissão está vazio
(THR EMPTY), ou seja, o controlador está pronto a enviar
 colocar a 1 o bit 1

Arquitectura de Computadores (2008/2009): Entradas/Saídas 694


Operação por interrupções
Inicia-se vector de interrupções, PIC e UART
Quando existe uma transferência para fazer, o
controlador da porta série passa a indicar (por int.)
quando se pode fazer a leitura/escrita nos registos
de dados
É a rotina de tratamento da interrupção que escreve
(OUT) no porto de Dados THR ou lê (IN) do porto de
Dados RBR, a quando da interrupção
A rotina usa um buffer como origem ou destino do
próximo byte a enviar/recebido

Arquitectura de Computadores (2008/2009): Entradas/Saídas 695


Relembrar a transmissão com espera activa
Para enviar um byte pela porta série temos:
void send_serial (unsigned char b ) {
unsigned char s;

do {
s = // Conteúdo do registo de estado (LSR)
} while ( /* bit THR vazio de LSR == 0 */ );
// Escrever b para o registo de dados a enviar
}

Arquitectura de Computadores (2008/2009): Entradas/Saídas 696


Transmissão com interrupções

Interrupção 12
(IRQ4)
Envio de Inserir na
caracteres 1ª posição livre
Rotina de
pelo UART 1
tratamento A gerar
programa
buffer da interrupçõe
interrupção s quando
THR vazio
número 12
Remover o Byte
byte mais
antigo

Arquitectura de Computadores (2008/2009): Entradas/Saídas 697


Transmissão com interrupções
A a rotina send_serial send_serial(ch) {
envia o byte para um while (bufFull())
; // esperar
buffer
if (bufEmpty())
Se necessário espera em bufPut(ch);
ciclo que haja espaço no /* ligar interrupções
buffer (esta situação não
THR vazio */
deve ser comum)
else
Se o buffer está vazio, bufPut(ch);
deposita o carácter no }
buffer e liga as
interrupções na UART
Esta operação
desencadeia a leitura do
buffer para o periférico
Arquitectura de Computadores (2008/2009): Entradas/Saídas 698
Transmissão com interrupções
Vamos definir novas Rotina de tratamento de
constantes simbólicas: interrupções THR vazio {
// ler byte do buffer
#define PIC_COMMAND 0x20
// escrever byte para a porta
#define EOI 0x20
if (buffer vazio)
/* desligar interrupções para
A rotina de interrupções THR vazio */
desliga as interrupções // Enviar EOI para o PIC
da UART se o buffer }
ficar vazio

Arquitectura de Computadores (2008/2009): Entradas/Saídas 699