Reti CAN: strumenti di progettazione e diagnosi

Per far esperimenti con la rete CAN è utile provare un simulatore prima del vero hardware. Questo documento mostra come usare l’apparecchiatura di simulazione inclusa nel Microcontroller Development Kit (MDK-ARM) di Keil® per il microcontroller STM32 ARM® Cortex™ M3.

CONTROLLER CAN STMICROELECTRONICS PER PROCESSORI CORTEX-M3.

In figura 1 è mostrato un diagramma a blocchi del controller CAN. I punti più importanti di tutti controller CAN sono:

  1. Piedini di I/O: si connettono ai piedini R e D del chip transceiver CAN come già descritto.
  2. Convertitori Seriale-Parallelo: CAN è un bus seriale mentre il processore è parallelo. La conversione avviene qui.
  3. Mailbox Tx: i messaggi da trasmettere sono scritti qui. ID, dati (se ce ne sono) e DLC vanno qui.
  4. Filtro di accettazione: questo passa, attraverso FIFO, al processore soltanto messaggi Per default, al RESET questi filtri passano a FIFO tutti i messaggi. È il vostro software che deve configurarli per filtrare i messaggi.
  5. FIFO 0 e 1: ogni FIFO di ricezione può contenere 3 messaggi Essi forniscono un sistema di buffer per il processore.
  6. Registri di controllo, di stato e di configurazione: è il vostro software che deve configurare questi registri, di solito all’inizializzazione.

Tutti i controller CAN hanno la stessa architettura di base. Controller differenti potranno avere differenze nel numero dei buffer FIFO di ricezione e/o di trasmissione, nella grandezza dei filtri di accettazione e di quella mappatura dei bit, negli indirizzi e le definizioni dei vari registri di configurazione. Tutti controller CAN sono autorizzati dalla Robert Bosch GmbH tedesca e quindi possono esercitare un controllo considerevole sugli attributi di base CAN in modo che siano coerenti tra i diversi fabbricanti. Ciò significa che tutti i controller CAN possono comunicare con altre marche in modo affidabile e prevedibile.

Figura 1: diagramma a blocchi del controller CAN.

Figura 1: diagramma a blocchi del controller CAN.

PROGRAMMA CAN DI ESEMPIO (KEIL)

  1. Inizializzate Vision® cliccando la sua icona sul vostro schermo.
  2. Selezionate Project/Open Aprite il file C:\Keil\ARM\Boards\Keil\MCBSTM32\CAN\CAN.Uv2.
  3. Assicuratevi che nel menù a discesa sia selezionato “Simulator”.
  4. Nel file sorgente c’è un errore. Nel file CanDemo.c andate alla riga 126. Probabilmente ci sarà scritto: delay (45000000); // Wait for initial display (~5s). Questo è troppo lungo. Cambiate il valore a una quantità inferiore. 45000 va bene.
  5. Compilate i files sorgenti cliccando sull’icona Build. Verranno compilati senza errori o avvertimenti.
  6. Cliccate su Options per avere l’icona Target. Poi selezionate Debug e assicuratevi che sia scelta ”Use Simulation”.
  7. Entrate in modo Debug cliccando sull’icona Debug. Scegliete OK quando appare il box Evaluation Mode.
  8. Posizionate i Toolbox, saranno appropriate CAN:Communication e CAN:Controller.
  9. Cliccate l’icona RUN. Nota: potete fermare il programma con l’icona STOP.
  10. Noterete che messaggi CAN con ID 0x21 appaiono nella finestra CAN:Communications. Potete vedere sia frames di trasmissione che di ricezione. Il controller CAN e in uno speciale Test Mode che gli permette di vedere i propri messaggi.
  11. Nella finestra Toolbox cliccate sul pulsante “Analog Sweep 0…3.3v”.
  12. Nei messaggi CAN appariranno ora valori di dati mutevoli: essi rappresentano l’output del convertitore A/D.

La Keil con i propri strumenti di sviluppo fornisce un esempio funzionale di CAN. Avete già compilato e  lanciato  questo esempio. Potete vedere e modificare i files sorgenti C sia in modo debug che non, ma per compilarli non dovete essere in modo debug. Questo esempio non usa quasi alcun codice assembler ed è (quasi) completamente scritto in C. In Vision può essere aperto qualsiasi file sorgente se non è già visibile cliccando su File/Open e selezionandolo. Guarderemo ora tre files sorgenti:

Can.h: questo file definisce una struttura per contenere le informazioni usate per costruire la frame CAN e crearne due copie.

Can.c: questo codice C inizializza il controller CAN, scrive e trasmettere un messaggio, riceve un messaggio, configura il filtri di accettazione e fornisce il modo di maneggiare gli interrupts di trasmissione e ricezione.

CanDemo.c: in questo file risiede la funzionalità principale. CanDemo.c è il cuore del programma dimostrativo e chiama le funzioni contenute in Can.c.

LA STRUTTURA CAN_MSG

In figura 2 viene mostrata la dichiarazione di struttura di Can.h. Adesso dovete essere in grado di riconoscere ognuno di questi elementi. Potete scrivere sia un identifier da 11 che da 29 bit. Più sotto sono chiamate e mostrate due copie di CAN.msg: CAN_TxMsg e CAN_RxMsg. CanDemo.c le usa per creare messaggi CAN con dati. I prototipi delle funzioni usate in Can.c sono elencati in Can.h alle righe da 32 a 40. Esse sono visibili con Vision.

23 typedef struct {
24 unsigned char id;               //29 bit identifiler
25 unsigned char data;             //data field
26 unsigned char len;              //length of data field in bytes
27 unsigned char format;           //0 – STADARD, 1 – EXTEDED
28 unsigned char type;             //0-DATA FRAME, 1-REMOTE FRAME
29 } CAN_msg;
42 extern     CAN_msg CAN_TxMsg;  //CAN message for sending
43 extern     CAN_msg CAN_RxMsg;  //CAN message for receiving
Figura 2: la dichiarazione di struttura di Can.h.

LA CONFIGURAZIONE DEL CONTROLLER CAN: (CAN.C)

Ci sono diverse cose da fare per configurare accuratamente il controller CAN. Queste vengono fatte in Can.c da funzioni che sono chiamate da CanDemo.c. Degli esempi si trovano nella funzione CAN_setup alle righe da 28 a 58 e mostrate in Vision:

  1. Abilitare e settare il clock del controller CAN. Per CAN il clock deve essere stabile. Qui niente oscillatori R-C.
  2. Configurare le porte GPIO PB8 e PB9 per le linee di trasmissione e ricezione al chip transceiver.
  3. Abilitare gli interrupts per le funzioni di trasmissione e ricezione.
  4. Settare CAN-BTR: questo è un registro del controller 32 CAN in cui vengono settate cose tipo la temporizzazione di bit, la frequenza del bus, punti di controllo e modi silent e loop back. Nell’esempio di Keil il baudrate viene settato a 500 Kbps (bits per secondo).

Spesso i settaggi di temporizzazione possono causare strani problemi. Se vi capitano alcuni problemi non usuali dovreste studiare la temporizzazione CAN più accuratamente. Per i piccoli sistemi, i settaggi di default o quelli suggeriti dal fabbricante del processore funzioneranno soddisfacentemente. Potete variare questi settaggi per ottenere la performance più robusta del bus.

TRASMISSIONE DI UN MESSAGGIO CAN

Le righe da 131 a 135 (figura 3) scrivono i valori della frame nella struttura CAN_TxMsg. (Tranne che per i byte di dati che vengono dal converter A/D). Questo messaggio CAN invierà un byte di dati. Per esempio, se, nella membro CAN_TxMsg.len, cambiate il valore da 1 a “3”, nel bus verranno inviati tre bytes di dati. Quali dati essi conterranno dipende dal contenuto dell’array CAN_TxMsg.data. Se inviate più byte di dati di quelli che avete, è una buona idea a riempire i byte di dati vuoti con 0 oppure 0xFF. La riga 141 scrive il valore di A/D nel membro dati CAN_TxMsg.data nel byte di dati 0 e la riga 142 lo trasmette (figura 4).

131 CAN_TxMsg.id=33;              //initialize message to send
132 for (i=0; i<8; i++) CAN_TxMsg.data[i]=0;
133 CAN_TxMsg.len=1;
134 CAN_TxMsg.format=STANDARD_FORMAT;
135 CAN_TxMsg.type=DATA_FRAME;
Figura 3: trasmissione di un messaggio CAN.
141 CAN_TxMsg.data[0]=adc_Get();   //data[0] field = ADC Value
142 CAN_wrMsg (&CAN_TxMsg):        //transmit message
143 val_Tx= CAN_TxMsg..data[0];    //send to LCD screen
Figura 4: la riga 141 scrive il valore di A/D nel membro dati CAN_TxMsg.data nel byte di
dati 0 e la riga 142 lo trasmette.

RICEZIONE DI UN MESSAGGIO CAN

le righe da 148 a 151 (figura 5) indicano quando viene ricevuto un messaggio CAN. Ma qui deve succedere qualcosa. La linea 151 mostra che il byte di dati ricevuto e inserito nell’array[0] è inviato per essere mostrato sull’LCD.

148 if(CAN_RxRdy) {
149 CAN_RxRdy=0;
151 val_Rx=CAN_RsMsg.data[0];
Figura 5: le righe da 148 a 151
indicano quando viene ricevuto
un messaggio CAN.

Come fa esattamente il byte di dati CAN a entrare nell’array membro CANRxMsg.data[0]? Ricordiamoci che prima è stato detto che la funzione per leggere i dati CAN era scritta dentro Can.c. Se guardiamo dentro Can.c, troviamo la funzione CAN_rdMsg alle righe da 130 a 159. Esaminandola è chiaramente qui che l’array[0] è veramente caricato alla riga 148. Ma come viene chiamata questa funzione? Non viene chiamata da CanDemo.c. Se apriamo un breakpoint alla riga 132 di Can.c (la prima istruzione assembler della funzione Can_rdMsg) facendo un doppio clic nella parte sinistra della riga 132, possiamo controllare la finestra Call Stack per vedere da dove era stata chiamata (figura 6).

Figura 6: la finestra call Stack.

Figura 6: la finestra call Stack.

Questo potrebbe indicare che CAN_rdMsg è stata chiamata dalla riga 148 della funzione principale. Ma esaminando il codice in assembler alla riga 148 si vede che questo non può essere vero. Possiamo usare la funzione Trace di Vision, che è disponibile in modo Simulator, per renderci conto di come viene chiamata CAN_rdMsg, ovvero:

  1. Cliccare sull’icona Enable Trace Recoding.
  2. Lanciate il programma fino al breakpoint stabilito precedentemente sulla riga 132.
  3. Cliccare su View Trace Records e guardare la finestra Disassembly che viene aperta.

La freccia gialla punta all’inizio della funzione CAN_rdMsg. La freccia rappresenta il contatore del programma. L’area grigia mostra una registrazione delle istruzioni che sono state eseguite. L’aria bianca mostra le istruzioni che non sono state eseguite. Proprio prima della riga 132 c’è la linea sorgente 213: è lei che chiama CAN_reMsg. Questa è in realtà l’istruzione in assembler all’indirizzo 0x800A10 BL.W, CAN_reMsg. Leggendo più in alto alla riga 210: possiamo vedere che questa linea sorgente viene dalla funzione USB_LP_CAN_RX0_IRQHandler che è il Receive Interrupt Handler scritto in Can.c. Quindi, questo interrupt handler ha chiamato la funzione che legge la frame CAN del controller CAN e la mette nella struttura.  Se qui cliccate col tasto destro sulla riga 210 e selezionate Show Source at Current Line esso verrà mostrato nel file sorgente. Se nel vostro processore avete più di un controller CAN, potete usarli come ricevitori paralleli. Con gli Acceptance Filters potrete dividere i messaggi. Questo che potrà aiutare a catturare tutti i messaggi in un bus molto occupato senza perderne alcuno. Ogni controller CAN si occuperà della propria parte dei messaggi. Ciò molto tipica in realtà il numero di memorie del buffer FIFO il che è un eccellente metodo per catturare tutte le frames CAN.

EXCEPTION, PC E  DATA TRACKING

Il processore ST Cortex-M3 possiede import CAN di capacità di debug. Queste possibilità sono raggruppate nel Serial Wire Viewer e vengono supportati dal Vision della Keil e ULINK2 e ULINKME dell’adattatore USB-JTAG. Ricordate che Can.c contiene due interrupt handlers: uno per trasmettere e uno per ricevere. Essi possono essere visualizzati in real-time (non viene perso alcun ciclo di CPU) nella finestra Trace Records come mostrato in figura 7.

Figura 7: la finestra Trace.

Figura 7: la finestra Trace.

Questo funziona solo con un Cortex-M3 connesso a Vision via un USB ULINK2 o ULINK-ME e un adapter JTAG. Il Serial Wire Viewer può essere usato per mostrare campioni PC, cicli di lettura e scrittura di dati, eccezioni e certi altri eventi. L’ITM è un output di strumentazione di tipo printf. Per mostrare il nostro esempio usando il Serial Wire Viewer e il chip STM32:

  1. Collegate un processore STM32 a Vision e lanciate lo stesso programma CAN usando il debugger ULINK Cortex.
  2. Attivate il Serial Wire Viewer come descritto nell’appendice di: www.keil.com/download/files/labst.pdf.
  3. Configurate il Logic Analyzer per mostrare CAN_RxMsg.data[0]. Ciò lo mostrerà anche nel Trace Records.
  4. Aprite un breakpoint all’istruzione della riga 148 di Can.c. Essa è la prima istruzione dopo la scrittura nell’array CAN_RxMsg.data[0]. Questo si rende necessario perché l’istruzione su cui è puntato il breakpoint non viene eseguita. Vogliamo vedere e registrare questa scrittura quindi dobbiamo eseguire questa riga sorgente.
  5. Lanciate il programma fino al breakpoint. La finestra Exception Trace viene mostrata in figura 7.

Vengono mostrati due eventi IRQ; notare che un IRQ è un subset di Exceptions. Con riferimento al Reference Manual di ST RM0008, IRQ 19 è l’IRQ di trasmissione di CAN, e IRQ 20 è quello di ricevimento. In figura 8 è riportata la finestra Trace Records. Possiamo vedere le righe seguenti:

  • Terza e quarta riga: Exception Entry e Exit: 35: questo è l’IRQ di trasmissione. Traducete il 35 in IRQ19 della finestra Exception Trace più sopra.
  • Quinta riga: Exception Entry: 36: questa è l’entry dell’IRQ20, è lo handler dell’IRQ di ricezione.
  • Sesta riga: Data Write: il valore 0x8F viene scritto all’indirizzo 0c2000004C dalla istruzione in 0x8004910.

Potete confermare che questi valori rappresentano una istruzione assembler che è parte della riga sorgente 148 e che l’indirizzo ivi scritto è quello di CAN_RxMsg.data[0]. Quanto appena visto è una dimostrazione parziale delle caratteristiche di tracciamento di Serial Wire Viewer del processore Cortex-M3. Andate su www.keil.com per avere più informazioni concernenti l’interfaccia Serial Wire Viewer dei processori Cortex-M3.

Figura 8: la finestra Trace records.

Figura 8: la finestra Trace records.

UN ESEMPIO DI RETE CAN

In figura 9 viene mostrata una vera rete di 2 kit di CAN che usano le schede di valutazione MCBSTM32 della Keil (a destra) e MCBSTM32E che usano lo stesso codice di esempio illustrato in questo articolo. Il Tx di un nodo viene trasmesso all’Rx dell’altro nodo e ciò si può vedere chiaramente sull’LCD. Da notare la coppia di carri ritorti CAN Hi e CAN Lo conto da notare anche che in questa piccola rete non viene usato nessun cavo di terra.

Figura 9: una rete CAN sperimentale

Figura 9: una rete CAN sperimentale

Scrivi un commento

EOS-Academy