I DSC (Digital Signal Controller) di Microchip sono dei controller single-chip che integrano le funzionalità di controllo di una MCU (MicroController Unit) con la potenza di elaborazione di un DSP (Digital Signal Processor). Microchip fornisce una suite completa di strumenti di sviluppo specifici per i dsPIC, sia software che hardware, altamente integrati in MPLAB IDE. L’ambiente di sviluppo MPLAB è costruito intorno all’IDE (Integrated Development Environment), e si tratta in pratica dello stesso ambiente utilizzato per sviluppare applicazioni per le MCU delle varie famiglie PIC, cui sono stati aggiunti dei tool specifici per i dsPIC ed i file di supporto relativi.
L’AMBIENTE DI SVILUPPO MPLAB
L’ambiente di sviluppo MPLAB è costruito intorno all’IDE (Integrated Development Environment) e comprende i tool necessari per la scrittura del codice, la gestione dei progetti, la compilazione, il debug e la programmazione dei dsPIC. Esamineremo ora i componenti principali dell’ambiente di sviluppo.
ASM30
Con MPLAB IDE viene fornito un Assembler gratuito per dsPIC denominato ASM30. Si tratta di un macro-assemblatore basato su software open-source GNU, del quale peraltro esistono molte altre versioni per le più diverse piattaforme. Si noti che tale Assembler non è compatibile con il vecchio MPASM utilizzato dai PIC, richiedendo uno sforzo ulteriore per un eventuale porting di applicazioni scritte per essi.
C30
L’uso di un linguaggio di alto livello come il C semplifica notevolmente il compito dello sviluppatore. Il compilatore C30 rende possibile la stesura di un codice più modulare, più facile da capire e da aggiornare, oltre ad aumentarne la portabilità. C30 è un compilatore ANSI C basato sul noto compilatore GCC (GNU C Compiler). Include una completa libreria ANSI C standard: questa rende disponibili funzioni per la manipolazione di stringhe, l’allocazione dinamica della memoria, funzioni matematiche trigonometriche, esponenziali ed iperboliche. In particolare, MPLAB C30 utilizza il formato IEEE-754 per i dati, un formato ottimizzato per la rappresentazione di tipi a 32 bit. C30 è un compilatore in grado di ottimizzare il codice prodotto. Il processo di ottimizzazione ha lo scopo di ridurre l’occupazione di memoria del codice e di aumentarne la velocità di esecuzione. Sono disponibili numerose opzioni a riguardo, alcune generiche, altre specifiche per il tipo di dispositivo –vale a dire un DSC. L’ottimizzazione può ad esempio eliminare il codice non raggiungibile, evitare la duplicazione di stringhe, ottimizzare i salti condizionati e non, o realizzare la cosiddetta astrazione procedurale. Quest’ultima consiste nello spostare porzioni di codice comuni a più parti del programma, in procedure che vengono eseguite con una chiamata. Il flusso dei dati durante il processo di compilazione è raffigurato nella figura 1.
MPLAB SIM30
MPLAB SIM30 è un potente debugger sourcelevel gratuito incluso con MPLAB IDE. Esso offre la possibilità di eseguire un debug del codice rapido ed economico senza la necessità di dover realizzare l’hardware sul quale dovrà effettivamente girare l’applicazione. MPLAB SIM30, oltre a simulare il set di istruzioni del dsPIC, è in grado di simulare anche le funzioni delle periferiche principali, tra cui I/O, i timer, i moduli A/D, l’UART. In particolare, la simulazione dell’UART può avvenire abilitando l’UART1 IO dalla finestra di dialogo Debugger >Settings: in tal modo l’input alla periferica sarà fornito tramite un semplice file di testo, e l’output potrà essere copiato su file o visualizzato nella finestra di Output, in corrispondenza della tab Sim UART1. Qualora si utilizzasse un compilatore C, basterà inserire nel codice una chiamata alla funzione printf() per visualizzare l’output dell’UART. MPLAB SIM30 offre la possibilità di simulare il comportamento dell’hardware generando stimoli esterni. Gli stimoli possono rappresentare sia variazioni di livelli di tensione sui pin di I/O che variazioni del contenuto degli SFR. In MPLAB SIM30 gli stimoli vengono gestiti tramite lo Stimulus Dialog. Si veda a tal proposito la descrizione di un esempio di utilizzo che verrà fatta nel paragrafo dedicato al debug dell’applicazione d’esempio. MPLAB SIM30 risulta ideale per lo sviluppo degli algoritmi, in particolare per testare operazioni matematiche e funzioni DSP. In questi casi, infatti, spesso testare il sistema nell’hardware reale può risultare problematico a causa della difficoltà nel ricreare un ambiente controllato, mentre fornire i dati di ingresso (eventualmente campionati da simulazioni reali) sotto forma di file di stimoli semplifica il test.
UN ESEMPIO DI APPLICAZIONE PER DSPIC
Vedremo ora un semplice esempio di applicazione in cui ci avvarremo di MPLAB IDE per la gestione del progetto e la compilazione, e di MPLAB SIM per il debug. Sebbene l’uso del linguaggio C sia comune nell’ambito delle applicazioni di DSP, utilizzeremo il linguaggio assembly/assembler perché questo ci permetterà di capire meglio il modello di programmazione dei dsPIC, ed inoltre evidenzierà alcune caratteristiche dei tool di debug. Il programma d’esempio è l’equivalente del classico Hello world nel campo dei microcontrollori: il dsPIC viene utilizzato per far lampeggiare un led indicato come LED1 se un pulsante SW1 viene premuto, altrimenti il led rimarrà spento. Inoltre, qualora si verificasse un errore software o hardware, accenderà il led LED2.
Creazione del progetto
Per semplificare i passi successivi, creiamo innanzitutto la directory C:\Microchip\Projects\dsPIC\dsPIC_LED nella quale andremo a copiare il file sorgente dsPIC_LED.s. Per la creazione del progetto ci avvarremo del Project Wizard. Una volta lanciato MPLAB IDE, dal menu dell’IDE selezioniamo Project>Project Wizard, quindi premiamo il pulsante Avanti sulla finestra di benvenuto che apparirà. Comparirà una finestra di dialogo in cui dovremo selezionare il dispositivo su cui girerà la nostra applicazione. Selezioniamo dsPIC30F6014 e premiamo Avanti. Nella successiva finestra di dialogo dovremo scegliere la toolsuite (assemblatore/compilatore, linker, ecc.) che verrà utilizzata per lo sviluppo del programma: nel nostro caso sceglieremo dall’elenco Active toolsuite la Microchip ASM30 toolsuite. Controlliamo nella casella di testo sottostante che i vari componenti della toolsuite siano stati individuati dall’IDE (non deve comparire una x accanto al nome di un componente). In caso contrario potremo cercare i componenti premendo il pulsante Browse e navigando nel file system: se abbiamo installato MPLAB IDE come suggerito durante l’installazione, la toolsuite dovrebbe trovarsi nella directory C:\Programmi\Microchip\MPLAB ASM30 Suite\bin. Si veda la figura 2.
Premiamo Avanti per continuare; ora dovremo assegnare un nome al progetto e scegliere la directory che conterrà i file dello stesso: scriviamo dsPIC_LED come nome del progetto e selezioniamo (tramite il pulsante Browse) C:\Microchip\Projects\dsPIC\dsPIC_LED come directory. Nella successiva finestra dovremo aggiungere al progetto i file sorgenti e di supporto. Ora, navigando nel file system nella casella di sinistra, selezioniamo la directory C:\Programmi\Microchip\MPLAB ASM30 Suite \Support\gld e selezioniamo il file p30F6014.gld (figura 3).
Clicchiamo su Add per aggiungerlo nella casella di destra. Il file .gld viene utilizzato dal linker per eseguire le operazioni di allocazione che sono state descritte nel paragrafo dedicato a LINK30. Infine, premiamo il pulsante Avanti e poi Fine per creare il progetto e terminare il wizard. Comparirà nell’ambiente di lavoro dell’IDE la finestra Workspace dalla quale potremo selezionare i file da modificare con l’editor.
Compilazione del progetto
Per compilare il progetto, selezioniamo Project>Make: si aprirà la finestra Output dove verranno visualizzate le informazioni relative al processo di compilazione. Se tutto andrà bene, l’ultima riga indicherà con BUILD SUCCEEDED che il processo è andato a buon fine. In caso di errori nel codice, sarà sufficiente cliccare sulla riga relativa nella finestra di Output per essere riportati alla riga di codice corrispondente. Nella finestra di Output, potremo visualizzare tra l’altro un utile report sull’occupazione della memoria del dsPIC da parte dell’applicazione. Per far ciò però è necessario, prima di compilare il progetto, selezionare dalla finestra di dialogo Project>Build Options>Project la scheda MPLAB LINK30, quindi selezionare dall’elenco categories la voce Diagnostics ed infine spuntare la checkbox accanto a Display memory usage. Notiamo anche che il file eseguibile risultante con estensione .cof viene convertito nel formato .hex dalla utility pic30-bin2hex.exe.
Debug dell’applicazione
Innanzitutto dal menu Debugger>Select tool clicchiamo su MPLAB SIM per indicare che lo utilizzeremo nella fase di debug. Per iniziare il debug del codice effettuiamo un reset dell’applicazione premendo F6, o in alternativa cliccando sul comando Debugger>Reset>Processor Reset. Notiamo che sulla barra di stato compare l’indicazione pc:0 che mostra che il program counter del dsPIC è stato azzerato. Diversamente da quanto ci aspetteremmo però, non compare la freccetta che indica nella finestra dell’editor la prossima istruzione che verrà eseguita. Questo perché l’istruzione che si trova nella locazione 0 è sempre una istruzione di salto all’entry point del programma che viene aggiunta automaticamente dal linker (utilizzando il famoso file .gld). Possiamo accertarci di ciò aprendo una finestra Program Memory, con View>Program Memory. Premendo ora F7, che corrisponde al comando Debugger>Step Into, potremo effettuare l’esecuzione passo passo del codice. Vediamo (figura 4) che nella finestra dell’editor la freccetta si è spostata accanto alla linea di codice con l’etichetta reset: è questo l’entry point del nostro programma.
Esistono altre modalità di esecuzione del codice:
Step Over, Step Out ed Animate. Step Over, selezionata con F8 o Debugger>Step Over, funziona come Step Into eccetto che se l’istruzione è una CALL esegue interamente la subroutine e poi ritorna, arrestandosi dopo la CALL. Step Out, selezionata con Debugger>Step Out, esegue interamente il resto della subroutine attualmente in esecuzione e si arresta dopo la CALL. Infine, Animate, selezionata con Debugger>Animate, è una serie di Step Into ripetute automaticamente a velocità ridotta. In ogni caso, si può interrompere l’esecuzione con F5, corrispondente a Debugger>Halt. Spesso è necessario interrompere l’esecuzione di un programma in punti determinati, in modo da poter esaminare i valori delle variabili o controllare il flusso di esecuzione del programma. Per far ciò si utilizzano i breakpoint, o punti di interruzione. Ad esempio, esaminando il codice, notiamo che esiste un loop identificato dall’etichetta Mainloop:
; Se il periodo e’ trascorso esce Mainloop: btss IFS0, #T1IF ; altrimenti rifa’ il loop bra Mainloop bclr IFS0, #T1IF
questo loop viene eseguito fintantoché il timer1 del dsPIC non avrà segnalato che è trascorso un certo intervallo di tempo (il flag T1IF verrà allora posto ad 1), dopodichè il flusso del programma riprenderà dall’istruzione bclr. È evidente che in tale caso risulta particolarmente scomodo eseguire il programma passo-passo a causa del numero elevato dei passi: settiamo allora un breakpoint alla linea contenente l’istruzione bclr facendo doppio click sulla linea stessa. Alternativamente possiamo, sempre ponendo il cursore in corrispondenza della linea dove vogliamo impostare il breakpoint, cliccare con il tasto destro del mouse e selezionare dal menu contestuale che apparirà, la voce Set Breakpoint. Effettuiamo un reset con F6 e facciamo quindi eseguire il programma a velocità normale con il comando Debugger>Run (o con F9): dopo un certo periodo di tempo, proporzionale al numero di istruzioni che il simulatore dovrà eseguire, l’esecuzione del programma si arresterà in corrispondenza del breakpoint (figura 5).
Con le versioni più recenti di MPLAB SIM è possibile anche imporre delle condizioni complesse di breakpoint, utilizzando il menu Debugger>Complex Breakpoints. Si tratta di breakpoint utili per intercettare delle occorrenze inusuali nel codice, dipendenti da un insieme di condizioni. Nello specifico, è possibile generare un breakpoint in funzione di:
- una lettura/scrittura di un registro SFR o GPR;
- lettura/scrittura di tabelle in program memory;
- caricamento di una data istruzione.
Inoltre si può utilizzare un pass counter per far scattare il breakpoint solo dopo un certo numero di occorrenze o di cicli istruzione. I breakpoint avanzati possono essere usati con una sequenza prestabilita (Sequenced Breakpoints) od in combinazione fra loro (ANDED Breakpoints). Per esaminare il contenuto delle variabili e degli SFR, possiamo utilizzare la finestra Watch, richiamabile da View>Watch. Potremo anche modificare il contenuto della memoria facendo doppio click nella casella della colonna Value. Selezioniamo ad esempio dall’elenco a sinistra l’SFR indicato come PORTD e clicchiamo su Add SFR per aggiungerlo all’elenco sottostante (figura 6).
Il contenuto dei bit 1:0 di questo registro corrisponderà ai livelli logici presenti sui pin dove sono collegati i LED del nostro…sistema virtuale! Effettuiamo un reset con F6 ed eseguiamo il run dell’applicazione con F9: notiamo che ogni volta che viene raggiunto il breakpoint che abbiamo impostato, il valore di PORTD cambierà commutando il bit 0 da 0 ad 1 e viceversa indicando che il LED1 lampeggia correttamente (il pulsante SW1 risulta premuto). Una caratteristica molto utile di MPLAB SIM è che possiamo controllare l’intervallo di tempo che intercorre tra due eventi utilizzando la fine stra Stopwatch. Apriamo lo Stopwatch con Debugger>Stopwatch: in essa vengono visualizzati i cicli d’istruzione eseguiti ed il tempo trascorso sia tra due eventi (Stopwatch) che dall’inizio della simulazione (Total simulated). Si può azzerare lo Stopwatch in un dato punto della simulazione premendo il tasto Zero. Le tempistiche sono calcolate a partire dal clock del dispositivo: per settarlo correttamente dobbiamo aprire la finestra di dialogo Simulator Settings da Debugger>Settings, quindi selezionando la linguetta Osc/Trace impostiamo il valore di 20 MHz per la frequenza di clock. Ora possiamo utilizzare lo Stopwatch con la nostra applicazione: effettuiamo un reset con F6, premiamo F7 finchè il cursore non si porta su Mainloop, premiamo il tasto Zero dello Stopwatch e quindi eseguiamo il programma con F9. L’esecuzione si arresterà in corrispondenza del breakpoint che avevamo impostato e lo Stopwatch mostrerà che l’intervallo di tempo trascorso è di circa 250 ms, corrispondente al periodo del timer1 così come impostato nel codice (figura 7).
Mediante il Trace Buffer possiamo visualizzare un elenco delle ultime istruzioni eseguite durante la simulazione. Il Trace Buffer può memorizzare un massimo di circa 65000 istruzioni; il buffer è circolare, perciò una volta riempito, le istruzioni più recenti sovrascrivono quelle più vecchie. Perché sia attivo è necessario controllare che nella finestra di dialogo Simulator Settings (Debugger>Settings), in corrispondenza della linguetta Osc/Trace sia spuntata la checkbox indicata da Trace All. Possiamo richiamare la finestra del Trace Buffer con View>Simulator Trace.
Stimulus Dialog
Come già accennato, MPLAB SIM30 offre la possibilità di simulare il comportamento dell’hardware generando stimoli esterni. Gli stimoli possono rappresentare sia variazioni di livelli di tensione sui pin di I/O che variazioni del contenuto degli SFR o dei GPR (General Purpose Register). Inoltre possono avvenire dopo un certo numero di cicli di clock o dopo un certo tempo, oppure quando è verificata una certa condizione, ad esempio, quando è raggiunta una data istruzione. Gli stimoli si distinguono fondamentalmente in:
- sincroni: una serie predefinita di variazioni sui pin di I/O o variazioni del contenuto degli SFR o dei GPR;
- asincroni: una serie analoga che si verifica però in un momento qualsiasi sotto controllo dell’utente.
In particolare, gli stimoli sincroni si distinguono in:
- pin/register actions: variazioni di I/O e dei registri che avvengono in tempi determinati;
- advanced pin/register: variazioni del tipo precedente che però possono avvenire in base a condizioni complesse, ad esempio in funzione del valore di altri registri;
- clock stimulus: serie di impulsi sui pin I/O, sincronizzati dal clock del dispositivo, che iniziano e terminano in corrispondenza di un dato numero di cicli o di un valore di un pin, o ancora al raggiungimento di una data istruzione;
- register injection: variazioni dei registri lette da file. Il trigger può essere on Demand, dipendente dal Program Counter, Message-based (per l’USART/UART).
A loro volta si distinguono due tipi di stimoli asincroni:
- regular: l’azione dello stimolo può essere tipo Pulse, High, Low, Toggle;
- message-based: l’azione dello stimolo è una serie di messaggi (packets) contenuti in file o immessi direttamente nella finestra di dialogo. Tali stimoli sono utilizzati per l’USART/UART.
Le opzioni relative alla creazione ed all’utilizzo degli stimoli sono molto numerose ed esulano dallo scopo di questo articolo. Si faccia riferimento all’help online di MPLAB SIM per una trattazione completa. Vediamo un esempio di creazione ed uso di uno stimolo asincrono. Apriamo la finestra Stimulus con Debugger>Stimulus> New Workbook. Genereremo uno stimolo asincrono che utilizzeremo per simulare la pressione del tasto SW1. Nella finestra Stimulus che abbiamo aperto selezioniamo la scheda Asynch, immettiamo quindi i valori delle colonne così come compaiono nella figura 8.
Ora rimuoviamo il breakpoint immesso in precedenza con un doppio click sulla linea relativa e settiamo un nuovo breakpoint in corrispondenza di per esempio:
; Testa SW1 TestSW1: btsc PORTA, #12 ; se non e’ premuto salta bra SwitchOff ; altrimenti LED1 lampeggia btg LATD, #0 ; e rifa’ il ciclo bra MainLoop ; Spegne LED1 SwitchOff: bset LATD, #0
Resettiamo con F6 ed eseguiamo con F9. L’esecuzione si arresterà in corrispondenza di TestSW1: in questo punto viene controllato il valore sul pin RA12. Se il valore logico è high (SW1 NON premuto) l’esecuzione salta all’etichetta SwitchOFF, altrimenti prosegue con l’istruzione successiva a quella di salto. Premiamo ora il tasto Fire in corrispondenza della riga RA12 della finestra Stimulus: poiché inizialmente il valore di RA12 è sempre low, dopo aver applicato lo stimolo diventerà high. Premendo ora F7 possiamo vedere che viene eseguita l’istruzione di salto a SwitchOFF. Se premiamo nuovamente F9 e successivamente applichiamo lo stimolo col tasto Fire, il valore di RA12 tornerà low (SW1 premuto), per cui il flusso del programma riprenderà dall’istruzione successiva a quella di salto.
Per approfondimenti su MPLAB vi consiglio questo link https://it.emcelettronica.com/?s=MPLAB