I use STM32F0 mcu with emulated EEPROM. The EEPROM takes data as EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
and returns them as EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
but my data are int16_t
. So my question is, how do I write and read signed short?
Asked
Active
Viewed 445 times
-2

muliku
- 416
- 3
- 17
2 Answers
2
Unfortunately the C language is being daft when it comes to things like hardware-related programming, such as EEPROM emulation. Therefore, the only reliable solution you can use is this:
uint16_t u16;
EE_ReadVariable(VirtAddress, &u16);
int16_t i16;
i16 = (int16_t)u16;
or alternatively:
memcpy(&i16, &u16, 2);
Anything else is unsafe and dangerous. In particular, you cannot do this:
EE_ReadVariable(VirtAddress, (uint16_t*)&i16); // BAD
Nor can you do i16 = *(int16_t*)&u16; // BAD
.
More information about why, can be found here: What is the strict aliasing rule?

Lundin
- 195,001
- 40
- 254
- 396
-
Are you suggesting we don't type cast specifically for hardware modules like EEPROM and others? Or that in general `EE_ReadVariable(VirtAddress, (uint16_t*)&i16); ` is bad? If you check out clean-flight's source code `bt = (*(__IO uint32_t *) (BKPSRAM_BASE + 4)) ;` this is done for SRAM (but not a read/write method). https://github.com/cleanflight/cleanflight/blob/master/src/main/drivers/system_stm32f7xx.c#L200 – clamentjohn Aug 10 '18 at 05:56
-
@ClamentJohn It is bad in general. But in embedded systems, you must go between different types all the time, as in the case of EEPROM drivers. This was not a problem historically, since embedded compilers relied on non-standard extensions. But with the introduction of gcc in the embedded branch, systems break left and right because they contain strict aliasing violations. – Lundin Aug 10 '18 at 06:16
-
1@ClamentJohn And yes, the "clean-flight" (whatever that is) is broken, in case the memory at those addresses contain anything else than what the compiler recognizes as either uint32_t variables or memory without a previously declared type. Upon further examination it appears to be raw addresses with no declared type, no there's no strict aliasing violation then. – Lundin Aug 10 '18 at 06:30
0
As per the application note The data is stored as 16-bit words in memory, so it's uint16_t
. That's the underlying data type that anything your store in emulated EEPROM must be. Regardless of what you store, it has to have this type.
int16_t
is guaranteed to have the same size as uint16_t
. Use an intermediary variable of type uint16_t.

Thomas Jager
- 4,836
- 2
- 16
- 30
-
can you elaborate a little please? Do you mean something like `EE_WriteVariable(VirtAddress, (uint16_t *)myData)` and then `EE_ReadVariable(VirtAddress, (int16_t *)Data)`? – muliku Aug 09 '18 at 12:33
-
3@muliku Assuming `myData` is defined like this: `int16_t myData`: The second argument to `EE_WriteVariable` is not a pointer so you need to cast it like this: `(uint16_t)myData`. The second argument to `EE_ReadVariable` expects an address of an `uint16_t` so you need to cast it like this: `(uint16_t *)&myData`. – Fiddling Bits Aug 09 '18 at 12:38
-
-1 for "cast your pointer" which will invoke undefined behavior and on gcc in particular, break the program. Similarly, the comment by @Fiddling Bits has the same strict aliasing bug. These things are important nowadays, since everyone is using gcc for embedded. – Lundin Aug 09 '18 at 13:27
-