Impostare la word di configurazione e il clock per i pic a 16bit (dsPic/Pic24)

Vediamo in questo articolo come impostare le word di configurazione per i dsPic33 e per i pic24F. Anche se vi interessa soltanto la configurazione dell’una o dell’altra tipologia di pic a 16 bit è bene che leggiate l’articolo per intero dal momento che le cose in comune (molte a dire il vero) le esporrò una volta sola. Non dimentichiamoci, difatti, che ciò che viene detto per i pic24  vale anche per i dsPic: i dsPic, difatti, non sono nien’altro che Pic24 con un core DSP, anche se alcune piccole cose possono variare a seconda delle funzioni specifiche sull’uno o l’altro modello di pic e deducibili dal datasheet relativo. Questa quindi è solo un’infarinatura di base per capire in che modo, con quali funzioni, si settano le word di configurazione per i pic a 16bit.

Configurazione dsPic33

Prenderò ad esempio i registri di configurazione del dsPIC33FJ128GP802. Andiamo quindi subito nel datasheet, come sempre alla voce “Special Features \ Configuration bits” e vediamo un po’ cosa abbiamo di fronte:

Vediamo che si tratta di parecchi registri ad 8 bit (forse gli unici!). Le impostazioni di configurazione per i dsPic, facendo uso del C30, vengono settate  utilizzando funzioni che hanno lo stesso nome del registro da impostare, preceduto da un underscore. Per impostare il registro FOSCSEL, ad esempio, basterà utilizzare la funzione :

_FOSCSEL(x);

nella quale la x verrà sostituita dal valore da assegnare al registro, o meglio: dai nomi mnemonici che è possibile trovare come sempre nel file header del pic interessato. Nel mio caso, dato che sto usando un dsPIC33FJ128GP802, il file header da cui prendere le informazioni  è p33FJ128GP802.h.

I file header dei pic a 16 bit si trovano di default nella cartella creata dall’installazione del C30:

C:\Programmi\Microchip\MPLAB C30\support\

gli header dei dsPic33 si troveranno quindi nella sottocartella:

\dsPIC33F\h

e quelli dei pic24F in:

\PIC24F\h

e così via per le altre famiglie. Non illustrerò la configurazione di tutti i registri ma solo di quelli principali, normalmente utilizzati per scopi didattici, gli altri possono essere lasciati ai valori di default. D’altronde la trattazione su tutte le funzionalità sarebbe un’impresa davvero ardua.

Registro di configurazione FOSCSEL

Viene utilizzato per selezionare la sorgente di clock del pic. Vediamo quali bit possiamo settare:

Bit IESO – Two-speed Oscillator Start-up Enable bit.  Possibili valori:

IESO_ON = Avvia il pic con l’oscillatore interno FRC (Fast RC) e in automatico passa all’oscillatore da noi selezionato una volta che questo è pronto.
IESO_OFF = Avvia il pic direttamente con l’oscillatore da noi selezionato.

Bits FNOSC – Initial Oscillator Source Selection bits. Serve a selezionare il tipo di oscillatore utilizzato dal momento che sui pic a 16 bit esistono varie sorgenti di clock che possono essere scambiate tra loro anche a runtime.  E’ possibile difatti  far funzionare il pic con:

  • oscillatore esterno primario (quarzo XT, quarzo HS o ancora: oscillatore esterno – EC) collegato ai pin OSC1 e OSC2
  • oscillatore esterno secondario. Pensato per un utilizzo a basso consumo e per un quarzo da 32768Hz da collegare ai pin SOSCI e SOSCO
  • oscillatore interno FRC (Fast RC) a 7.37MHz
  • oscillatore interno LPRC (Low Power RC) funzionante a 32768Hz

Possibili valori:

FNOSC_PRI = Oscillatore primario (XT, HS, EC)
FNOSC_PRIPLL = Oscillatore primario (XT, HS, EC) con PLL
FNOSC_SOSC
= Oscillatore secondario (LP – a bassa potenza)
FNOSC_FRC
= Oscillatore interno Fast RC
FNOSC_FRCPLL = Oscillatore interno Fast RC (FRC) con PLL
FNOSC_FRCDIV16
= Oscillatore interno Fast RC con divisione fissa per 16
FNOSC_LPRC
= Oscillatore interno LPRC
FNOSC_LPRCDIVN
= Oscillatore interno LPRC con divisione impostabile per N (vedremo dopo come)

Esempio di settaggio del registro FOSCSEL:

_FOSCSEL(IESO_OFF & FNOSC_PRIPLL); // avvio direttamente con oscillatore primario + PLL

Registro di configurazione FOSC

Serve ad impostare la modalità di funzionamento dell’oscillatore.

Bit FCKSM –  Clock Switching Mode bits

Il clock switching è una funzione che permette di cambiare la sorgente di clock anche con programma in esecuzione (possiamo passare dal clock primario a quello secondario ad esempio per ridurre i consumi o in caso di malfunzionamenti). In aggiunta, come anche su altri pic ad 8 bit, abbiamo anche il fail-safe clock monitor che è un sistema di monitoraggio di malfunzionamenti del clock primario. Possibili valori:

FCKSM_CSDCMD = funzione di clock switching disabilitata
FCKSM_CSECMD = abilitata solo la funzione di clock switching
FCKSM_CSECME = abilitate sia la funzione di clock switching che la funzione di fails safe clock monitor

Bit IOL1WAY – Single configuration for remappable I/O

Come abbiamo visto in un articolo precedente, è possibile rimappare su alcuni pin determinate periferiche (funzione PPS – Peripheral Pin Select). Esiste una funzione di sicurezza, aggiuntiva, che ci permette di eseguire una sola volta questa operazione (non una sola volta nella vita ma una sola volta per reset!), gestita appunto da tale bit. Possibili valori:

IOL1WAY_ON : è possibile eseguire una sola volta la funzione di remapping
IOL1WAY_OFF : è possibile eseguire più volte la funzione di remapping

In pratica, se tale bit è abilitato, permette un’unica scrittura, per reset, nei registri RPINRx and RPORx utilizzati per il pin remapping. Bisogna sempre e comunque effettuare lo sblocco come già spiegato.

bit OSCIOFNC – OSC2 Pin Function bit.  Tale impostazione non è applicabile se si utilizza l’oscillatore in modalità XT o HS in quanto il pin OSC2 è appunto occupato dal quarzo, torna utile nel caso di utilizzo di un oscillatore esterno. Possibili valori:

OSCIOFNC_ON : Il pin OSC2 può essere usato come normale I/O
OSCIOFNC_OFF : Il pin OSC2 è usato come uscita del clock

Bits POSCMD – Primary Oscillator Mode Select bits. Serve a selezionare il tipo di oscillatore primario. Possibili valori:

POSCMD_EC : modalità External Clock (oscillatore esterno sul pin OSC1)
POSCMD_XT : modalità con quarzo XT (quarzo da 3 a 10MHz)
POSCMD_HS : modalità con quarzo HS (quarzo da 10 a 40MHz)
POSCMD_NONE : oscillatore primario non usato

Esempio di settaggio del registro FOSC:

// FCKSM_CSDCMD : funzione clock switching disattivata
// IOL1WAY_OFF : è possibile effettuare più di una volta le funzioni di remapping
// OSCIOFNC_OFF : il pin OSC2 è utilizzato normalmente come uscita del clock
// POSCMD_XT : stiamo usando un quarzo con un valore da 3 a 10MHz
_FOSC(FCKSM_CSDCMD & IOL1WAY_OFF & OSCIOFNC_OFF & POSCMD_XT);

Registro di configurazione FWDT

Serve ad impostare il funzionamento del WatchDog Timer. Personalmente non utilizzo mai questa funzione per cui setto questo registro unicamente in questo modo:

_FWDT(FWDTEN_OFF); // Watchdog timer disattivato

Se vi serve usare il watchdog timer, sappiate che oltre a poterlo semplicemente attivare, ne potete settare anche altre caratteristiche. Controllate sempre il datasheet e il file header del pic utilizzato per controllare tutt i valori impostabili.

Altri registri di configurazione

I registri FBS, FSS e FGS servono a proteggere determinate locazioni di memoria, personalmente li lascio sempre non programmati, e quindi ai valori di default, in maniera che sia sempre tutto sprotetto. Alcuni di questi registri non sono disponibili su tutti i dspic.

Il registro FPOR serve ad impostare sia il tempo di poweron-reset che il “posizionamento” dei pin destinati all’I2C. Come abbiamo visto nell’articolo precedente, l’I2C non può essere rimappata ma ha un’assegnazione fissa. Agendo sul bit ALTI2C del registro FPOR, però, si può fare in modo che l’I2C sia mappato diversamente:

ALTI2C_ON:  I2C rimappata sui pin ASDA1/ASCL1
ALTI2C_OFF: I2C mappata sui pin SDA1/SCL1 (condizione di default)

Ovviamente, trattandosi di un’impostazione di configurazione, non può essere eseguita a runtime come invece è possibile fare per le altre periferiche gestibili tramite PPS.

Esempio di configurazione del registro FPOR:

// PowerOn Reset di 128mS + I2C rimappata sui pin ASDA1/ASCL1
_FPOR(FPWRT_PWR128 & ALTI2C_ON);

Il registro FICD serve ad abilitare il JTAG (uno standard nato per la comunicazione / programmazione / debug degli integrati, vedi su wikipedia per maggiori informazioni. Una lacuna, finalmente colmata, per la quale spesso la Microchip è stata “additata”) e per selezionare i pin di comunicazione con l’ ICD (In-Circuit Debugger – difatti l’ICD su questi dispositivi si può collegare su 3 diverse coppie di pin).

Configurazione PIC24F

Prenderò ad esempio il PIC24FJ64GB004 che è “quasi” pin-to-pin compatibile con il dsPic illustrato fin’ora. Nei PIC24 ai registri di configurazione non è stato dato un nome che riflette la funzione specifica del registro come nei dsPIC, ma sono stati chiamati semplicemente: CONFIG1, CONFIG2, CONFIG3, CONFIG4 (w l’originalità!)  o CWx (Configuration Word 1,2,3 e 4) probabilmente perchè ogni registro, come sui pic ad 8 bit, assolve a più funzioni.  I registri inoltre,  sono in minor numero rispetto ai dsPic perchè qui sono a 24bit. Anche in questo caso, col C30, i registri saranno configurati tramite funzioni aventi lo stesso nome dei registri, preceduti da un underscore:

_CONFIG1(x);

Andiamo quindi a controllarci sia il datasheet che il file header (p24FJ64GB002.h nel mio caso) . Vediamo che i nomi dei bit, e le funzioni, sono più o meno le stesse che vi ho già illustrato per i dsPic. In aggiunta, sul pic24 che ho citato, essendoci un modulo USB fullspeed, ci sono delle opzioni aggiuntive che permettono di avere un clock di 48MHz per il funzionamento del modulo USB sebbene il pic in questione non possa funzionare a più di 32MHz. C’è difatti in questo pic un secondo modulo PLL (PLL96MHz) che assolve a questa funzione.

Impostazione del Clock con PLL

Sui pic a 16 bit, il Clock, come abbiamo visto, è una di quelle cose che è possibile settare in mille modi diversi. In particolare l’utilizzo del PLL ci permette di moltiplicare la frequenza di clock fino a raggiungere valori davvero “spropositati” (fino ad 80MHz sui dsPic e fino a 32MHz sui pic24f) utilizzando quarzi di modesto valore e fornendoci, soprattutto, una notevole flessibilità nella scelta del quarzo da utilizzare per l’oscillatore primario.

Per settare correttamente il clock è necessario leggersi per bene sul datasheet la sezione relativa all’oscillatore (Oscillator Configuration), per cui qui fornirò solo delle istruzioni di base  facendo sempre riferimento al dsPIC33FJ128GP802. Abbiamo visto già , nella parte relativa al settaggio della word per l’oscillatore, come selezionare la sorgente di clock. Vediamo adesso come aumentare il clock proveniente dall’oscillatore primario.

Un pic a 16bit esegue già normalmente le istruzioni con una frequenza Fcy = Fosc/2  più alta rispetto ai pic ad 8 bit che operano ad una frequenza pari Fosc/4.   Con Fosc si intende la frequenza dell’oscillatore NON il solo quarzo ma tutto il sistema di oscillazione nel suo insieme (es.: quarzo + PLL).

A volte i simboli Fcy e Tcy vengono utilizzati in maniera equivalente sui datasheet creando confusione, quindi fate attenzione. Con Fcy si intende la frequenza operativa reale (Fosc/2), con Tcy il tempo di un ciclo di istruzioni (Tcy = 1/Fcy). Per cui: se Fosc vale 80MHz, Fcy=40MHz e quindi Tcy=25nS.

Per capire come funziona il PLL osserviamo lo schema concettuale presente sul datasheet:

Chiamiamo Fin la frequenza dell’oscillatore in ingresso al circuito del PLL (es.: la frequenza del solo quarzo se abbiamo deciso di utilizzare il quarzo). La frequenza Fin, prima di “andare in pasto” al PLL, dovrà essere divisa, tramite un prescaler, di un fattore N1 (variabile da 2 a 33).

Il fattore N1 viene impostato selezionando i 5 bit PLLPRE (PLL Prescaler) del registro CLKDIV (0b00000 = input/2, 0b00001 = input/3 … 0b11111 = input/33 – il valore di N1 vale in pratica il valore binario impostato + 2). Ricordiamoci che per utilizzare il PLL è necessario utilizzare un quarzo o un oscillatore tale che all’uscita del prescaler sia presente una frequenza compresa tra 0.8 e 8MHz, per cui nel caso si voglia utilizzare il PLL con un quarzo esterno è necessario selezionare un quarzo XT e non HS: questo è necessario affinchè vengano rispettate anche le condizioni imposte successivamente nella catena del PLL.

La frequenza in uscita dal PLL Prescaler andrà quindi in ingresso al VCO (Voltage Controlled Oscillator) del PLL. Il VCO ha un divisore di feedback, selezionabile tramite i 9 bit PLLDIV (unici bit del registro PLLFBD), che provvede a fornire un fattore M con il quale la frequenza in uscita al VCO viene moltiplicata. All’uscita del VCO dobbiamo avere una frequenza compresa tra 100 e 200MHz. Il valore di default di PLLDIV è 50, il suo valore può essere variato da 2 (0b000000000) a 513 (0b111111111 – anche qui basta impostare il valore binario e aggiungere 2 a tale valore per ottere M).

La frequenza in uscita al VCO viene quindi inviata in un postscaler che fornisce un secondo fattore di divisione N2, selezionabile tra i valori 2 (0b00), 4 (0b01 – valore di default) e 8 (0b11) impostando i due bit PLLPOST (del registro CLKDIV).

La frequenza in uscita dal PLL (Fosc) dovrà essere compresa tra 12.5 e 80MHz. Il calcolo del valore finale di Fosc si effettua con la formula:

Facciamo un esempio pratico che vale sempre più di mille parole. Supponiamo di utilizzare un quarzo esterno da 10MHz. Abbiamo quindi Fin=10MHz. Impostiamo (in C30) i seguenti valori per i fattori M, N1 e N2:

_PLLPRE=0x00; // N1=2
_PLLDIV=0x1E; // M=32
_PLLPOST=0x00; // N2=2

Avremo che all’ingresso del VCO ci saranno 10/N1 = 5MHz (rientriamo nel range 0.8 – 8). All’uscita del VCO : 5*32=160MHz (rientriamo nel range 100-200). Infine all’uscita del postscaler: 160/2 = 80MHz (rientriamo nel range 12.5 – 80).

Il nostro Fosc, quindi, utilizzando un quarzo da 10MHz e settando opportunamente il PLL, è di ben 80MHz fornendoci una ragguardevole velocità di elaborazione pari a 40MIPS (25 nanosecondi) !

Se avete letto la nota1 dell’immagine precedente, capite che sia la frequenza Fosc che tutti i valori vanno scelti in modo che i 3 range di frequenza in uscita dai vari blocchi siano tutti rispettati contemporaneamente.

Il registro OSCCON – Ancora impostazioni per l’oscillatore!

Il registro OSCCON permette ulteriori impostazioni dell’oscillatore:

I bits COSC sono di sola lettura e riflettono (una volta che il clock si è stabilizzato) l’impostazione dei bits FNOSC data nel registro di configurazione FOSCSEL. Indicano in pratica l’oscillatore attualmente in funzione.

Quindi, se si esegue il clock switch, una volta che questa operazione è conclusa,  tali bits rifletteranno il nuovo valore impostato.

E’ buona norma controllare tali bit prima dell’esecuzione del main, nel caso in cui , ad esempio, abbiamo scelto di far partire il pic prima con l’oscillatore FRC e quindi con l’oscillatore da noi selezionato (impostazione di configurazione IESO_ON in FOSCSEL):

while (OSCCONbits.COSC != 0b011); {continue;} // controllo che sia entrato in funzione l'oscillatore primario con PLL

I bits NOSC vanno impostati allo stesso, identico modo, dei bits FNOSC :

e servono per selezionare il “nuovo” oscillatore mediante la funzione di clock switching di cui abbiamo discusso prima. Quindi se vogliamo passare ad un altro oscillatore, dovremo impostare questi bits su un nuovo valore prima di effettuare il clock switch.

Il bit CLKLOCK funziona solo con il clock switch abilitato e il fail safe clock disabilitato (ovvero impostazione di configurazione FCKSM_CSECMD nel registro di configurazione FOSC) e serve ulteriormente per abilitare (0) o disabilitare (1) il clock switching.

Del bit IOLOCK ne abbiamo già discusso nell’articolo precedente: serve a bloccare (1) o sbloccare (0) la funzione PPS.  Il blocco/sblocco va eseguito tramite la sequenza in assembler che abbiamo già visto o tramite le builtin: non è possibile modificare questo bit direttamente.

Il bit LOCK, di sola lettura, indica se il PLL è “agganciato” (1) e quindi sta funzionando in maniera stabile o non è ancora in lock (0). Va controllato prima dell’esecuzione del main nei nostri programmi nel caso in cui stiamo utilizzando il PLL. Per cui è sempre bene porre un’istruzione del tipo:

while(OSCCONbits.LOCK!=1) {continue;} // controllo che il PLL sia agganciato

prima dell’esecuzione del main.

Il bit CF viene settato dall’hardware e va resettato via software: indica un malfunzionamento del clock principale rilevato dal FSCM (Fail Safe Clock Monitor).

Il bit LPOSCEN serve per abilitare (1) o disabilitare (0) il clock secondario a bassa potenza.

Il bit OSWEN serve per eseguire il clock switch (ponendolo a uno). Quando il clock switch è completo tale bit viene riportato a zero dall’hardware.

Il registro CLKDIV

Abbiamo già visto le funzioni “principali” di questo registro, ovvero l’impostazione del prescaler  (PLLPRE) e del postscaler (PLLPOST) del PLL. In tale registro ci sono altri bit “interessanti” che possono essere settati:

DOZEN : abilita (1) o disabilita (0) il rapporto tra la frequenza del processore e la frequenza usata dalle periferiche (si può difatti fare in modo che il processore operi a frequenza più bassa rispetto alle periferiche). Il valore di divisione di frequenza operativa del processore viene impostato tramite i bit DOZE nello stesso registro. Impostando DOZEN a 0 in pratica processore e periferiche lavoreranno con lo stesso clock. Questa caratteristica è stata introdotta per ridurre ulteriormente i consumi di corrente.

ROI : se posto ad 1, al verificarsi di un interrupt il bit DOZEN viene resettato (posto a zero) e quindi riporta il funzionamento del processore alla frequenza standard. Ponendolo a zero gli interrupt non hanno nessun effetto sul valore di DOZEN.

FRCDIV : questi 3 bits servono ad impostare il postscaler (divisore) per l’oscillatore interno FRC (000 = nessuna divisione, valore di default).

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)