简体   繁体   中英

Assigning unsigned short to an unsigned char bit field makes STM32F1 reset

So I came across this issue without understing why.

I'm reading an EEPROM portion of 16 bit. On the first ever read of the EEPROM, all the cells are 0xffff. This portion of memory will store a flag so, basically 1 bit.

This flag is stored into the code inside a structure as unsigned char maxM1 :1; . See below

struct s_system {
   unsigned char maxM1 :1;
}

I'm reading the EEPROM with a special function rd_word(MEMORY_ADDRESS) that returns 16bit

Now I'm assigning the return value to the maxM1 variable quoted above as

struct s_system sys;
...
...
sys.maxM1=rd_word(MEMORY_ADDRESS);

Where rd_word returns return SPI_I2S_ReceiveData(SPI2);

Now, I'm using IAR 6.50 as IDE and in debug mode it seems that the line sys.maxM1=rd_word(MEMORY_ADDRESS);makes the STM32F to reset

Now, I'm thinking it's because I'm assigning a value not compatible to the variable type of the variable but, in this case, shouldn't the compiler be reporting an error?

I haven't ever used bit fields, but did some research now. The most useful information was here:

Stackoverflow thread , Andrew's answer, which I will quote

Appendix D.4 of MISRA C:2012 is usefully titled "The essential types of bit fields"

  • For a bit-field which is implemented with an essentially Boolean type, it is essentially Boolean
  • For a bit-field which is implemented with a signed type, it is the Signed Type of Lowest Rank which is able to represent the bit field
  • For a bit-field which is implemented with a unsigned type, it is the Unsigned Type of Lowest Rank which is able to represent the
    bit field

The Unsigned Type of Lowest Rank of a single-bit unsigned integer would be uint8_t (aka unsigned char) - assuming that the tool does not interpret a single-bit as being boolean...

Further down he states that for a single-bit field you should get away with casting it to uint8_t (aka unsigned char).

My personal guess is that something goes bits up because of byte/halfword access because you don't explicitly cast your 16-bit uint.

Since the struct takes full 8 bits anyway, a conceptually simpler and safer idea might be to have a byte variable in the struct and enum or a set of defines associated with every position of every bit field in that byte, and you can do bitwise operations using those defines when writing there or reading from there, much like fiddling directly with peripheral registers. It will probably generate the same machine code, since, well, if you need to write only one bit to the byte, you kinda need to read it out, flip one bit and write it back anyway, because, you know, byte access.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM