La gestione degli interrupt su MPC555

Come sono trattati gli interrupt e le eccezioni in ambito MPC555™? Questo articolo vuole fornire informazioni sulla gestione degli interrupt nell’architettura MPC555 e dare le necessarie indicazioni di carattere tecnico.

I due termini interrupt ed exception sono due aspetti della stessa medaglia; sono infatti eventi che interrompono il normale flusso di esecuzione di un programma. In realtà non sono termini del tutto equivalenti. Le eccezioni (exceptions) sono eventi, che possono essere definiti sincroni o asincroni e che cambiano il normale flusso di esecuzione di un programma, al pari di un’interruzione. Sono classificati come eccezioni gli eventi associati al reset o al decrementer, cioè un evento periodico asincrono utilizzato come timer di sistema, o le chiamate di sistema, system call. Sono presenti in questa famiglia anche vari errori di bus ed eventi utilizzati in fase di diagnostica del software o dell’hardware. In questo contesto, ad ogni occorrenza di un’eccezione, una piccola porzione, riferita al contesto hardware, è memorizzata in una particolare locazione e il processore  esegue una routine, di solito in assembly, residente in una zona fissa in memoria (vettore dell’eccezione) che è unica per ogni tipo di eccezione. Al contrario, un evento definito come interrupt è un altro tipo di eccezione. Un interrupt di solito è un evento associato ad un particolare pin di ingresso (per esempio il timer periodico) o riferito ad un dispositivo, come una periferica esterna. Nell’architettura del PowerPC™ tutti gli interrupt condividono uno stesso vettore delle eccezioni, chiamato external interrupt, posizionato alla locazione 0x500. Con il termine external interrupt ci si riferisce a tutti gli interrupt esterni al core della cpu, non interni al chip. L’integrato mpc555 dispone di numerose periferiche, quali timer, o pin di ingresso deputate alla generazione di interrupt. Infatti, programmando in maniera opportuna i registri di controllo del PowerPc è possibile generare e gestire degli eventi asincroni associati a diversi pin. La figura 1 mostra un diagramma a blocchi generale della parte degli interrupt, con  le varie relazioni, nell’ambiente MPC555.

Figura 1: overall MPC555 Interrupt System.

Figura 1:overall MPC555 Interrupt System.

Il componente permette la gestione fino a 16 livelli di priorità, l’abilitazione e disabilitazione in maniera selettiva delle sorgenti di interrupt, la gestione di un indirizzo ISR e la priorità degli interrupt, cioè permette di mettere in esecuzione la ISR associata alla più alta priorità. La figura 1 mostra al lettore la divisione in diverse macroaree. I riquadri 2, 3 e 4 mostrano le relazioni degli otto livelli di interrupt assegnato ai vari dispositivi interni; ogni pin IRQ è riservato per usi specifici, per esempio video card, mentre IRQ[0] è connesso al reset. Questi riquadri utilizzano una certo numero di registri interni. Il registro SIPEND, chiamato Interrupt pending register, contiene le informazioni sugli eventuali segnali di eventi pendenti e in attesa di essere serviti: otto sorgenti di interrupt interni ed altrettanti esterni.  Il registro è relazionabile con UIPEND localizzato nel modulo UIMB. I Bit 0-15 identificano le sorgenti di interrupt, mentre la parte 16-31 sono riservati. Gli interrupt esterni sono messi in evidenza su IRQ[0:7], quindi da I0 a I7, vedi figura 2.

Figura 2: SIPEND.

Figura 2: SIPEND.

Il SIMASK, Interrupt mask register, è composto di 16 bit dove ognuno identifica una sorgente di interrupt. Il SIMASK  permette l’abilitazione e la disabilitazione delle sorgenti in maniera selettiva, vedi figura 3.

Figura 3: SIMASK.

Figura 3: SIMASK.

Per ultimo, abbiamo il SIVEC, Interrupt vector code, che è un indice ad una tabella dei vettori a più alta priorità ed è utilizzato all’interno di una ISR. La figura 4 mostra una rappresentazione delle funzionalità del registro, mentre la tabella 2 pone in evidenza le relazioni tra priorità degli interrupt e i relativi codici.

Figura 4 :SIVEC

Figura 4 :SIVEC

 

Tabella 2 – Interrupt Priority & Codes

Tabella 2 – Interrupt Priority & Codes

La figura 5 mostra il flusso sulle varie relazioni esistenti.

Figura 5: MPC555 Exceptions and Interrupts

Figura 5: MPC555 Exceptions and Interrupts

Gestoe  interrupt esterni

Per gestire correttamente un interrupt all’interno dell’MPC555 è necessario seguire diverse operazioni. Per prima cosa occorre salvare  il contesto della macchina corrente, successivamente riabilitare gli interrupt, registrare i registri di livello utente, leggere  il codice del vettore, calcolare l’indirizzo della ISR associata e mettere in esecuzione la procedura software associata. Viceversa, al termine occorre rimettere a posto il contesto della macchina interrotta con i vari registri utente e restituire il controllo al programma interrotto. Di conseguenza occorre inizializzare il registro SIMASK, configurare la tabella ISR e fare il setup del livello dell’interrupt del dispositivo. Il primo passo per gestire un interrupt è quello di creare lo stack frame, salvare i registri r3, SRR0 e SRR1. Per memorizzare lo stato dei registri di sistema occorre utilizzare un registro di tipo GPR, per esempio r3; infatti, non è possibile intervenire direttamente sui registri SRR0:1. I bit EE (interrupt disabled) e RI (execution not recoverable) del registro MSR devono essere disabilitati. Queste operazioni sono fatte ricorrendo alla seguente porzione di codice:

; passo 1: save “machine context”
stwu sp, -40 (sp)
stw r3, 24 (sp)
mfsrr0 r3
stw r3, 12 (sp)
mfsrr1 r3
stw r3, 16 (sp)

Successivamente occorre inizializzare  il bit EE e R del registro MSR. Con EIE si interviene su MSR[EE] e MSR[RI], EID su MSR[RI]. Tutti questi bit devono essere messi a uno.

; passo 2:
; interrupt esterno
mtspr EIE, r3

I registri  LR e CR devono essere preservati. Il  registro LR sarà modificato alla chiamata della ISR, questa, poi, modificherà il registro CR con le operazioni di salto. Siccome i  registri LR e CR non possono essere modificati direttamente, allora si deve utilizzare  il registro r3.

; passo 3: registra tutti gli altri
appropriati contesti
mflr r3
stw r3, 8 (sp)
mfcr r3
stw r3, 20 (sp)

Ora, si deve fare lo stesso per altri registri. Si assume che una ISR utilizza solo i registri r3-r6 e si deve considerare maggiore carico di lavoro se la ISR è scritta in C.

stw r4, 28 (sp)
stw r5, 32 (sp)
stw r6, 36 (sp)

Si carica il valore di 8 bit da SIVEC a r3. Il registro SIVEC si trova alla locazione esadecimale 2FC01C

; passo 4: si determina la sorgente
dell’interrupt:
lis r3, SIVEC@ha
lbz r3, SIVEC@l (r3)

Ora ci si deve predisporre per un salto con una jump table. A questo scopo si utilizza lis e ori per caricare una tabella IRQ e aggiungere un offset per ottenere così l’indirizzo della ISR. Al termine occorre mettere l’indirizzo dell’istruzione di salto in LR:

lis r4, IRQ_table@h
ori r4, r4, IRQ_table@l
add r4, r3, r4
mtlr r4

Con l’istruzione blrl si effettua  il salto all’indirizzo posizionato in LR e registra  il valore PC+4 in LR. In pratica, è come utilizzare un puntatore a funzioni all’indirizzo b kth_isr_addr

; passo 5: Salta al gestore dell’interrupt
blrl

“ripara” i registri r4, r5, r6, con i valori in precedenza posti sullo stack.

; passo 6: Rimetti a posto il
contesto
lwz r4, 28 (sp)
lwz r5, 32 (sp)
lwz r6, 36 (sp)

Riposiziona   i valori di CR e LR. Il  registro gpr (r3) è di nuovo utilizzato come una variabile temporanea perché i registri  CR e LR ( e ogni altro registro SPR) non possono essere caricati direttamente.

lwz r3, 8 (sp)
mtcrf 0xff, r3
lwz r3, 20 (sp)
mtlr r3

azzera MSR[RI] e MSR[EE]. È un passaggio non interrompibile.

;passo 6: Rimetti a posto il contesto
mtspr NRI, r3
lwz r3, 12 (sp)

Rimetti i valori originali di SRR0, SRR1 e r3. Il registro r3 è, anche in questo caso, un registro di lavoro temporaneo utile per trattare SRR0 e SRR1. Si nota che r3 è il primo registro ad essere salvato e l’ultimo ad essere recuperato.

mtsrr0 r3
lwz r3, 16 (sp)
mtsrr1 r3
lwz r3, 24 (sp)
addi sp, sp, 40

questa operazione è svolta utilizzando rfi (return from interrupt). Rimetti a posto i bit MSR salvati in SRR1 e il valore del PC memorizzato in SRR0.

; passo 7: Ritorniamo alle attività
precedenti
rfi ; End of Interrupt

La tabella 1 mette in evidenza una possibile checklist sull’uso dei registri.

Tabella 1 - Checklist

Tabella 1 - Checklist

Gestore  interrupt interni

La porzione 1 della figura 1 mostra le varie sorgenti degli interrupt interni. Per esempio, con TPU3 si identifica il Time Processor Units, la terza versione. È un modulo molto versatile e potente che permette di costruire funzioni trattate come microcodice all’interno dell’architettura del PowerPc. È presente il MIOS1, un sistema di I/O modulare, o il  QADC64 che svolge la funzione di convertitore analogico digitale. È presente, poi, TouCAN (Control Area Network), un modulo a due linee fino ad una velocità di 1Mbps: questo modulo permette di mettere a punto una rete all’interno di un veicolo. Per finire troviamo il QSMCM (  Queued Serial Multi-channel Module) e il bus IMB3 bus, Inter-Module Bus. Una sorgente di interrupt è qualsiasi dispositivo che può generare un evento. A riguardo del componente MPC555, i dispositivi  che possono essere classificati come sorgenti di interrupt sono i pin di ingresso IRQ[0:7], i timer interni, il  PLL e le periferiche descritte sopra (IMB3). Solo i  timer inter ni time base (TBL), il  programmable interrupt timer (PIT) e il real-time  clock (RTC) sono sorgenti di interrupt. Un livello di interrupt è un numero assegnato dal software ad ogni sorgente di interrupt a parte i pin di ingresso IRQ[0:7]. Questo numero fornisce al software un meccanismo per identificare la ragione specifica che ha causato l’evento. Il livello implica anche una priorità in merito alla loro gestione qualora due interrupt sono riconosciuti nello stesso momento dal controllore hardware. Gli unici ad avere una priorità fissa sono gli interrupt pin. La tabella 2 mostra la priorità degli interrupt. La porzione 2 della figura 1 identifica l’interfaccia “U-bus to IMB”, o UIMB, ed è composta dai moduli funzionali UIM, U-bus verso l’interfaccia IMB, il registro UIPEND (Interrupt pending register) e U-bus (Unified bus) che connette multipli bus interni. Tutti gli interrupt delle periferiche su IMB sono trasmessi verso il  modulo UIMB. Questo modulo contiene un interrupt controller con la presenza del registro UMCR[IRQUX]. L’interfaccia converte 32 livelli di interrupt sul bus IMB3 verso 8 livelli di interrupt su U-Bus, in questo modo: livelli 06 a U-Bus livelli 0-6, livelli 7-31 a U-bus livello 7. Il gestore degli interrupt può leggere il registro UIPEND attraverso  il meccanismo di tipo memory-mapped. Il modulo USIU si occupa del controllo del start-up del sistema, oltre a svolgere le attività di inizializzazione e sovrintendere alle operazioni che deve svolgere nor-malmente la CPU. Inoltre, si occupa della protezione del sistema e della gestione del bus di sistema esterno. Il blocco funzionale USIU ha 16 ingressi: otto interrupt esterni su interrupt pin e altrettanti su livelli di interrupt interni. Le sorgenti di interrupt all’interno del modulo USIU (time base, real-time clock, periodic interrupt timer, PLL, watchdog software e decrementer) sono mappati sui livelli 0:7, mentre le sorgenti di interrupt delle periferiche verso 0:31.

Powerpc  core

Il ruolo del core è messo in evidenza dal riquadro 5 in figura 1. Dalla figura è possibile mettere in evidenza che il modulo PowerPc core ha solo una singola sorgente di interrupt che proviene dall’interrupt controller. Gli interrupt sono abilitati intervenendo sul bit EE del registro MSR (machine state register). Il  bit EE abilita anche l’eccezione del decrementer. Dal riquadro 5 della figura 1 si può anche notare che al processor core arrivano tre linee di interrupt: IREQ, NMI (Non-maskable interrupt) e decrementer. Ad ogni occorrenza di un interrupt, l’hardware del microprocessore deve aspettare la conclusione della corrente istruzione, memorizzare  il PC nel registro SRR0, fare il backup di MSR[EE] verso il registro SRR1 e azzerare subito dopo MSR[EE e, per finire, trasferire  il controllo alla locazione n+0x100, n+0x500 o n+0x900 in base alla sorgente di interrupt. Tutto il resto è in carico al software.

Esempio: interrupt del timer  periodico

Il  timer periodico è un contatore di 16 bit e conta all’indietro fino ad arrivare a zero. Ad ogni occorrenza del valore zero è sollevato un interrupt. Il timer è pilotato da un clock interno, un oscillatore con valore di solito pari a 4MHz, diviso per 4, di conseguenza la frequenza è pari a 1 MHz. Per gestire correttamente  il PIT sono disponibili tre registri. Il PICSR (Periodic Interrupt Control & Select Register) permette di definire e inizializzare correttamente il livello  di interrupt del PIT e dispone di una serie di bit che permettono la gestione dell’evento, quali il PIT Freeze, PIT Status, PIT Enable e il PIE (PInterrupt Enable). La figura 7 mostra uno schema del registro.

Figura 7: PICSR Periodic Interrupt Control & Select Register.

Figura 7: PICSR Periodic Interrupt Control & Select Register.

Il PIT counter è un registro a 16 bit utilizzato per impostare il periodo del timer secondo la relazione (PITC+1)/(PIT Frequency)  con 1MHZ di oscillatore, con un valore pari a 33000 si ottiene un interrupt ogni 33ms. Il  PITR (Periodic Interrupt Timer Register) può essere utilizzato per quantificare  il valore dell’evento. La figura 6 mostra il diagramma  a blocchi del PIT.

Figura 6: PIT Block Diagram

Figura 6: PIT Block Diagram

Il listato 1 pone in evidenza la sua inizializzazione.

.equ USIU_BASE_UPPER 0x2f
.equ PICSR_OFFSET 0xc240
.equ PITC_OFFSET 0xc244
.equ PITR_OFFSET 0xc248

; r4 base address of SIU regs
        lis r4, USIU_BASE_UPPER

; set PISCR bits: PIRQ=08, PS=PS, PIE=1, PITF=0, PTE=0
; so flag is cleared, interrupt is enabled, timer is
; enabled, and level is assigned
        li r0,0x0804
        sth r0,PICSR_OFFSET(r4)

;PITC = 33000 = 0x80e8 and store it in PITC
        li r5, 0x80e8
        sth r5, PITC_OFFSET(r4)

;now enable PIT: PTE = 1
        lhz r0, PICSR_OFFET(r4)
        ori r0, r0, 0x1
        sth r0, PICSR_OFFSET(r4)
Listato 1 – PIT Initialization

Scrivi un commento

EOS-Academy
Abbonati ora!