Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Curioso allineamento della memoria in C

Linguaggi e sistemi

Moderatori: Foto UtentePaolino, Foto UtenteMassimoB, Foto Utentefairyvilje

0
voti

[1] Curioso allineamento della memoria in C

Messaggioda Foto Utenteboiler » 17 dic 2018, 17:00

Ciao a tutti

Mi è appena successa una cosa che mi sembra strana. Volevo sentire cosa ne pensate.

Il target è un Cortex-M3, quindi architettura a 32 bit.
Il compiler è quello di IAR, ma questo dovrebbe essere irrilevante.

Ho una struct in RAM:
Codice: Seleziona tutto
typedef struct CalWriteStruct {
    uint16_t    zero;
    uint16_t    zeroOffset;
    float       zeroGain;

    uint16_t    fullscale;
    uint16_t    fullscaleOffset;
    float       fullscaleGain;

    uint32_t    timestamp;

    uint16_t    checksum;

    bool        dataReadyZero;
    bool        dataReadyFullscale;
}CalWriteStruct;


È allineata a 32 bit, quindi fino e compreso l'elemento "checksum" non dovrebbe esserci padding.

Ad un certo punto trasferisco questa struttura (o perlomeno i primi 22 bytes, quindi fino a e compresa la checksum) in una EEPROM esterna al microcontroller. Questo il codice:

Codice: Seleziona tutto
uint8_t* dataBuffer = (uint8_t*) &CalData;

for (ii = 0; ii < 22; ii++)
{
    resultCode = preampEepromWrite(ii, dataBuffer[ii], CALMEM_PROTECTION_KEY);
    if (resultCode != 0)
        break;
}

La funzione uint8_t preampEepromWrite(uint8_t address, uint8_t data, uint16_t key) scrive all'indirizzo address il valore data.

Se dopo quest'operazione leggo il contenuto dell'EEPROM ottengo roba con l'endianness ribaltata.
Per esempio se il primo valore della struct è 18432, all'indirizzo 0 leggo 0x00 e all'indirizzo 1 leggo 0x48.

Beh, la cosa non mi irrita piú di tanto...

Ma poi ad un certo punto voglio riportare il contenuto della EEPROM nella RAM:

Codice: Seleziona tutto
preampEepromRead(0, 0x16, (uint8_t*) &CalData);


Qui leggo 0x16 (22) bytes a partire dall'indirizzo 0 e li metto in memoria all'indirizzo della struct.

E a questo punto ho l'endianness invertita anche nella RAM ?%
Così che il primo valore (0x0048) interpretato come uint16_t diventa 72 e non 18432...

Qualcuno vede dove sbaglio?

Boiler
Avatar utente
Foto Utenteboiler
14,4k 4 7 13
G.Master EY
G.Master EY
 
Messaggi: 2447
Iscritto il: 9 nov 2011, 12:27

0
voti

[2] Re: Curioso allineamento della memoria in C

Messaggioda Foto UtenteIlGuru » 17 dic 2018, 17:11

Ma poi quando accedi ai membri della struct dereferenziando il puntatore a quella in ram ti trovi i dati giusti o no?
Di sicuro non è il ciclo for a ribaltare i byte visto che li legge uno alla volta come una stringa.

Com'è fatta preampEepromWrite ?
\Gamma\nu\tilde{\omega}\theta\i\ \sigma\epsilon\alpha\upsilon\tau\acute{o}\nu
Avatar utente
Foto UtenteIlGuru
3.920 1 9 13
Master
Master
 
Messaggi: 1241
Iscritto il: 31 lug 2015, 23:32

0
voti

[3] Re: Curioso allineamento della memoria in C

Messaggioda Foto Utenteboiler » 17 dic 2018, 17:15

IlGuru ha scritto:Ma poi quando accedi ai membri della struct dereferenziando il puntatore a quella in ram ti trovi i dati giusti o no?


No, è questo il problema.

Boiler
Avatar utente
Foto Utenteboiler
14,4k 4 7 13
G.Master EY
G.Master EY
 
Messaggi: 2447
Iscritto il: 9 nov 2011, 12:27

0
voti

[4] Re: Curioso allineamento della memoria in C

Messaggioda Foto UtenteIlGuru » 17 dic 2018, 17:23

Non è che preampEepromRead tiene già conto dell' endianess ribaltata e quindi quando tu inserisci i byte in quel modo, stai fregando la funzione che li andrà a leggere?
\Gamma\nu\tilde{\omega}\theta\i\ \sigma\epsilon\alpha\upsilon\tau\acute{o}\nu
Avatar utente
Foto UtenteIlGuru
3.920 1 9 13
Master
Master
 
Messaggi: 1241
Iscritto il: 31 lug 2015, 23:32

0
voti

[5] Re: Curioso allineamento della memoria in C

Messaggioda Foto Utenteboiler » 17 dic 2018, 17:31

Np, quella funzione verifica semplicemente che l'handle statico dell'interfaccia I2C non sia NULL, dopodiché chiama la funzione di lettura del driver I2C (funzione fornita dal produttore del micro).

Ho attaccato l'oscilloscopio al bus I2C... stay tuned... sembra roba interessante ;-)

Boiler
Avatar utente
Foto Utenteboiler
14,4k 4 7 13
G.Master EY
G.Master EY
 
Messaggi: 2447
Iscritto il: 9 nov 2011, 12:27

0
voti

[6] Re: Curioso allineamento della memoria in C

Messaggioda Foto Utenteboiler » 17 dic 2018, 17:50

Ho modificato il codice in modo che proprio prima del loop for venga eseguito quanto segue:
Codice: Seleziona tutto
CalData.zero = 0x0011;
CalData.zeroOffset = 0x2233;
CalData.zeroGain = 853.601;    // = 0x44556677
CalData.fullscale = 0x0011;
CalData.fullscaleOffset = 0x2233;
CalData.fullscaleGain = 853.601;     // = 0x44556677
CalData.timestamp = 0xAABBCCDD;
CalData.checksum = 0xEEFF;


Sul bus succede questo:
writecal1.png


Dalla tabella si vede che i bytes che compongono l'uint16_t sono invertiti.
È effettivamente quello che riscontro leggendo l'EEPROM byte per byte.
Questa deve essere l'endianness come è utilizzata nella RAM.

Adesso vedo di scoprire cosa succede in scrittura.

Boiler
Avatar utente
Foto Utenteboiler
14,4k 4 7 13
G.Master EY
G.Master EY
 
Messaggi: 2447
Iscritto il: 9 nov 2011, 12:27

0
voti

[7] Re: Curioso allineamento della memoria in C

Messaggioda Foto UtenteIlGuru » 17 dic 2018, 18:00

Bisogna vedere il segnale sul bus quando i byte tornano indietro dalla eprom durante la lettura.
Cioè come vengono impacchettati i byte nella struct dal compilatore ha poca importanza, potrebbero anche essere tutti mischiati per quello, ma per funzionare le due aree in memoria e nella eprom devono essere identiche byte a byte, altrimenti occorre qualcosa che faccia la traduzione.
\Gamma\nu\tilde{\omega}\theta\i\ \sigma\epsilon\alpha\upsilon\tau\acute{o}\nu
Avatar utente
Foto UtenteIlGuru
3.920 1 9 13
Master
Master
 
Messaggi: 1241
Iscritto il: 31 lug 2015, 23:32

0
voti

[8] Re: Curioso allineamento della memoria in C

Messaggioda Foto Utenteboiler » 17 dic 2018, 18:06

IlGuru ha scritto:Bisogna vedere il segnale sul bus quando i byte tornano indietro dalla eprom durante la lettura.

L'ho verificato ed è uguale a quello in scrittura (nell'ordine 0x11 0x00 0x33 0x22 ...). Non mi sorprende, perché qui do esplicitamente degli indirizzi all'EEPROM e la larghezza della memoria è 8 bit... c'è poco da scombussolare ;-)
potrebbero anche essere tutti mischiati per quello

Beh, no, questo mi causerebbe dei problemi, ma sono abbastanza sicuro che lo standard di C richieda che siano nell'ordine in cui sono stati dichiarate le variabili.

Boiler
Avatar utente
Foto Utenteboiler
14,4k 4 7 13
G.Master EY
G.Master EY
 
Messaggi: 2447
Iscritto il: 9 nov 2011, 12:27

0
voti

[9] Re: Curioso allineamento della memoria in C

Messaggioda Foto Utenteluxinterior » 17 dic 2018, 18:13

Servirebbero almeno le sigle dei componenti per dare una risposta che vada oltre le ipotesi.

Io scommetto sulla eeprom non è una 8bitxqualcosa ma una 16bitxqualcosa

Ma come ho detto è tirare a indovinare con queste informaizoni

Legog il tuo ultimo messaggio dopo aver scritto:Ipotesi sbagliata peccato!
Avatar utente
Foto Utenteluxinterior
2.249 2 4 8
Expert EY
Expert EY
 
Messaggi: 1259
Iscritto il: 6 gen 2016, 17:48

0
voti

[10] Re: Curioso allineamento della memoria in C

Messaggioda Foto Utenteboiler » 17 dic 2018, 18:30

La risposta piú semplice è spesso quella giusta (rasoio di Occam).
Il programmatore (un certo Foto Utenteboiler) è rincoglionito.
Dopo aver testato tutto con dati sintetici, anche quello che c'è in RAM nella struct dopo aver reimportato i dati sembra corretto.

O i dati usati per il test erano fallati o c'è un errore in una formula da qualche parte...

Grazie comunque perché un dialogo così aiuta... da solo ci avrei probabilmente messo di piú...

Boiler

P.S.: ancora prima di spedire... trovato il problema... un cast sbagliato #-o
Avatar utente
Foto Utenteboiler
14,4k 4 7 13
G.Master EY
G.Master EY
 
Messaggi: 2447
Iscritto il: 9 nov 2011, 12:27

Prossimo

Torna a PC e informatica

Chi c’è in linea

Visitano il forum: Nessuno e 4 ospiti