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
-