Search code examples
carmc99c11

Bitfield write size


I have a volatile struct/bitfield for a memory mapped register on an ARM processor. The particular peripheral must be accessed by words.

struct
{
  unsigned field1 : 1;
  unsigned field2 : 3;
  unsigned field3 : 4;
  unsigned : 24;
} volatile my_variable __attribute__((section(".bss.my_periph")));

ARM Compiler V5 generates 32-bit accesses. ARM Compiler V6 is smart enough to see that only field2 has changed and generates 8-bit accesses. These 8-bit accesses break the world.

Is there a way to ensure that accesses are done by word?

I expect that something like this would work, but I would rather avoid the union:

union
{
  struct
  {
    unsigned field1 : 1;
    unsigned field2 : 3;
    unsigned field3 : 4;
    unsigned : 24;
  } fields;
  unsigned word;
} volatile my_variable __attribute__((section(".bss.my_periph")));

Solution

  • I found that the following works to force word-wise reads and writes.

    Structure:

    union my_type
    {
      struct
      {
        unsigned field1 : 1;
        unsigned field2 : 3;
        unsigned field3 : 4;
        unsigned : 24;
      } fields;
      unsigned word;
    } volatile my_variable __attribute__((section(".bss.my_periph")));
    

    Read:

    union my_type my_type;
    my_type.word = my_variable.word;
    return my_type.field2;
    

    Write:

    union my_type my_type = {0};
    my_type.field3 = 5;
    my_variable.word = my_type.word;
    

    Read, Modify, Write:

    union my_type my_type;
    my_type.word = my_variable.word;
    mytype.field2 = 7;
    my_variable.word = my_type.word;