2013-08-23 17 views
5

Sto lavorando con un compilatore C incorporato (chip ARM cortex-m3) e sembra inizializzare il valore sbagliato su una struttura. Perché succede? Se si tratta di un problema di allineamento, il compilatore non dovrebbe sapere di allineare un int32u a un limite di 4 byte?Perché il compilatore inizia questa variabile al valore errato? È un problema di allineamento?

Nota: il printf emette semplicemente byte dalla porta seriale. Non esiste alcuna implementazione stdio.h su questo chip.

typedef struct 
{ 
    int32u startTime; 
    int16u length; 
    int32u offTime; 
} Cycle; 

Cycle cycle = 
{ 
    315618000, 
    1200, 
    0 
}; 


void init() 
{ 
    printf("\r\nInitialized! Cycle Start: %d", cycle.startTime); 

    cycle.startTime = 315618000; 
    cycle.length = 1200; 

    printf(" Cycle Start: %d", cycle.startTime); 

} 

uscita: inizializzato! Cycle Start: 631237200 Cycle Start: 315618000

Nota:: Questo non è un problema printf. Il debugger verifica anche il valore in memoria come 631237200.

+0

'"% d "' richiede un argomento 'int'.Probabilmente funziona se 'int' è a 32 bit, ma per sicurezza prova a cambiare il formato da' "% d" 'a' "% lu" 'e lancia esplicitamente l'argomento a' unsigned long'. –

+2

Il tuo documento del compilatore 'void main()' come definizione corretta per 'main'? Hai '#include '? –

+1

@KeithThompson: Anche se sono completamente d'accordo sul fatto che '% d' è sbagliato, dubito che questo riguardi gli specificatori di conversione (o anche le dimensioni integer), poiché sembra funzionare per il secondo' printf() '. – alk

risposta

1

In alcuni sistemi embedded, l'inizializzazione statico non è impostato per avvenire automaticamente. Questo va contro le specifiche C, ma a volte è così. Si noti che questo può essere vero per entrambi i segmenti di dati e bss, ad esempio si potrebbe scoprire che la statistica non inizializzata NON può essere inizializzata a zero.

La soluzione a questo è, purtroppo, specifica del sistema. È possibile trovare qualcosa nella documentazione del sistema di compilazione che consente di richiamare l'inizializzazione degli elementi statici.

+0

Normalmente ciò significa che il compilatore C si aspetta che alcuni componenti runtime azzerino il file .bss e caricino i segmenti di dati corretti (const) nella posizione corretta in memoria. Mancando di un tale runtime, dovrai scriverlo da solo. (O hai semplicemente incasinato durante la creazione della mappa del linker, o scartato le sezioni quando si trasformava il file binario da avviare, egduring objcopy da elf in un file .bin) – nos

+0

Per il segmento dati, il compilatore genera funzioni di inizializzazione per l'inizializzazione statica. Questi devono essere chiamati nel CRT (prima del main). Questo può essere utile. http://gcc.gnu.org/onlinedocs/gccint/Initialization.html – Ziffusion

1

[Modifica] Il mio suggerito sotto quella sizeof (int) == 2 è probabile non il numero come " Cycle Start: %d", cycle.startTime stampa rapidamente valori> 64k. Sospetto un problema di imbottitura. Ma si applicano le raccomandazioni più basse su printf(), anche se non spiegano questo problema.


L'inizializzazione cycle in effetti ha una cycle.startTime = 315618000. La tua dimensione int/unsigned è probabile 2, quindi l'overflow di inizializzazione. Invece:

Cycle cycle = { 
    315618000LU, 
    1200, 
    0 
    }; 

tuo printf() dovrebbe anche usare l'identificatore di formato di corrispondenza per uint32_t

#include <inttypes.h> 
printf("Cycle Start: %" PRIu32 "\n", cycle.startTime); 
printf("Length  : %" PRIu16 "\n", cycle.length); 
+1

L'OP potrebbe essere così gentile e commentare questa risposta, poiché sono davvero curioso di sapere se l'appendice 'LU' ha funzionato. – alk

+0

@alk I _think_ che dal momento che la risposta accettata implica che l'inizializzazione statica non è avvenuta, ciò che è stato stampato è stato ciò che è accaduto in 'cycle.startTime' non inizializzato, forse dalle esecuzioni precedenti. Ah, le debolezze del mondo incorporato. – chux

0

Probabilmente è possibile scoprire cosa sta accadendo visualizzando il codice assembly. Non so se il tuo compilatore è GCC. Se è il flag -S dovrebbe produrre un file assembly chiamato come file di input ma con estensione .s.

Con questo si dovrebbe essere in grado di visualizzare quali valori vengono assegnati alla variabile di struttura globale.

Un'altra cosa che potrebbe essere errata è la funzione printf. Se non si è utilizzato un prototipo di funzione che lo dichiara come una funzione vararg come int printf(const char *fmt, ...), la chiamata verrà eseguita in modo errato.

Su almeno un'architettura che conosco, tutte le voci vararg hanno l'allineamento massimo perché la funzione non sa cosa sta ottenendo. Le funzioni normali passano i valori sullo stack con l'allineamento del tipo dichiarato. Se printf non ha un prototipo, il linguaggio C assumerà tutti gli argomenti int e cercherà di passarli in quel modo. Nel frattempo la funzione printf cercherà di estrarre argomenti come vararg e potrebbe facilmente scivolare di qualche byte qua e là.

Problemi correlati