Domanda

Sto lavorando a un progetto C incorporato che dipende da alcuni HW esterni. Vorrei cancellare il codice accedendo a queste parti, in modo da poter simulare il sistema senza usare alcun HW. Fino ad ora ho usato alcune macro, ma questo mi costringe a cambiare un po 'il mio codice di produzione, che vorrei evitare.

Esempio:

stub.h
#ifdef _STUB_HW
#define STUB_HW(name) Stub_##name
#else /*_STUB_HW*/
#define STUB_HW(name) name
#endif /*_STUB_HW*/

my_hw.c
WORD STUB_HW(clear_RX_TX)()
{ /* clear my rx/tx buffer on target HW */ }

test_my_hw.c
#ifdef _STUB_HW
WORD clear_RX_TX()
{ /* simulate clear rx/tx buffer on target HW */ }

Con questo codice posso attivare / disattivare lo stub con il tag preprocessore _STUB_HW

C'è un modo per realizzarlo senza dover cambiare il mio codice prodotto ed evitare molti ifdefs. E non mescolerò codice prod e test nello stesso file se posso evitarlo. Non mi interessa l'aspetto del codice di prova finché riesco a tenere il più possibile fuori dal codice di produzione.

Modifica:

Sarebbe bello se fosse possibile selezionare / rinominare le funzioni senza sostituire l'intero file. Come prendere tutte le funzioni a partire da nRF _ ## e dare quindi un nuovo nome e quindi inserire test_nRF _ ## in nRF _ ## se è possibile

È stato utile?

Soluzione

Faccio solo due file ActualDriver.c e StubDriver.c contenenti esattamente gli stessi nomi di funzione. Creando due build che collegano il codice di produzione a diversi oggetti non si verificano conflitti di denominazione. In questo modo il codice di produzione non contiene test o codice condizionale.

Altri suggerimenti

Come ha detto Gerhard, usa un file header comune " driver.h " e file separati di implementazione del livello hardware contenenti le funzioni effettive e stub.

In eclipse, ho due obiettivi e escludo dalla build " il file driver.c che non deve essere utilizzato e assicurarsi che sia incluso quello corretto nella build. Eclipse quindi genera il makefile al momento della creazione.

Un altro problema da sottolineare è assicurarsi di definire numeri interi di dimensioni fisse in modo che il codice si comporti allo stesso modo da una prospettiva di overflow. (Anche se dal tuo esempio di codice posso vedere che lo stai facendo.)

Sono d'accordo con quanto sopra. La soluzione standard a questo è quella di definire una serie astratta opaca di chiamate di funzione che sono il "driver" a hw, quindi chiamalo nel programma principale. Quindi fornire due diverse implementazioni di driver, una per hw, una per sw. La variante sw simulerà l'effetto IO di hw in un modo appropriato.

Nota che se l'obiettivo è ad un livello inferiore, ovvero scrivere un codice in cui ogni accesso hardware deve essere simulato anziché intere funzioni, potrebbe essere un po 'più complicato. Ma qui, diverse " write_to_memory " e " read_from_memory " funzioni (o macro, se la velocità sul bersaglio è essenziale) potrebbe essere definita.

In entrambi i casi non è necessario modificare i nomi delle funzioni, basta avere due diversi file batch, creare file o target di generazione IDE (a seconda degli strumenti che si stanno utilizzando).

Infine, in molti casi una soluzione tecnica migliore è quella di cercare un simulatore di sistema di destinazione completo, come Qemu , Simics , SystemC , CoWare , VaST o simile. Ciò consente di eseguire sempre lo stesso codice e invece di creare un modello di hardware che funzioni come l'hardware reale dal punto di vista del software. Richiede un investimento iniziale molto più ampio, ma per molti progetti vale la pena. Fondamentalmente si sbarazza del brutto problema di avere build diverse per target e host e si assicura di utilizzare sempre il compilatore incrociato con le opzioni di build di distribuzione. Si noti che molte suite di compilatori incorporati sono dotate di alcune funzionalità di simulazione di base integrate.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top