Quali strumenti o standard possono essere utilizzati per migliorare l'affidabilità del codice C incorporato?


9

Generalmente programma PIC in C, di solito per convertitori in modalità commutata. Ho sentito parlare di vari strumenti e standard di analisi statica come MISRA C che può essere utilizzato per migliorare l'affidabilità del codice. Mi piacerebbe saperne di più Quali standard o strumenti potrebbero essere appropriati per il mio contesto?


1
Quanto sei impostato sul linguaggio C?
Brian Drummond,

1
Potrei essere persuaso a passare a qualcos'altro se ci fosse un ottimo caso per farlo. Ma dovrebbe essere un ottimo caso.
Stephen Collings,

"Un ottimo caso" per il passaggio da C non può essere fatto rapidamente, e per il PIC, forse non lo è ancora affatto. Per AVR, ARM o MSP430, Ada varrebbe la pena dare un'occhiata seria (nonostante la negatività che attrae, come puoi vedere!) E per alta affidabilità, SPARK vale la pena dare un'occhiata.
Brian Drummond,

Potresti trovare questi interessanti come informazioni di base: SPARK vs MISRA-C spark-2014.org/entries/detail/… e questo case study in corso: spark-2014.org/uploads/Nosegearpaper_1.pdf
Brian Drummond,

Potrebbe essere il momento migliore per investire in un caso per passare dal PIC a qualcosa di moderno ... Soprattutto se si sta progettando il tipo di sistemi mission-critical a cui inizialmente erano destinati MISRA e SPARK.
Lundin,

Risposte:


11

La convalida del codice incorporato è complicata, soprattutto quando si tratta di parti a risorse limitate come i PIC. Spesso non si ha il lusso di codificare nei casi di test a causa dei vincoli di memnry della parte e della programmazione spesso "in tempo reale" eseguita su questo tipo di dispositivi.

Ecco alcune delle mie linee guida:

  1. Scrivi una specifica se non ce n'è una: se non stai codificando una specifica, documenta ciò che dovrebbe essere il tuo codice, quali sono gli input validi, quali sono gli output previsti, quanto tempo dovrebbe impiegare ogni routine, cosa può e non può ottenere ostruito, ecc. - una teoria dell'operazione, diagrammi di flusso, tutto è meglio di niente.

  2. Commenta il tuo codice: solo perché qualcosa è ovvio per te non significa che sia ovvio (o corretto) per qualcun altro. I commenti in linguaggio chiaro sono necessari sia per la revisione che per la manutenibilità del codice.

  3. Codice difensivo: non includere semplicemente il codice per input normali. Gestisci input mancanti, input fuori portata, overflow matematici, ecc. - più angoli coprirai con la progettazione del tuo codice, minore sarà il grado di libertà che il codice avrà quando verrà distribuito.

  4. Usa strumenti di analisi statica: può essere umiliante quanti strumenti di bug come PC-lint possono trovare nel tuo codice. Considera un'analisi statica pulita come un buon punto di partenza per test seri.

  5. Le revisioni tra pari sono essenziali: il codice deve essere pulito e ben documentato in modo da poter essere esaminato in modo efficiente da una parte indipendente. Controlla il tuo ego alla porta e considera seriamente qualsiasi critica o suggerimento fatto.

  6. Il test è essenziale: è necessario eseguire la propria convalida e disporre di una convalida indipendente del codice. Altri possono violare il codice in modi che non puoi immaginare. Prova ogni condizione valida e ogni condizione non valida che ti viene in mente. Usa PRNG e inserisci i dati della spazzatura. Fai tutto il possibile per rompere le cose, quindi ripara e riprova. Se sei fortunato, sarai in grado di eseguire il codice in modalità debug e sbirciare registri e variabili; in caso contrario, dovrai essere furbo e attivare i LED / i segnali digitali per avere un'idea dello stato del tuo dispositivo. Fai tutto il necessario per ottenere il feedback di cui hai bisogno.

  7. Guarda sotto il cofano: non aver paura di guardare il codice macchina generato dal tuo compilatore C. Potresti (troverai?) Luoghi in cui il tuo bellissimo codice C è esploso in decine se non centinaia di operazioni, dove qualcosa che dovrebbe essere sicuro (dal momento che è solo una riga di codice, giusto?) Impiega così tanto tempo per eseguire più interruzioni hanno licenziato e invalidato le condizioni. Se qualcosa diventa orribilmente inefficiente, riformattalo e riprova.


+1 Tutti i suoni consigliano. Mi aspetto che qualsiasi sviluppatore di firmware professionale sorrida e annuisca semplicemente leggendo questo.
Lundin,

2
Un aspetto importante delle revisioni tra pari è che la revisione riguarda il codice, non il programmatore. Se analizzi il tuo codice con termini come "prima lo faccio, poi lo faccio", probabilmente sei nei guai. "Prima il codice fa questo, poi lo fa" è il modo giusto di pensarci. E lo stesso vale per i revisori: non "perché l'hai fatto?", Ma "perché il codice lo fa?".
Pete Becker,

Si potrebbe anche considerare l'aggiunta di: 1. Uso del controllo della complessità ciclomatica 2. Software di controllo della versione
AlphaGoku

4

La maggior parte delle stesse tecniche per la creazione di software affidabile su un PC sono applicabili anche allo sviluppo integrato. È utile separare gli algoritmi dal codice specifico dell'hardware e testarli separatamente con unit test, simulazioni, analisi statiche e strumenti come Valgrind. In questo modo c'è molto meno codice che viene testato solo sull'hardware.

Non abbandonerei C. Mentre lingue come Ada possono offrire alcune garanzie minori, è facile cadere nella trappola di pensare che la lingua promette più di quanto non faccia realmente.


Valgrid potrebbe essere un po 'più rilevante per PC che per un MCU a 8 bit, tuttavia :)
Lundin,

Sfortunatamente alcune tecniche per la creazione di un buon software a livello di PC sono molto inadatte ai piccoli micros, e alcune pratiche considerate Bad And Wrong in PC sono perfettamente accettabili in un ambiente embedded.
John U,

3

MISRA-C è davvero molto utile per migliorare la qualità del codice generale e minimizzare i bug. Assicurati solo di leggere e comprendere ogni regola, la maggior parte di essi è buona, ma alcuni di essi non hanno alcun senso.

Un avvertimento qui. Il documento MISRA presuppone che il lettore sia qualcuno con una vasta conoscenza del linguaggio C. Se non hai un tale veterano C indurito nella tua squadra, ma decidi di ottenere un analizzatore statico e quindi seguire ciecamente ogni avvertimento dato, molto probabilmente si tradurrà in una qualità inferiore codice di , poiché potresti ridurre la leggibilità e introdurre bug per caso. L'ho visto accadere molte volte, convertire il codice in conformità MISRA non è cosa da poco.

Sono disponibili due versioni del documento MISRA-C. MISRA-C: 2004, che è ancora l'attuale standard di fatto del settore embedded. O il nuovo MISRA-C: 2012 che supporta lo standard C99. Se non hai mai usato MISRA-C prima, ti consiglierei di implementare quest'ultimo.

Tenere presente, tuttavia, che i fornitori di utensili di solito si riferiscono a MISRA-C: 2004 quando affermano di disporre di un controllo MISRA (a volte fanno persino riferimento alla versione obsoleta MISRA-C: 1998). Per quanto ne so, il supporto degli strumenti per MISRA-C: 2012 è ancora limitato. Penso che solo alcuni analizzatori statici lo abbiano implementato finora: Klocwork, LDRA, PRQA e Polyspace. Potrebbe essere di più, ma devi assolutamente verificare quale versione di MISRA supporta.

Prima di decidere, puoi ovviamente iniziare leggendo il documento MISRA e vedere cosa comporta. Può essere acquistato per £ 10 da misra.org , abbastanza conveniente rispetto ai prezzi degli standard ISO.


1

Mathworks (la gente MATLAB) ha uno strumento di analisi del codice statico chiamato Polyspace .

Oltre all'analisi statica del codice, a lanugine e simili, suggerirei un'attenta definizione e progettazione delle interfacce (con un processo di revisione formale) e l'analisi della copertura del codice.

Potresti anche voler consultare le linee guida per la progettazione di codici critici per la sicurezza, incluso MISRA, ma anche gli standard UL1998 e IEC 61508.


Non consiglio di andare vicino a IEC 61508 a meno che non sia necessario. Cita software, ma manca di fonti scientifiche moderne per le sue affermazioni. Questo standard è arrivato con 30 anni di ritardo - se fosse stato rilasciato negli anni '70 come la maggior parte delle sue cosiddette "fonti", sarebbe stato utile.
Lundin,

1

Per una risposta completa a questa domanda, sopporterei l'idea di "affidabilità del codice" e penserei invece a "affidabilità del progetto", poiché il codice è solo l'espressione finale del progetto.

Quindi, inizia con i requisiti e scrivi e ispeziona quelli. Se non disponi di un documento sui requisiti, indica una riga di codice casuale e chiediti "perché è necessaria quella riga?" La necessità di qualsiasi riga di codice dovrebbe eventualmente essere riconducibile a un requisito, anche se è semplice / ovvio come "l'alimentatore deve emettere 5 V CC se l'ingresso è compreso tra 12 e 36 V CC". Un modo di pensare a questo è che se quella riga di codice non può essere ricondotta a un requisito, come fai a sapere che è il codice giusto o che è necessario?

Successivamente, verifica il tuo design. Va bene se è completamente nel codice (ad esempio, nei commenti), ma ciò rende più difficile sapere se il codice sta facendo ciò che realmente si intende. Ad esempio, il codice potrebbe avere una riga che legge output = 3 * setpoint / (4 - (current * 5)); È current == 4/5un input valido che potrebbe causare un arresto anomalo? Cosa si dovrebbe fare in questo caso per evitare la divisione per zero? Eviti del tutto l'operazione o degrada invece l'output? Avere una nota generale nel documento di progettazione su come gestire tali casi limite rende molto più semplice verificare il progetto a un livello superiore. Quindi, ora l'ispezione del codice è più semplice perché si tratta di verificare se il codice implementa correttamente tale progetto.

Oltre a ciò, l'ispezione del codice dovrebbe verificare la presenza di errori comuni che il tuo IDE non rileva (stai usando un IDE, giusto?) Come '=' quando intendevi '==', parentesi graffe mancanti che cambiano il significato di 'if ", punti e virgola dove non dovrebbero essere, ecc.

Mentre scrivo, mi viene in mente che è davvero difficile riassumere anni di formazione / esperienza sulla qualità del software in un singolo post. Scrivo codice per dispositivi medici e quanto sopra è un sommario estremamente semplificato di come lo affrontiamo.


La mia comprensione è che la parte di codice in un dispositivo medico viene testata quasi come se fosse un dispositivo separato. È preciso?
Scott Seidman,

@ScottSeidman Più probabilmente, viene testato in base ai requisiti, come indicato in questa risposta. Per ogni requisito, è necessario disporre di un modulo di codice e per ciascuno di tali moduli di codice è necessario disporre di un test. Quindi, essenzialmente, ogni requisito ha un test corrispondente e il codice è il mezzo per soddisfare il requisito. Questo tipo di tracciamento dei requisiti è pratica comune in tutti i sistemi mission-critical, molto prima che comparisse la parola d'ordine "TDD".
Lundin,

Mi riferivo specificamente alla guida della FDA, come fda.gov/downloads/RegulatoryInformation/Guidances/ucm126955.pdf Il software richiede in realtà più di quanto si possa pensare se fa parte di un dispositivo medico, a partire dalla fase di pianificazione e dai controlli di progettazione.
Scott Seidman,

Scott, non ci ho mai pensato in quel modo, ma hai ragione. I nostri addetti all'assicurazione della qualità del software verificano il software separatamente dal resto del sistema (per quanto possibile) prima di consegnarlo a un altro gruppo responsabile della verifica e della convalida del sistema.
lyndon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.