Stavo sviluppando un progetto TV, quando qualcosa di strano mi ha infastidito per qualche giorno. Il progetto CRT (Cathode Ray Tube) TV utilizzava un microcontrollore Philips 8051 dotato di periferiche OSD (On Screen Display) e Tuning.
Il software girava sul mio emulatore senza problemi. Quindi i nostri clienti hanno deciso di avviare la produzione pilota. Il team QA mi ha subito segnalato di aver trovato qualcosa di strano durante l'audit interna. In un lotto di 12 televisori, circa 5 hanno fatto casualmente delle linee dopo l'accensione. L'evento era imprevedibile.
Una immagine è mostrata sullo schermo televisivo scandendo, una riga alla volta, un segnale elettrico orizzontalmente. L'ampiezza di questo segnale nel tempo rappresenta la luminosità istantanea in quel punto fisico sullo schermo. Alla fine di ogni riga, esiste una porzione della forma d'onda (intervallo di blanking orizzontale), che dice al circuito di scansione di ritornare verso la parte sinistra dello schermo e poi scandire la riga successiva.
Una volta che la prima immagine è stata scandita, esiste un'altra porzione d'onda (intervallo di blanking verticale, non mostrato), che dice al circuito di scansione di ripercorrere la parte superiore del display e scandire l'immagine successiva. Questa sequenza viene ripetuta periodicamente, abbastanza velocemente, in modo che le immagini visualizzate siano percepite come un continuo movimento.
In una TV CRT, il segnale video normale è visibile sullo schermo, perché la tensione del segnale video è superiore a quello di riferimento del livello di nero. Durante l'intervallo di oscuramento la tensione del segnale video è fissato a livello di oscuramento che è inferiore a quello del livello di nero così la linea di ritraccia è invisibile durante questo oscuramento orizzontale o verticale.
I nostri clienti ed io abbiamo passato una settimana per capire cos’è andato male. Abbiamo provato a verificare il suo rapporto con la temperatura nella camera di tortura (ero quasi congelamento in quel grande frigorifero), ma non siamo riusciti a capire la causa principale. Abbiamo provato il debug sull'emulatore, ma il software era OK. Avevamo provato di tutto, ed eravamo sul punto di rinunciare.
Infine, il nostro cliente ha catturato la linea di scansione con un oscilloscopio. Era chiaramente visibile che l'OSD addizionale dal microcontrollore era attivato e il segnale video finale era superiore al livello di nero. La linea di scansione visualizzata sullo schermo non era il segnale video, ma il segnale proveniente dall'OSD. C'era un difetto nel software. Ma perché questo difetto non accadeva mai usando l'emulatore? Ho ricontrollato la specifica dei microcontrollori TV. I registri relativi l'OSD sono assegnati nello spazio RAM esterno (XDATA) dell' 8051. Questi registri sono chiamati MMR (registri mappati in memoria). Durante il reset, tutte le RAMs interne e tutti i registri sono resettati al valore 0x00, lo spazio XDATA dell' 8051 è uno stato casuale perché il circuito di reset interno non resetta la memoria esterna. La documentazione non riporta quanto detto perché è dato per scontato. Ho provato a resettare i registri nella procedura di startup. Il problema non si presentava più. Ho capito quindi che quello era la causa principale. Essendo il contenuto della memoria indeterminato, il comportamento del sistema dopo il reset era imprevedibile. Infine,risolto il problema il progetto è stato approvato dal QA.
Con l'aumentare delle periferiche integrate e quindi i relativi registri, sempre più registri devono essere assegnati nello spazio XDATA. E questi registri contengono valori indeterminati dopo il reset del sistema.
Quindi i progettisti li devono resettare esplicitamente all'inizializzazione del sistema.
Dopo questo progetto, ho riveduto tutti i sorgenti del progetto. Tutti i registri e le variabili nella XDATA sono stati scritti con zero o con dei loro valori di default. A volte la scrittura nello spazio XDATA dell' 8051 e' lenta. Come alternativa, i progettisti possono lasciarla inalterata, pero devono esseri sicuri che la memoria non influenzerà le prestazioni del sistema.
Non importa quale linguaggio sia utilizzato, C o il linguaggio assembly, è sempre buona norma dichiarare esplicitamente i registri e le variabile statiche nella XDATA con valori di default, invece di lasciarli non inizializzati.
// variable declare
static unsigned int XDATA var1;
static unsigned int XDATA var2 = 0x80;// variable initialization, which should be called from system initialization
void module_init (void)
{
var1 = 0x00;
....
}
// normal functions
void module_update(void)
{
var1 = 0x80;
var2 = 0x00;
}
Se alcuni registri devono essere resettati non appena il sistema termina il reset dal power on (POR), codice integrativo di inizializzazione può essere scritto nella routine di start up. Per un compilatore C (Keil) 8051, si può aprire startup.a51 per aggiungere il codice assembly richiesto.