Le periferiche dei PIC24

Un viaggio all’interno del PIC 24 con l’analisi delle periferiche ed in particolare dei moduli RTCC (RealTime Clock & Calendar), PMP (Parallel Master Port) e CRC (Cyclic Redundancy Check).

I microcontrollori a 16 bit PIC24 di Microchip possiedono un’architettura innovativa ed un ricco insieme di periferiche. Nell’articolo, dopo una breve introduzione sull’architettura, vedremo la dotazione di periferiche di questi dispositivi, con particolare riguardo ad alcune delle più interessanti: il modulo RTCC - un orologio e calendario real time - l’interfaccia parallela master PMP, il generatore  CRC.

Caratteristiche dei PIC24

Il core dei PIC 24 è basato su una CPU a 16 bit con un’architettura Harvard modificata: come sappiamo ciò significa che memoria, programma e dati utilizzano due bus differenti. Questo rende possibile realizzare una pipeline di esecuzione delle istruzioni che, nel caso dei PIC24, permette di eseguire un’istruzione ogni due cicli di clock (ovvero un ciclo istruzione: Tcy). Si tratta inoltre di un’architettura Harvard modificata in quanto è possibile scambiare dati tra le memorie programma e dati. Nella tradizione Microchip, l’architettura Harvard presenta memorie programma e dati di larghezza differente, 24 e 16 bit rispettivamente: ciò permette di avere codici d’istruzione che comprendono gli indirizzi degli operandi, in modo tale da poter eseguire quasi tutte le istruzioni in un solo ciclo. Deriva però lo svantaggio di non poter eseguire codice da RAM. Rispetto alla famiglia PIC18 abbiamo a disposizione quindi una potenza elaborativa di gran lunga superiore, mentre la migrazione delle applicazioni è resa semplificata da un set d’istruzioni abbastanza simile, sebbene molto potenziato. In particolare le istruzioni dei PIC24 permettono l’uso dell’indirizzamento indiretto ed indiretto attraverso indice, che ottimizzano l’uso di un compilatore C. Il modello di programmazione fa uso di ben 16 working register a 16 bit, W0W15, con il registro W15 utilizzato come stack pointer per uno stack software, usato in particolare dai compilatori per gli interrupt e le chiamate di funzione. Alcune istruzioni permettono inoltre di eseguire calcoli su tre operandi, così da eseguire operazioni del tipo A+B=C in un solo ciclo. Completa la dotazione della CPU un moltiplicatore hardware 17 x 17 bit che permette di eseguire una moltiplicazione con/senza segno 16 x 16 bit in un singolo ciclo, ed il supporto hardware per le divisioni 32 / 16 bit. Rispetto ai dsPIC33, dei quali sono chiaramente diretti discendenti, i PIC24 sono privi dell’unità DSP, e risultano nel complesso adatti ad applicazioni di complessità relativamente elevata che non necessitino appunto di un Digital Signal Processor. Da non trascurare anche il fatto che l’architettura della pipeline e la tensione d’alimentazione di 3.3 V (tipici) permettono di contenere i  consumi, circa 20 mA @ 16 MIPS. I PIC24 sono attualmente disponibili in due famiglie, PIC24FJ e PIC24HJ, che differiscono tra loro principalmente per la frequenza di clock massima. Nel caso dei PIC24FJ la fck può arrivare a 32 MHz, contro gli 80 MHz per i PIC24HJ.  A queste frequenze corrisponde una potenza elaborativa massima di 16 MIPS e 40 MIPS (analoga quindi a quella dei dsPIC33) rispettivamente. Altre differenze riguardano la dotazione di periferiche, in particolare tutti i dispositivi della famiglia PIC24FJ sono dotati delle periferiche innovative quali RTCC, PMP e generatore CRC, mentre lo sono solo alcuni della famiglia PIC24HJ. Più di recente alcuni dispositivi della famiglia PIC24FJ sono stati dotati di un avanzato modulo USB OTG, analogo al modulo USB dei PIC32MX4XX.

Le periferiche dei PIC24

I PIC24 sono dotati di un vasto insieme di periferiche: possiamo innanzitutto dividerle tra periferiche innovative e per così dire tradizionali. Fra le prime troviamo:

» RTCC  (Real Time Clock and Calendar);

» PMP (Par allel Master Port);

» Generatore  CRC (Cyclic Redundancy Check): USB OTG (On-The-Go)

Mentre fra le periferiche più usuali ritroviamo:

» UART,  con encoder/decoder hardware per il protocollo IrDA;

» SPI Master/Slave per comunicazioni sincrone ad alta velocità;

» I2C™, con clock fino a 400 KHz;

» ADC con rate di conversione di 500 ks/s

» Comparatori analogici

» Timer  a 16 bit

» Input Capture

» Output Compare/PWM

Notiamo infine che le porte di I/O dei PIC24 sono capaci di sopportare una corrente massima di 18 mA, contro i soli 4 mA dei dsPIC33: sono così in grado di pilotare direttamente LED, o altri carichi simili. Nel corso dell’articolo focalizzeremo il nostro interesse su alcune delle nuove periferiche: RTCC, PMP e generatore CRC. Per quanto riguarda  il modulo USB OTG potete fare in parte riferimento all’articolo [1] sul modulo USB del PIC32, data l’analogia tra i moduli – pur con le dovute differenze tra il core a 16 ed a 32 bit.

Il peripheral remapping nei PIC24

Una delle caratteristiche innovative più interessanti che i PIC24 hanno in comune con i dsPIC33, è il cosiddetto peripheral remapping: la possibilità di rimappare alcune delle periferiche sui pin del dispositivo via software, anche a runtime, in modo da ottimizzarne l’uso. Basti pensare che perfino su dispositivi a 28 pin è così possibile utilizzare 2 UART, 2 SPI e 2 I2C contemporanee. È possibile rimappare quasi tutte le periferiche, tranne gli ingressi analogici, i moduli I2C (il modulo I2C1 ha però una disposizione alternativa non modificabile a run-time) e pochi altri terminali. In tabella 1 sono riportate la caratteristiche principali dei dispositivi maggiori della famiglia PIC24FJ64GA004, usata come riferimento per gli esempi di codice che vedremo di seguito.

Tabella 1: Caratteristiche dei dispositivi principali della serie PIC24FJ64GA004

Tabella 1: Caratteristiche dei dispositivi principali della serie PIC24FJ64GA004

Il Real-Time Clock dei PIC24

La periferica RTCC permette di realizzare un orologio real-time fornito di calendario, con la possibilità di generare un allarme da 1 secondo ad un anno di distanza. L’allarme può essere ripetuto automaticamente fino a 255 volte, o anche indefinitamente. In figura 1 è riportato il  diagramma a blocchi del modulo RTCC. Tra i pochi componenti esterni necessari al funzionamento del RTCC vi è un comune quarzo per orologi da 32.768 KHz collegato ai terminali dell’oscillatore secondario SOSC del PIC.

Figura 1: diagramma a blocchi del modulo RTCC dei PIC24.

Figura 1: diagramma a blocchi del modulo RTCC dei PIC24.

Il segnale  a 32 KHz viene diviso da un prescaler che fornisce in uscita un impulso ogni ½ secondo: questo impulso è usato dal timer per aggior nare 4 registri a 16 bit che contengono anno, mese, giorno, giorno della settimana, ora, minuti, secondi. Il formato dei dati contenuti nei registri è BCD (Binary Coded Decimal): 4 bit corrispondono ad una cifra decimale, cosa che ne facilita l’uso con i display  numerici. L’allarme può essere configurato per scattare ad una data ora o con un intervallo di tempo prestabilito da un secondo ad un anno, tramite una maschera di setup. Questa funzionalità è utile ad esempio per generare un interrupt periodico che permetta al PIC di eseguire il controllo di un qualche canale di comunicazione, come IrDA o radio. L’uscita del timer RTCC alla frequenza di 1 Hz può essere riportata sul pin RTCC del PIC24, in alternativa all’impulso generato allo scadere di un allarme, a seconda del valore del campo RTCOE del registro RCFGCAL. La periferica R TCC prevede anche la possibilità di eseguire una calibrazione a run-time dell’oscillatore a 32 KHz. Ciò è possibile aggiungendo o togliendo un numero di conteggi specifico al prescaler una volta al minuto, usando il  registro RCFGCAL. Tra i diversi  metodi utilizzabili per eseguire la calibrazione ne menzioniamo due: il primo utilizza una tabella di look-up che contiene degli appositi valori correttivi in funzione della temperatura ambiente misurata da un sensore, il secondo sfrutta il confronto con un’altra sorgente di clock usata dal PIC. Spesso infatti i quarzi usati per l’oscillatore primario ad alta frequenza possiedono caratteristiche di accuratezza e stabilità molto migliori dei piccoli quarzi da 32.768 KHz tipici degli orologi, e possono quindi essere usati come riferimento. Con questo secondo metodo è anche possibile tenere conto dell’invecchiamento del componente ed altri fattori. In ogni caso con un’adeguata calibrazione è possibile ottenere un precisione massima di circa 3 secondi/mese, contro i circa 50 secondi senza calibrazione. La CPU accede ai registri del RTCC indirettamente tramite dei registri per la configurazione o per leggere/scrivere  i valori dell’orologio e dell’allarme. Questi registri appartengono quindi al CPU-domain, distinto dai registri del RTCC-domain, che operano alla frequenza dei 32 KHz. Ciò permette al RTCC di funzionare a questa bassa velocità (con un consumo ridotto) e continuare ad operare anche se la CPU è posta in una modalità a basso consumo. Tra l’altro è proprio questa particolarità che permette di realizzare un orologio real-time...
Vediamo più in particolare come sono usati i registri  del CPU-domain. Il registro RCFGCAL (RTCC  Calibration and Configuration Register)  è utilizzato per configurare l’orologio e selezionare  i registri del RTCC-domain che contengono i valori dello stesso. I  registri del RTCC-domain  (si veda la tabella 2) sono selezionati tramite un campo puntatore su due bit, RTCPTR<1:0>: quando il puntatore è pari ad 11b, la CPU potrà accedere tramite il registro RTCVAL al registro YEAR dell’orologio.

Tabella 2: Organizzazione dei registri del RTCC-domain

Tabella 2: Organizzazione dei registri del RTCC-domain

Dopo la lettura/scrittura di RTCVAL,  il puntatore sarà decrementato automaticamente in modo che l’accesso successivo  riguarderà il registro MTHDY, e così via per le letture/scritture successive. Il registro ALCFGRPT (Alarm Configuration Register) è usato invece per configurare gli allarmi e per leggere/scrivere  i valori dei registri relativi del RTCC-domain (tabella 2). Anche in questo caso, i registri  del RTCCdomain sono selezionati tramite un campo puntatore, ALRMPTR<1:0>: quando il puntatore è pari ad 10b, la CPU potrà accedere, tramite il registro ALRMVAL, al contenuto del registro ALMTHDY. Dopo la lettura/scrittura di ALRMVAL  il puntatore sarà decrementato automaticamente in modo che l’accesso successivo riguarderà il valore del registro ALWDHR, e così via. Nel listato 1 è riportata la parte principale di un esempio d’uso del RTCC, che dovrebbe chiarirne l’utilizzo.

#include <p24fxxxx.h>
// configurazioni, prototipi, definizioni
//...
// Gestore interrupt RTCC
void __attribute__((interrupt, no_auto_psv)) _RTCCInterrupt(void)
{
   IFS3bits.RTCIF = 0; // azzera flag
   LATAbits.LATA1 = !LATAbits.LATA1; // LED
   RTCCReadVal(); // per debug
}
// Funzione main
int main(void)
{
   TRISAbits.TRISA1 = 0; // RA1 -> LED
   RTCCInit(); // inizializza data/orario RTCC
   RTCCReadVal(); // lettura RTCC
   while (1); // ciclo infinito
   return (0);
}
void RTCCInit(void)
{
   // abilita SOSC
    __builtin_write_OSCCONL(OSCCON | 0x02);
   // abilita la scrittura dei registri RTCC
    __builtin_write_RTCWEN();
   RCFGCALbits.RTCEN = 0; // disabilita RTCC
   PADCFG1bits.RTSECSEL = 1;
   RCFGCALbits.RTCOE = 1; //RTCC Output Enable bit
   IFS3bits.RTCIF = 0; // azzera l’interrupt flag RTCC
   IEC3bits.RTCIE = 1; // abilita l’interrupt
   RCFGCALbits.RTCEN = 1; // abilita RTCC
   // meglio bloccare la scrittura
   RCFGCALbits.RTCWREN = 0;
   // scrive data/orario
   time.sec = 0x00;
   time.min = 0x22;
   time.hr = 0x18;
   time.weekday = 0x2;
   time.day = 0x30;
   time.month = 0x09;
   time.year = 0x08;
   RTCCSet();
   // Setup allarme
   alarm.sec = 0x05; // scatta al secondo x5
   alarm.min = 0x01;
   alarm.hr = 0x01;
   alarm.weekday = 0x01;
   alarm.day = 0x01;
   alarm.month   =   0x01;
   RTCCAlarmSet();
}
// Scrive data-orario nei registri RTCC
void RTCCSet(void)
{
   __builtin_write_RTCWEN();

   // scrive orario-data nei registri RTCC
   RCFGCALbits.RTCPTR = 3;
   RTCVAL = time.ptr11; // year
   RTCVAL = time.ptr10; // month:day
   RTCVAL = time.ptr01; // week:hour
   RTCVAL = time.ptr00; // min:sec
   RCFGCALbits.RTCWREN = 0; // Lock the RTCC
}
// Scrive i dati dell’allarme nei registri RTCC
void RTCCAlarmSet(void)
{
   __builtin_write_RTCWEN();
   // attende sincronizzazione
   while(RCFGCALbits.RTCSYNC==1);
   ALCFGRPTbits.ALRMEN= 0; // disabilita
   // scrive i dati dell’allarme
   ALCFGRPTbits.ALRMPTR = 2;
   ALRMVAL = alarm.ptr10; // month:day
   ALRMVAL = alarm.ptr01; // week:hour
   ALRMVAL = alarm.ptr00; // min:sec
   // setup maschera e ripetizioni
   ALCFGRPTbits.AMASK = 2; // ogni 10 secondi
   ALCFGRPTbits.ARPT = 0xff;// 255 volte
   ALCFGRPTbits.CHIME = 1; // ripetizioni ON
   ALCFGRPTbits.ALRMEN= 1; // abilita allarme
   RCFGCALbits.RTCWREN = 0; // Blocca scrittura RTCC
}
// Legge i registri RTCC
void RTCCReadVal(void)
{
   // legge data/orario
   RCFGCALbits.RTCPTR = 3;
   time.ptr11 = RTCVAL; // year
   time.ptr10 = RTCVAL; // month:day
   time.ptr01 = RTCVAL; // week:hour
   time.ptr00 = RTCVAL; // min:sec
   // altre elaborazioni
   //...
}
Listato 1 esempio d’uso del modulo RTCC

Scorrendo il listato, possiamo vedere che la funzione main non fa altro che richiamare la funzione RTCCInit(), la quale si occupa d’inizializzare l’orologio e l’allarme, quindi tramite la funzione RTCCReadVal() leggerà  il contenuto dei registri dell’orologio. La funzione RTCCInit()  inizia attivando l’oscillatore secondario SOSC del PIC. Infatti anche se quest’oscillatore venisse selezionato come oscillatore di partenza tramite i bit di configurazione del PIC24, è sempre necessario attivarlo settando il bit SOSCEN del registro OSCCON. Per poter scrivere nel registro OSCCON è necessario eseguire una sequenza di sblocco, richiamata tramite la funzione builtin del compilatore C per PIC24 di Microchip:

__builtin_write_OSCCONL(OSCCON | 0x02)

l’uso di questa funzione ci evita di inserire del codice assembly inline, di per sè necessario per garantire l’esecuzione delle istruzioni di sblocco con le corrette tempistiche. Segue la chiamata di un’altra funzione built-in del compilatore, da richiamare ogni volta che risulta necessario scrivere in uno dei registri del RTCC. Analogamente alla precedente,  il codice esegue la sequenza di sblocco per poter eseguire la scrittura del bit RTCWREN del registro RCFGCAL

__builtin_write_RTCWEN();

In realtà le funzioni built-in non eseguono una vera chiamata di funzione, ma sono tradotte direttamente dal compilatore in una sequenza assembly: ad esempio nel caso appena visto il  codice assembly generato sarà del tipo seguente

mov #0x55, Wn
mov Wn, _NVMKEY
mov #0xAA, Wn
mov Wn, _NVMKEY
bset _RCFGCAL, #15
nop
nop

dove _NVMKEY corrisponde al registro di sblocco della scrittura. Sebbene sia possibile ottenere la stessa sequenza tramite dell’assembly in-line, come permette il  compilatore C per PIC24, l’uso delle funzioni built-in è preferibile in quanto assicura l’allocazione corretta dei registri della CPU ed inoltre permette di usare tutte le ottimizzazioni del compilatore (alcune di queste vengono infatti disabilitate se è usato l’assembly inline). Una volta eseguito lo sblocco vengono settati i  bit di configurazione del registro RCFGCAL, abilitato l’interrupt del RTCC ed infine avviato l’orologio settando il bit RTCEN di RCFGCAL. La scrittura dei valori dell’orologio nei registri del RTCC avviene come già detto indirettamente scrivendo nel  re gistro RTCVAL (funzione RTCCSet()): notiamo come il puntatore RTCPTR punti inizialmente al registro YEAR del RTCC-domain

RCFGCALbits.RTCPTR = 3;

I  registri dell’allarme sono scritti utilizzando il registro ALMVAL con una tecnica analoga (funzione RTCCAlarmSet()), mentre tramite il registro ALCFGRPT sono settati la maschera dell’allarme (in modo che questo scatti una volta ogni 10 secondi), ed il numero di ripetizioni. Viene infine attivato l’allarme settando il bit ALRMEN. La funzione RTCCReadVal() non fa altro che settare il puntatore RTCPTR in modo che le letture successive del registro RTCVAL ci riportino in sequenza  il contenuto  dei  registri  YEAR,  MTHD Y, WKDYHR e MINSEC. Infine, la funzione _RTCCInterrupt() è il gestore dell’interrupt del R TCC. Nell’esempio è usata per segnalare con un LED lo scadere dell’allarme e leggere  i valori dell’orologio a scopo di debug.

La Parallel Master Port dei PIC24

La periferica PMP dei PIC24 è un’evoluzione della PSP (Parallel Slave Port) già presente su alcuni dispositivi Microchip (ad esempio i PIC18F4620).  Una porta parallela di tipo master è in grado di colloquiare con un minimo intervento del firmware con dispositivi che utilizzano un’interfaccia parallela per velocizzare le operazioni di scambio dati, come ad esempio memorie EEPROM, memorie Compact Flash e display grafici LCD. In figura 2 è riportato uno schema delle connessioni del modulo PMP.

Figura 2: connessioni del modulo PMP.

Figura 2: connessioni del modulo PMP.

Le caratteristiche salienti del modulo sono le seguenti:

» bus indirizzi fino a 16 pin PMA<15:0> che permette di indirizzare un massimo di 64k locazioni.  I pin fisicamente presenti dipendono dal dispositivo;

» bus dati con 8 bit paralleli PMD<7:0>, in grado di supportare operazioni sia su 8 che su 16 bit, tramite il pin PMBE (Byte Enable);

» 2 segnali di chip select, PMCS1 e PMCS2, che possono essere eventualmente utilizzati come linee aggiuntive per gli indirizzi;

» altri due pin sono utilizzati per i segnali di Read, Write ed Enable, secondo gli standard Motorola o Intel.

Il modulo PMP supporta anche il multiplexing dei segnali dati e indirizzi in modo da risparmiare pin per altri scopi. In particolare sono disponibili tre tipologie di multiplexing, selezionate tramite i  bit PMCON<ADRMUX1:ADRMUX0>:

» demultiplexed: in questa modalità i segnali dati ed indirizzi sono completamente separati. Questa modalità, pur essendo la più veloce (un trasferimento richiede un solo Tcy) permette però di usare 16 bit di indirizzo solo sui dispositivi con almeno 64 pin;

» partially multiplexed: gli 8 bit bassi PMA<7:0> dell’indirizzo sono multiplexati con gli 8 bit di dati. I  bit superiori sono presenti invece sui pin PMA<15:8>, il numero effettivo dei quali dipende dal dispositivo.  Il pin PMA<0> è usato come latch per gli indirizzi (segnale PMALL) ed è attivo quando sul bus dati è presente la parte bassa dell’indirizzo. Questa modalità di trasferimento richiede quindi almeno 2 Tcy, oltre all’eventuale logica aggiuntiva (ad esempio dei latch 74AHC373) per demultiplexare indirizzi e dati;

» fully multiplexed: in quest’ultima modalità tutti i 16 bit di indirizzo sono multiplexati con gli 8 bit  dati. Vengono eseguito tre cicli di trasferimento: nel primo vengono inviati gli 8 bit bassi dell’indirizzo PMA<7:0> sul bus dati, mentre il pin PMA<0> è usato come segnale PMALL per segnalare la presenza del byte basso, nel secondo ciclo sono inviati gli 8 bit alti  PMA<15:8>, mentre questa volta è utilizzato  il pin PMA<1> per emettere  il segnale PMALH che segnala la presenza del byte alto, infine nel terzo ciclo sono in viati o ricevuti i dati PMD<7:0. Si tratta quindi della modalità di funzionamento più lenta, che tuttavia rende possibile l’uso di 16 bit d’indirizzo anche sui dispositivi a 28 pin. Naturalmente può essere richiesta della logica aggiuntiva per demultiplexare  i segnali se la periferica collegata non è in grado di effettuare  il latch degli indirizzi. Tramite  i bit PMMODE<INCM1:INCM0> la PMP può essere configurata per incrementare/decrementare automaticamente l’indirizzo dopo ogni operazione di lettura/scrittura. Ogni segnale di controllo della PMP può essere abilitato o disabilitato tramite il registro di configurazione PMCON ed il registro PMAEN (CS1 e CS2), così come si può scegliere la polarità dei singoli segnali, sempre tramite il registro PMCON.

Modalità di interfacciamento

Il modulo PMP può interfacciarsi con periferiche standard secondo due modalità Master, selezionate tramite i bit PMMODE<MODE1:MODE0>

»  Standard   M o t o r o l a   (MODE1:MODE0=11): utilizzato dalle periferiche Motorola oltre che dalla maggior parte degli LCD paralleli. In questo standard i  segnali di Read e Write sono condivisi sullo stesso pin PMRD, mentre il segnale di Enable è presente sul pin PMENB.

» Standard Intel (MODE1:MODE0=10): utilizzato dalle periferiche Intel e dalle memorie ad accesso parallelo. In questo standard i  segnali di Read e Write sono separati sui due pin PMRD e PMWR, dove quest’ultimo corrisponde al pin PMENB, dato che il segnale  di Enable in questo caso non serve. Per potersi interfacciare con periferiche lente, in particolare memorie, è possibile aggiungere dei wait states tramite i bit PMMODE<WAITM3:WAITM0>, PMMODE<WAITB1:WAITB0> e PMMODE<WAITE1:WAITE0> così da rallentare  i diversi segnali della PMP. Oltre alle due modalità master, il modulo PMP può funzionare anche in due modalità Slave, denominate legacy -corrispondente alle tradizionali PSPed enhanced. In quest’ultima modalità, a sua volta distinta in due varianti, buffered ed addressable, è abilitato un buffer FIFO di 4 byte per i dati di ingresso/uscita, indirizzabile direttamente  nella variante addressable.

Il modulo  CRC dei PIC24

Il modulo CRC è una periferica in grado di calcolare in hardware una checksum CRC. Una checksum CRC è utilizzata per rilevare errori nei protocolli di comunicazione ma anche in blocchi di memoria. Normalmente è implementata tramite un hardware incluso nella periferica di comunicazione, ad esempio un motore USB, un’interfaccia Ethernet od un modulo CAN. Il modulo CRC dei PIC24 è invece standalone, così da poter essere utilizzato ad esempio per garantire l’integrità dei dati in protocolli di comunicazione usati dall’UART, come XModem o CCITT, od ancora IrDA.

Principio  di funzionamento del CRC

Il codice CRC utilizza un polinomio specificato dall’utente, detto polinomio generatore, di una lunghezza prefissata, ad esempio 12 bit. I dati sui quali va calcolata la checksum vengono fatti passare attraverso  il modulo CRC e divisi per il polinomio generatore per generare un resto che costituisce la checksum. Questa viene quindi aggiunta in coda ai dati da trasmettere o memorizzare. Dal lato del ricevitore, o quando i dati memorizzati sono riletti, i dati sono fatti passare nuovamente attraverso  il generatore  CRC, che utilizza lo stesso polinomio generatore, per ricalcolare la checksum. Se questa checksum è identica a quella aggiunta alla fine dei dati, è altamente probabile che i dati siano validi. La robustezza del codice CRC dipende essenzialmente dal numero di bit del polinomio generatore. Lo standard CRC-CCITT ad esempio, che utilizza un polinomio generatore a 16 bit, è in grado di riconoscere errori singoli e doppi, tutti gli errori costituiti da un numero di bit dispari e tutte le raffiche di errori con lunghezza minore o pari a 16. Vediamo più nel dettaglio come funziona e come possiamo utilizzare il  modulo CRC dei PIC24. Il modulo è costituito da due blocchi principali:

» logica di controllo: comprende i registri tramite i quali il modulo è controllato dalla CPU, un’interfaccia con il motore CRC, una FIFO, ed il generatore  dell’interrupt;

» motore CRC: implementa  il generatore CRC vero e proprio. La divisione usata dal codice CRC è una divisione modulo 2, che richiede essenzialmente una serie di shift e sottrazioni modulo 2. La sottrazione modulo 2 è a sua volta eseguita tramite uno XOR (in pratica addizione e sottrazione sono identiche). Il generatore  CRC, il cui schema è riportato in figura 3, comprende quindi uno shift register a 16 bit con punti di feedback programmabili tramite un multiplexer.

Figura 3: schema del generatore CRC dei PIC24.

Figura 3: schema del generatore CRC dei PIC24.

Per poter usare il modulo CRC è innanzitutto necessario configurarlo inserendo i  dati del polinomio generatore. I  bit CRCCON<PLEN3:PLEN0> sono usati per indicare l’ordine del polinomio (corrispondente al termine di grado massimo) meno 1. Il  registro CRCXOR sarà caricato invece con i coefficienti  dei termini del polinomio compresi tra x15 ed x1, dato che i coefficienti del termine di grado massimo e del termine x0  sono assunti sempre pari ad 1. Ad esempio i coefficienti del polinomio generatore di ordine 16, CRC-CCITT:
x16+x12+x5+x0
saranno memorizzati nel registro come 1020H. I dati sui quali è calcolata la checksum vengono inseriti nel registro CRCDAT: ad ogni scrittura il dato viene aggiunto nella FIFO contenuta nel modulo CRC. È possibile memorizzare nella FIFO un massimo di 8 parole da 16 bit, o in alternativa 16 byte (se PLEN è ≤7).
I bit CRCCON<VWORD4:VWORD0> in dicano il numero degli elementi presenti nella FIFO: durante il calcolo del codice CRC, questo numero decresce finché non arriva a zero. A questo punto è possibile leggere il  valore della checksum dal registro CRCWDAT. Per esemplificare vediamo quale dev’essere la procedura per calcolare la CRC nel caso di un polinomio generatore di 16 bit con un messaggio di non più di 128 bit di lunghezza (ipotizziamo per semplicità che sia il primo calcolo CRC dopo il reset):

1- porre CRCCON<PLEN3:PLEN0>=0FH (16 meno 1);

2- scrivere i coefficienti  del polinomio generatore (tranne quello del termine di ordine massimo e del termine x0) nel registro CRCXOR;

3- scrivere il valore 0000H nel registro CRCWDAT per indicare un nuovo calcolo CRC;

4- scrivere  i primi 16 bit del messaggio nel registro CRCDAT;

■  5- se sono stati scritti tutti i dati del messaggio scrivere 0000H nel registro CRCDAT e passare al punto seguente, altrimenti tornare al punto 4;

6- iniziare il calcolo CRC settando il bit CRCCON<CRCGO>;

7- quando il bit CRCCON<CRCMPT> è 1, porre a 0 il bit CRCCON<CRCGO> e  legger e  il   risultato  dal  r e gistr o CRCWDAT;

In conclusione,  il modulo CRC dei PIC24 permette di eseguire  il calcolo CRC con un minimo uso di firmware e ad alta velocità. In pratica, considerando che l’hardware CRC funziona a velocità doppia rispetto alla CPU (2*fcy), sono necessari  solo  64  Tc y  per  calcolar e  la checksum su un messaggio di 128 bit di lunghezza. Una versione software dello stesso calcolo richiederebbe all’incirca un migliaio di Tcy.

 

 

Scrivi un commento

EOS-Academy

Ricevi GRATIS le pillole di Elettronica

Ricevi via EMAIL 10 articoli tecnici di approfondimento sulle ultime tecnologie