Often in embedded programming (but not limited to) there is a need to serialize some arbitrary struct
in order to send it over some communication channel or write t
Consider that writing to eeprom is often slower, sometimes a lot slower, than writing to normal memory, that using an intervening buffer is rarely a performance drag. I realize this goes against this comment, yet I feel it deserves consideration as it handles all other C concerns
Write a helper function that has no alignment, aliasing nor size issues
extern void write_to_eeprom(/* I'd expect const */ uint32_t *data, uint32_t len);
// Adjust N per system needs
#define BYTES_TO_EEPROM_N 16
void write_bytes_to_eeprom(const void *ptr, size_t size) {
const unsigned char *byte_ptr = ptr;
union {
uint32_t data32[BYTES_TO_EEPROM_N / sizeof (uint32_t)];
unsigned char data8[BYTES_TO_EEPROM_N];
} u;
while (size >= BYTES_TO_EEPROM_N) {
memcpy(u.data8, byte_ptr, BYTES_TO_EEPROM_N); // **
byte_ptr += BYTES_TO_EEPROM_N;
write_to_eeprom(u.data32, BYTES_TO_EEPROM_N / sizeof (uint32_t));
size -= BYTES_TO_EEPROM_N;
}
if (size > 0) {
memcpy(u.data8, byte_ptr, size);
while (size % sizeof (uint32_t)) {
u.data8[size++] = 0; // zero fill
}
write_to_eeprom(u.data32, (uint32_t) size);
}
}
// usage - very simple
write_bytes_to_eeprom(&s, sizeof s);
** Could use memcpy(u.data32, byte_ptr, BYTES_TO_EEPROM_N);
to handle @zwol issue.
Just a note I am not entirely sure but it can be that it is not always safe to cast uint8_t*
to char*
(here).
Regardless, what does the last parameter of your write function want, number of bytes to write - or number of uint32_t
elements? Let's assume later, and also assume you want to write each member of the struct to separate integer. You can do this:
uint32_t dest[4] = {0};
memcpy(buffer, &s.a, sizeof(float));
memcpy(buffer+1, &s.b, sizeof(uint8_t));
memcpy(buffer+2, &s.c, sizeof(uint32_t));
write_to_eeprom(buffer, 3 /* Nr of elements */);
If you want to copy the structure elements to the integer array consecutively - you can first copy the structure member to a byte array consecutively - and then copy the byte array to the uint32_t
array. And also pass number of bytes as last parameter which would be - sizeof(float)+sizeof(uint8_t)+sizeof(uint32_t)