ultimo aggiornamento: 10 Luglio 2010
English version

Guida all'uso del debugger pdb

Come usare pdb, debugger in-circuit per microcontrollori PIC16



Introduzione
Debug monitor
Usare pdb
Scarica
Risorse in rete
Cronologia
Contatti

Introduzione

Programmando i microcontrollori può capitare che un circuito si comporti in modo imprevisto, di solito in relazione a stimoli esterni che non erano stati previsti. Anche se usando tutte le tecniche di simulazione si può risolvere il 99% dei problemi, rimangono delle rare situazioni in cui solo un debugger può rivelare cosa accade veramente.
I PIC sono dotati di un sistema di debug detto in-circuit, perchè il dispositivo rimane fisicamente nel cicuito pur consentendo all'utente di fermare il programma in esecuzione, farlo avanzare a passi, e modificare a piacimento le variabili interne del micro o le periferiche.
Il vantaggio rispetto a un emulatore classico è certamente il costo, visto che si usa il dispositivo stesso anzichè un circuito esterno; lo svantaggio è che vengono impegnate due linee di IO e un po' di memoria.
Lo sviluppo di questo debugger è basato sulla documentazione ufficiale della Microchip, in particolare del documento "On chip debugger specification" (DS51242A) relativo ai PIC16Fxxx.
Suppongo anche che il lettore abbia già costruito il programmatore Open Programmer, qui usato per far comunicare PC e PIC.

Debug monitor

Il debugger in-circuit funziona così:
quando il micro è configurato per il debugging, un evento di break, che può essere un fronte di discesa su RB6 o un hardware breakpoint, ferma l'esecuzione del programma e lo fa saltare all'indirizzo 0x2004; qui una istruzione "goto ICD" trasferisce il controllo a una funzione detta debugger monitor, che ha il compito di dialogare con l'host (cioè il computer dell'utente) ed eseguire quello che viene specificato.
Una serie di registri speciali, disponibili solo in questa modalità, permettono di controllare il comportamento delle periferiche e di impostare i breakpoint o l'esecuzione a passi.
Il debugger monitor è una funzione simile a un classico gestore di interrupt; deve salvare i registri di stato e ha quindi bisogno di risorse di memoria; ovvviamente si cerca sempre di farla più piccola posssibile.
Attualmente vengono richiesti 8 byte di memoria (da 0x6B a 0x72) e meno di 180 locazioni di memoria programma.
Per poter usare il debugger è necessario includere il codice di debug nel programma del micro; questo può essere fatto in due modi:
1) copiare il codice di debug nel codice principale, facendolo iniziare nella parte finale della memoria programma; solitamente si inserisce una direttiva ORG 0x1F00 (cioè 256 a byte dalla fine, per memorie di 0x2000 byte); le variabili di debug vanno invece nei registri 0x6B-0x72, e si specificano con cblock 0x6B ... endc.
2) usare il modulo precompilato debugger_mon.o e uno script per linker corrispondente; il modulo va aggiunto tra gli "Object files" del progetto MPLAB; lo script per linker è quello standard che si trova nella directory lkr di MPASM, a cui si deve aggiungere una pagina di codice per il debugger:
CODEPAGE   NAME=pageICD  START=0x1F00   END=0x1FFF	//! bisogna anche accorciare la pagina precedente
SECTION    NAME=ICD      ROM=pageICD     // ICD routine
Se alle strette con la memoria programma ci si può anche avvicinare alla fine (tenendo presente un minimo di circa 164 locazioni).
Per prevenire l'utilizzo delle variabili di debug (0x6B-0x72) sarebbe poi meglio accorciare le sezioni disponibili per il programma principale:
DATABANK   NAME=gpr0     START=0x20     END=0x6A
SHAREBANK  NAME=gprnobnk START=0x73     END=0x7F
... e così via per gli altri SHAREBANK.
Con altri ambienti di sviluppo le operazioni sono concettualmente simili.
Oltre a includere il codice bisogna:
abilitare il debugger tra le opzioni di configurazione (che verranno scritte nella config word);
abilitare la scrittura del salto al debugger ICD tra le opzioni di programmazione (e impostare correttamente l'indirizzo della routine ICD); non è necessario scriverlo ogni volta, in quanto la cancellazione normale non ne modifica il contenuto (si trova a 0x2004);
inserire una istruzione NOP all'indirizzo 0.
Tutta la procedura è illustrata nell'esempio che ho compilato.
Una volta scritto il file .hex bisogna collegare programmatore e circuito tramite i segnali ICSP (GND,VDDU,VPPU,SCK,SDA); VDD è necessaria solo se si vuole effettuare anche la programmazione in-circuit, ma di solito si stacca durante le sessioni di debug per non sovraccaricare il programmatore.
La comunicazione è sincrona col clock (RB6) e fatta in modo da utilizzare i comandi TX16 e RX16 del programmatore; vengono quindi trasferiti 16 bit alla volta.
L'elenco delle istruzioni è il seguente (per riferimento):
Comando Valore Parametri Risposta Note
NOP 0x00 0x00 no non fa nulla
VER 0x01 x 2B versione debugger
STEP 0x02 x no esegue un passo singolo
GO 0x03 x no continua l'esecuzione
RREG 0x04 N,A(2B) N*2B legge N registri a partire da A; il primo byte di ogni
risposta indica il numero di trasferimenti restanti
WREG 0x05 D,A(2B) no scrive D sul registro A

Usare pdb

pdb è il debugger che gira sul PC; è stato sviluppato prendendo come riferimento il ben noto gdb (che è ordini di grandezza più complesso) e ne riprende un po' la filosofia; è un programma da linea di comando (per linux e windows) con cui si può interagire per controllare un PIC direttamente sul circuito di applicazione.
È richiesta la presenza di un programmatore Open Programmer, per cui valgono le stesse considerazioni già esposte su come collegarlo.
Un esempio di utilizzo può essere di aiuto per comprenderne il funzionamento:
>pdb
pdb, an In Circuit Debugger for PIC microcontrollers
>
All'avvio viene attivata la VDD ma MCLR rimane basso e il PIC è sotto reset; non è necessario collegare VDD al circuito se questo ha già un'alimentazione.
Con il comando run MCLR va a 1 (H) e il micro esegue la prima istruzione (nop); un break manda in esecuzione il debugger che segnala la sua presenza al PC tramite RB7; pdb inizia a leggere informazioni circa lo stato di esecuzione e le riporta:
>run
running
execution stopped
Next instruction: goto  4 (0x2804)      PC=0x0001
STATUS=0x1F (            TO PD Z DC C)
W=0x28 PCLATH=0x00 FSR=0xBF
>
A questo punto si possono esaminare tutti i registri, ma anche modificarli a piacimento:
>print PORTB
0x006: PORTB = 0x36
>set PORTB 2
0x02 written to PORTB
>
Sono già inclusi i nomi dei registri hardware, ma si possono aggiungere i nomi delle variabili di programma:
>define var1 25
var1 (0x25) added to variable list
>print var1
0x025: var1 = 0x3F
>
Usando l'opzione -load all'avvio è possibile caricare un file con tutte le definizioni scritte nella forma:
variabile indirizzo
Una delle funzioni più usate è l'esecuzione passo passo:
>step
step
Next instruction: bcf   STATUS,5 (0x1283)       PC=0x0010
STATUS=0x1A (            TO PD   DC  )
W=0xF1 PCLATH=0x00 FSR=0xBF
>
Potrebbe essere utile esaminare qualche periferica o variabile automaticamente a ogni passo:
>display PORTC
variable PORTC (0x7) added to display list
>step
step
0x007: PORTC = 0x00
Next instruction: bcf   STATUS,6 (0x1303)       PC=0x0011
STATUS=0x1A (            TO PD   DC  )
W=0xF1 PCLATH=0x00 FSR=0xBF
>
Per continuare l'esecuzione:
>continue
running
/
Ora il programma gira libero ma lo si può fermare manualmente:
>halt
halted
0x007: PORTC = 0xFF
Next instruction: nop    (0x0000)       PC=0x0640
STATUS=0x1A (            TO PD   DC  )
W=0xFF PCLATH=0x00 FSR=0xBF
>
A volte serve che si fermi a un indirizzo particolare; si usa cioè un breakpoint:
>break 18
break at address 0x18
>continue
running
execution stopped
0x007: PORTC = 0xFF
Next instruction: xorlw 3 (0x3A03)      PC=0x0019
STATUS=0x1A (            TO PD   DC  )
W=0x4A PCLATH=0x00 FSR=0xBF
>
Queste sono le funzioni base del debugger; segue l'elenco completo dei comandi:
help                command help
break <addr>        set breakpoint at address <addr>
c[ontinue]          continue execution after halt
define <var> <a>    define variable named <var> at address <addr>
define rm <a>       remove definition for variable at address <addr>
define rm <var>     remove definition for variable named <var>
define rm all       remove all variable definitions
define list         list variables
display             if halted read variables in display list
display <var>       add variable named <var> to display list
display rm <a>      remove variable at address <addr> from the display list
display rm <var>    remove variable named <var> from the display list
display rm all      remove all variables from the display list
display list        list variables in display list
display {on off}    turn on-off auto display
freeze [on,off]     freeze peripherals
h[alt]              halt execution
list                display program code in the vicinity of current instruction
n[ext]              step over calls
print <addr>        print variable at address <addr>
print <var>         print variable <var>
print bank <b>      print registers in bank <b>
print p <addr>      print program memory at address <addr>
print ee <addr>     print eeprom memory at address <addr>
print ee            print all eeprom memory
q[uit]              quit program
r[un]               remove MCLR and run
set <a> <d>         write <d> at address <a>
set <var> <d>       write <d> to variable <var>
s[tep] [n]          single step [n times]
version             read version
Non escludo di cambiare in futuro i comandi o di aggiungerne altri seguendo le richieste degli utenti.
Dovrei anche aggiungere il supporto per i file .cof, in modo da poter usare direttamente i nomi delle variabili e delle funzioni presenti nel codice sorgente.
Il fatto che pdb sia un programma da linea di comando non preclude l'utilizzo con ambienti grafici (come d'altronde avviene con gdb); purtroppo MPLAB usa un protocollo proprietario che viene rivelato solo ai produttori di sistemi commerciali, quindi non può comandare direttamente pdb; un altro ambiente è Piklab, a cui spero di aggiungere presto il supporto per pdb.
Stesso discorso per quanto riguarda le altre famiglie di PIC (PIC18, PIC24, dsPIC): fino ad ora la Microchip non ha rilasciato alcuna informazione su come implementare un debugger, ma magari lo farà in futuro se riceverà abbastanza richieste in tal senso.

Scarica

debugger monitor
eseguibile pdb
sorgenti pdb

Risorse in rete

Open Programmer
Microchip.com
DevC++
licenze GNU/GPL

Contatti

Per informazioni o commenti:
Alberto Maccioni  email.png
Cosiglio anche di usare i forum su sourceforge.

Torna su

Pagina principale