I have an ATMega328 and I'm using the <avr/eeprom.h> functions to use the inbuilt EEPROM.
I can use the EEPROM correctly but I don't understand the function arguments I pass to the EEPROM functions.
For example, to write different types of data I can use
void eeprom_update_byte (uint8_t *addr, uint8_t value);
void eeprom_update_word (uint16_t *addr, uint16_t value);
void eeprom_update_dword (uint32_t *addr, uint32_t value);
void eeprom_update_float (float *addr, float value);
But why does the pointer type for the address (the addr parameter) change depending on the function used? If addr just points to a valid EEPROM address why is the type different in each function?
Also, the use of the void * in the EEPROM function below is confusing me. I understand that a void * can point to any address, so I'm assuming the function simply writes byte by byte the data in src but I'm unsure if this is correct?
void eeprom_update_block (const void *src, void *dst, size_t n);
The first four functions listed define the type of object being written. So internally the function might look like this:
void eeprom_update_float (float *addr, float value)
{
*addr = value;
}
This offers type safety benefits (e.g. cannot write a float into a uint16_t) by ensuring that the destination pointer is the same as the source variable.
The final version void eeprom_update_block() simply writes an arbitrary block of memory to a given address. It probably uses something like memcpy underneath:
void eeprom_update_block (const void *src, void *dst, size_t n)
{
memcpy(dst, src, n);
}
This version of the function doesn't have any type safety advantages, but can be used to write non-trivial data into memory. For example, a struct can be written like this:
eeprom_update_block(&myStruct, dst, sizeof(myStruct));
There is no technical reason behind taking type-specific pointers in the first four APIs. These functions could be redefined with void* without the need to recompile code relying on them:
void eeprom_update_byte (void *addr, uint8_t value);
void eeprom_update_word (void *addr, uint16_t value);
void eeprom_update_dword (void *addr, uint32_t value);
void eeprom_update_float (void *addr, float value);
There is no special alignment requirements in EEPROM, so my guess is that Atmel team used type-specific pointers for aesthetic reasons.
Also, the use of the
void*in the EEPROM function below is confusing me.
eeprom_update_block is an untyped version of type specific eeprom_update_XXX functions. Note that since the second parameter is void*, a third parameter specifying block size is now required, while eeprom_update_XXX functions imply the size from the type of their argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With