Strano bug software nel controllo BLDC: controllare attentamente i registri di sola scrittura

Non avevo mai visto un bug così prima. Sembrava che il sistema funzionasse normalmente, ma non secondo i dati di telemetria. L'ingresso della richiesta che determina la velocità a cui deve girare il motore segnalava 85%, ma per fortuna il motore non stava girando. Potevo far finta di niente e pensare a un problema del software di analisi dei dati di telemetria, ma qualcosa non mi tornava. Quindi decisi di andare a fondo e analizzare il sistema per cercare di capire cosa causava il bug.

Questo tipo di sistema usava un chip motore c.c. brushless (BLDC) A4964 di Allegro Microsystems che mi piace particolarmente, perché rappresenta una soluzione di comando motore flessibile e contiene il codice di controllo sufficiente per spostare la gestione dei cicli della CPU dal microcontroller (MCU) a un chip hardware dedicato (Figura 1).

Figura 1: A4964 è utile perché scarica il controllo di un motore BLDC dalla MCU all'hardware dedicato. (Immagine per gentile concessione di Allegro MicroSystems)

In questa configurazione di sistema utilizzavo l'interfaccia di comunicazione SPI per impostare i 32 registri su chip che stabiliscono come viene comandato e controllato il motore BLDC.

Per l'applicazione, A4964 viene configurato durante l'impostazione da una routine di inizializzazione, leggendo una tabella di configurazione che contiene i parametri desiderati per il motore. Lo pseudocodice (solo a scopo di esempio) è elencato di seguito (listato 1):

Copyfor(uint8_t WriteIndex = 0; WriteIndex < A4964MaxRegister; WriteIndex++)
{
    // Write value stored in A4964Config at index WriteIndex to the chip
}

Listato 1: La routine di inizializzazione che legge i parametri di configurazione del motore. (Codice sorgente: Jacob Beningo)

Dal punto di vista dell'inizializzazione, nel codice non può avvenire molto di sbagliato, quindi decisi subito di esaminare la logica principale che veniva chiamata regolarmente all'interno dell'applicazione. Questa parte di codice era già più interessante. Il dominio dell'applicazione era un ambiente ricco di radiazioni, che possono influenzare i valori memorizzati nella RAM. I valori di inizializzazione vengono scritti nella RAM di A4964 all'avvio quindi, per far fronte ad eventuali bit flip che possono verificarsi, la memoria di A4964 veniva letta periodicamente. In caso di mancata corrispondenza, le impostazioni venivano aggiornate. Lo pseudocodice era simile al seguente (listato 2):

Copyfor(uint8_t Index = 0; Index < A4964MaxRegister; Index++)
{
    // Read the A4964 configuration register at location Index

   // If read value does not match expected value, write configuration value
}

Listato 2: Le radiazioni locali potevano influenzare i valori memorizzati nella RAM quindi, per far fronte ai bit flip, la memoria di A4964 veniva letta periodicamente e le impostazioni venivano aggiornate in caso di mancata corrispondenza. (Codice sorgente: Jacob Beningo)

Ancora una volta mi trovavo di fronte a codice semplicissimo, in cui non poteva accadere molto. Eppure, per qualche motivo, qualcosa scriveva un valore di ingresso di richiesta errato nel chip. Sembrava che il valore non fosse costante: compariva a volte nella telemetria prima che venisse segnalato il valore corretto e poi di nuovo indicando il valore errato. Veramente strano.

E, ancora più interessante, non c'era alcun valore di configurazione o dell'applicazione che potesse scrivere un 85% nel registro! Quindi da dove veniva questo 85%? Un 85 decimale è 0x55 se convertito in valore esadecimale. C'era forse uno 0x55 nella base di codice? Ma certo! 0x55 viene usato come carattere di scrittura fittizio per le operazioni di lettura sul bus SPI! Ma in che modo le operazioni di lettura vengono convertite in operazioni di scrittura?

In realtà la risposta è piuttosto ovvia se consultiamo la scheda tecnica di A4964 (Figura 2).

Figura 2 : Una sezione della scheda tecnica mostra il problema: il registro 30 è di sola scrittura! (Immagine per gentile concessione di Allegro MicroSystems)

Il registro 30, che gestisce l'ingresso della richiesta (DI) del motore è di sola scrittura! Un tentativo di leggere da questo registro causa la scrittura del byte fittizio nel registro stesso. Questa semplice funzione di inizializzazione e aggiornamento del chip tentava di leggere dal registro di ingresso di richiesta per verificare le impostazioni e inavvertitamente scriveva un nuovo ingresso di richiesta. Il sistema continuava a funzionare normalmente perché la lettura del registro di scrittura causava sempre la scrittura del valore corretto poco dopo, ma non sempre abbastanza in fretta da evitare che il valore scorretto finisse nella telemetria del sistema.

Con A4964, uno sviluppatore software non può scrivere dati di configurazione in tutta la mappa di memoria, ma deve fermarsi al registro 29. Gli ultimi due registri indirizzabili sono registri speciali di sola lettura e scrittura.

Anche se facciamo di tutto per scrivere un driver o implementare un software nel migliore dei modi, a volte l'imprevisto è dietro l'angolo. I bug più strani sono spesso opportunità per imparare qualcosa di nuovo sull'hardware, e di frequente fanno nascere nuove best practice. Questo strano minuscolo bug mi ha fatto aggiungere alla lista la voce "Controllare attentamente i registri di sola lettura/scrittura" per assicurarmi di gestirli in modo corretto. In una situazione diversa, leggere quel registro di sola scrittura avrebbe potuto causare un evento catastrofico all'interno del sistema.

Informazioni su questo autore

Image of Jacob Beningo

Jacob Beningo è un consulente software embedded e attualmente lavora con clienti in più di una decina di paesi per trasformare radicalmente le loro attività migliorando la qualità dei prodotti, i costi e il time-to-market. Ha pubblicato più di 200 articoli sulle tecniche di sviluppo di software embedded, è un relatore e un istruttore tecnico e ha conseguito tre lauree, tra cui un master in ingegneria presso University of Michigan. Risponde all'indirizzo jacob@beningo.com, ha un sito web personale www.beningo.com e produce una Newsletter mensile Embedded Bytes cui è possibile iscriversi.

More posts by Jacob Beningo
 TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum