PIC24/dsPic : Bootloader e Interrupts

  • Gianni
  • Autore della discussione
  • Elit Utente
  • Elit Utente
Di più
13 Anni 7 Mesi fa #1 da Gianni
PIC24/dsPic : Bootloader e Interrupts è stato creato da Gianni
Dopo essere riuscito a implementare un bootloader su usb hid per pic24 (grazie alla microchip ovviamente!), mi ritrovo ora a voler capire come gestire gli interrupt in presenza di un bootloader. Sono andato nel pallone perchè in qualsiasi main della MAL, riguardo al C30 si trova questa nota:
Code:
/* * ISR JUMP TABLE * * It is necessary to define jump table as a function because C30 will * not store 24-bit wide values in program memory as variables.

Ok.. qui dice che è necessario definire una tabella di salti... ma il motivo non arrivo ad afferrarlo: non salva valori a 24 bit in memoria programma come variabili...beh è ovvio... in memoria programma puoi mettere costanti non variabili.... non capisco a cosa fa riferimento...

poi:
Code:
* * This function should be stored at an address where the goto instructions * line up with the remapped vectors from the bootloader's linker script. * * For more information about how to remap the interrupt vectors, * please refer to AN1157. An example is provided below for the T2 * interrupt with a bootloader ending at address 0x1400 */ // void __attribute__ ((address(0x1404))) ISRTable(){ // // //asm("reset"); //reset instruction to prevent runaway code // //asm("goto %0"::"i"(&_T2Interrupt)); //T2Interrupt's address // }


Ho letto l'application note a cui si fa riferimento... ma in realtà non dice nulla che faccia capire il senso di queste operazioni (diciamo che probabilmente sono io che mi sto "fossilizzando".. nel senso che giro intorno ad un argomento mentre di sicuro lo spiraglio di luce sta da un'altra parte) .

Aiutatemi a capire: queste istruzioni in pratica servono a dichiarare una funzione ISRTable che verrà posizionata alla locazione 0x1404 (poco sotto la fine del bootloader). Ricapitolando le locazioni di memoria utilizzate:

sui pic24 i vettori di interrupt finiscono alla locazione 0x01FE, per cui la prima locazione "utile" per il programma è la 0x0200.

Il bootloader parte da 0x0400 (hanno lasciato libero uno spazio tra 0x200 e 0x3FE, ma ignoro il motivo... forse per poterla eventualmente sfruttare come memoria eeprom dato che i pic24 non hanno l'eeprom dati?) e il programma inizia in 0x1400 (nelle note sembra che dica che la locazione 0x1400 sia ancora usata dal bootloader ma in realtà nel sorgente del bootloader si capisce chiaramente che in 0x1400 inizia il programma dato che se non viene richiamato il bootloader c'è un goto 0x1400).

Questa funzione ISRTable di esempio viene posizionata in 0x1404... ma poi non ne capisco il senso: il reset a cosa serve e il goto "goto %0"::"i"(&_T2Interrupt) dove va a puntare? (ok al vettore di interrupt del timer2) ma... Quando si verifica un interrupt... non è mica la ISRTable ad essere richiamata... ?!

Sono tutti bravi ad essere "open" con il "source" degli altri.
Un amico è colui che ti dice sempre quando stai sbagliando. Il mio miglior amico è il parser.
SettoreZero

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Mauro Laurenti
  • Moderatore
  • Moderatore
Di più
13 Anni 6 Mesi fa - 13 Anni 6 Mesi fa #2 da Mauro Laurenti
Risposta da Mauro Laurenti al topic Re: PIC24/dsPic : Bootloader e Interrupts
Ciao Gianni,

non ho molta esperienza con i PIC24 in ambito Bootloader. Mi aspetterei qualcosa simileai PIC18.
In ogni modo ho allegato un secondo modo per inserire l'offset per mezzo dell'IDE MPLAB.
E' stao utilizzato per PIC18 ma dovrebbe fuznionare anche per gli altri PIC.

Il documento e' stato scritto dall'utente gcupini.

Saluti,

Mauro
Allegati:
Ultima Modifica 13 Anni 6 Mesi fa da Mauro Laurenti.

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Gianni
  • Autore della discussione
  • Elit Utente
  • Elit Utente
Di più
13 Anni 6 Mesi fa #3 da Gianni
Risposta da Gianni al topic Re: PIC24/dsPic : Bootloader e Interrupts
Ho letto il documento, può tornare sicuramente utile ma non fa al caso mio.
Con i pic dalla serie18 in su è tutto più facile perchè basta selezionare il linker modificato per fare in modo che il programma parta da una determinata locazione alla quale punta il bootloader, e lo trovo più comodo. Pure per i pic24 utilizzo il linker modificato quando devo compilare per bootloader, oppure semplicemente non metto nessun linker se devo compilare senza bootloader e quindi mplab si carica da sè il linker di default in base al pic selezionato per il progetto.


Nee approfitto per approfondire la questione per i pic a 16 bit, magari può essere argomento di discussione.

Sui pic serie 18 abbiamo imparato che ci sono due vettori di interrupt: alta e bassa priorità. Ad ogni tipo di interrupt possiamo assegnargli una priorità per fare in modo che "cada" nell'uno o nell'altro vettore.

Sui pic24/dspic questo meccanismo non esiste o meglio è stato reso molto piu versatile: ogni tipo di interrupt ha il suo esclusivo vettore di interrupt. Non abbiamo piu, quindi, dei vettori di interrupt assegnati in base ad una priorità ma dei vettori di interrupt associati proprio allo specifico interrupt. Questo consente, a mio avviso, anche una scrittura di codice forse piu pulita: ci sarà una ISR per ogni interrupt.
Ad ogni tipo di interrupt, in aggiunta, possiamo assegnare un livello di priorità, che verrà usato nel caso in cui si verificano due interrupt insieme ma anche per mascherare un interrupt. Ma i vettori, ricordo ancora una volta, sono assegnati all'interrupt e non alla priorità. La priorità diviene quindi un attributo dell'interrupt.

Questa cosa porta ad avere la cosiddetta "interrupt vector table": una tabella nella quale sono elencati tutti i vettori di interrupt, per ogni interrupt.
Ogni "riga" della tabella occupa una word, ovvero 16bit.
Alla locazione 0 sappiamo che c'è il reset vector. Nei pic a 16 bit nel reset vector c'è un'istruzione GOTO, e nella locazione immediatamente successiva (che sarà la 0x02 => stiamo ragionando a 16 bit) c'è memorizzato l'indirizzo al quale l'istruzione GOTO deve puntare. Dalla locazione 0x04 in poi (la successiva), parte la tabella dei vettori di interrupt (ci sono le "trappole", la tabella interrupt e la tabella interrupt alternativa, ma non soffermiamoci su questo di cui ne ho ampiamente parlato in questo articolo: www.settorezero.com/wordpress/la-gestion...6-pic18-pic24-dspic/ ).

La tabella degli interrupt finisce alla locazione 0x01FE e quindi il programma che noi andiamo a scrivere partirà dalla locazione 0x0200.

E' ragionevole pensare che in condizioni "normali", l'istruzione GOTO posta nel reset vector punti appunto alla locazione 0x0200.

E' ragionevole inoltre pensare che, dato che i vettori di interrupt sono separati tra loro di una sola word, non c'è spazio per la scrittura dell'ISR, quindi nel vettore di interrupt ci sarà sempre un'istruzione GOTO che poi punta alla ISR, spero che questo mio ragionamento sia corretto.

Ora:

Il bootloader usato dalla microchip parte dalla locazione 0x0400, non so dove termina ma so che il programma va poi salvato a partire dalla locazione 0x1400.

Non ho idea del perchè non abbiano fatto partire il bootloader direttamente in 0x0200 ma suppongo che sia stato lasciato dello spazio libero in maniera tale da poterlo utilizzare come emulazione eeprom dal momento che i pic24F e i dsPIC non hanno la memoria eeprom e la microchip ha fatto una libreria per sfruttare la memoria programma come eeprom (ricordo che tale libreria è disponibile pure per i pic18 e usa una tecnica molto interessante).

Adesso... le note poste nell'esempio fanno questo:
Code:
void __attribute__ ((address(0x1404))) ISRTable(){

ovvero, tradotto in italiano: viene dichiarata una funzione dal nome ISRTable e viene posta nella locazione 0x1404.... cioè 2 word sotto a dove inizia il programma ?!
E poi nella funzione c'è una chiamata assembler ad un reset e quindi una sintassi che non so interpretare ma che penso punti all'interrupt vector del timer2 preso come esempio.

Le domande quindi sono molteplici:

- perchè rimappare gli interrupt se gli interrupt vector punteranno già a locazioni di memoria scelte dal compilatore in base al programma? Allora vuol dire che non è cosi che funzionano gli interrupt e ho detto una baggianata

- perchè dichiarare una funzione, allocata poi in 0x1404, cha fa qualcosa che non si arriva a capire?

vado a mettermi un po di ghiaccio in testa

Sono tutti bravi ad essere "open" con il "source" degli altri.
Un amico è colui che ti dice sempre quando stai sbagliando. Il mio miglior amico è il parser.
SettoreZero

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Mauro Laurenti
  • Moderatore
  • Moderatore
Di più
13 Anni 6 Mesi fa #4 da Mauro Laurenti
Risposta da Mauro Laurenti al topic Re: PIC24/dsPic : Bootloader e Interrupts
Ciao Gianni,

Come hai messo in evidenza tu il fatto di avere piu’ vettori delle interruzioni permette di essere piu’ flessibili.
In particolare in applicazioni real time dove potrebbe essere richiesta una piccola latenza prima dell’esecuzione del codice, l’avere vettori dedicati permette di risparmiare il tempo di ricerca della periferica che ha generato l’interruzione.
In applicazioni a batteria questo risparmio di codice si traduce anche in un risparmio di energia.

L’avere vettori distanziati di due byte e’ pensato per posizionare il solo GOTO.
Questa tecnica e’ usata quasi sempre sui microcontrollori e PC.

Relativamente alla domanda sulla necessita’ di mettere il goto ad un’altra tabella dove e’ presente il secondo goto e’ legato alla flessibilita’.
Se infatti hai il bootloader posto all’inizio probabilemente vorrai proteggere quell settore di memoria da scritture accidentali.
Frequentemente questo significa bloccare anche i vettori delle interruzioni.
Dato che il bootloader serve per aggiornare il firmware, se la tabella dei vettori delleinterruzioni venisse bloccata non la si potrebbe piu’ aggiornare.
Se un aggiornamento del firmare causasse (cosa probabile) uno spastamento delle funzioni ISR la tabella non protrebbe essere aggiornata.
Spostando il tutto su una seconda tabella si bypassa il problema.
Questa problematica e’ piu’ o meno sentita a seconda delle modalita’ di protezione della memoria che sono implementate nel microcontrollore.
Per i PIC a 16 bit (dsPIC inclusi) si hanno diverse implentazioni di protezione della memoria.

Saluti,

Mauro

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Gianni
  • Autore della discussione
  • Elit Utente
  • Elit Utente
Di più
13 Anni 6 Mesi fa #5 da Gianni
Risposta da Gianni al topic Re: PIC24/dsPic : Bootloader e Interrupts
Ho trovato questa discussione interessante:

www.microchip.com/forums/m482560-print.aspx

anche se ci ho capito ben poco, dicono che il problema non sussiste se si utilizza il linker per bootloader fornito con l'ultima versione della MAL.

Per fare un esempio, cosi inizia il linker standard del mio pic24F:
Code:
MEMORY { data (a!xr) : ORIGIN = 0x800, LENGTH = 0x1FFF reset : ORIGIN = 0x0, LENGTH = 0x4 ivt : ORIGIN = 0x4, LENGTH = 0xFC aivt : ORIGIN = 0x104, LENGTH = 0xFC program (xr) : ORIGIN = 0x200, LENGTH = 0xA9F8 CONFIG4 : ORIGIN = 0xABF8, LENGTH = 0x2 CONFIG3 : ORIGIN = 0xABFA, LENGTH = 0x2 CONFIG2 : ORIGIN = 0xABFC, LENGTH = 0x2 CONFIG1 : ORIGIN = 0xABFE, LENGTH = 0x2 }

e questa invece è la stessa parte ma relativa al linker da usare per applicazioni che devono sfruttare il bootloader:
Code:
MEMORY { data (a!xr) : ORIGIN = 0x800, LENGTH = 0x1FFF reset : ORIGIN = 0x0, LENGTH = 0x4 ivt : ORIGIN = 0x4, LENGTH = 0xFC aivt : ORIGIN = 0x104, LENGTH = 0xFC app_ivt : ORIGIN = 0x1400, LENGTH = 0xC0 program (xr) : ORIGIN = 0x14C0, LENGTH = 0x96E8 CONFIG4 : ORIGIN = 0xABF8, LENGTH = 0x2 CONFIG3 : ORIGIN = 0xABFA, LENGTH = 0x2 CONFIG2 : ORIGIN = 0xABFC, LENGTH = 0x2 CONFIG1 : ORIGIN = 0xABFE, LENGTH = 0x2 }

vediamo che l'IVT e l'AIVT iniziano sempre nello stesso punto, cambia il punto in cui inizia il programma. La cosa si infittisce sempre di piu perchè viene dichiarato uno "spazio" aggiuntivo chiamato "app_ivt" il cui nome è facile capire cosa significa, posizionato in 0x1400 ma di lunghezza inferiore all'IVT standard.... e quindi il programma comincia piu sotto.. In aggiunta il linker del bootloader ha una lunga parte in piu in cui pare che i vettori di interrupt vengono riposizionati, esempio:
Code:
SHORT(DEFINED(__T2Interrupt) ? ABSOLUTE(__T2Interrupt) : ABSOLUTE(__DefaultInterrupt)); SHORT(0x04); SHORT(DEFINED(__T2Interrupt) ? (ABSOLUTE(__T2Interrupt) >> 16) & 0x7F : (ABSOLUTE(__DefaultInterrupt) >> 16) & 0x7F); SHORT(0);

ma la cosa strana è che quei "numeri" sono uguali per tutti i vettori di interrupt...

Sono tutti bravi ad essere "open" con il "source" degli altri.
Un amico è colui che ti dice sempre quando stai sbagliando. Il mio miglior amico è il parser.
SettoreZero

Si prega Accesso o Crea un account a partecipare alla conversazione.

Moderatori: Mauro LaurentiMatteo Garia

Registrati al sito

Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.

Registrati al sito LaurTec.