Search code examples
carmvolatilebit-fields

volatile and non-volatile bitfields


I'm writing a code for Cortex-M0 CPU and gcc. I've the following structure:

struct {
    volatile unsigned flag1: 1;
    unsigned flag2: 1;

    unsigned foo; // something else accessed in main loop
} flags;

flag1 is read and written from both GPIO interrupt handler and main loop. flag2 is only read and written in main loop.

The ISR looks like this:

void handleIRQ(void) {
    if (!flags.flag1) {
        flags.flag1 = 1;
        // enable some hw timer
    }
}

The main loop looks like this:

for (;;) {
    // disable IRQ
    if (flags.flag1) {
        // handle IRQ
        flags.flag1 = 0;
        // access (rw) flag2 many times
    }
    // wait for interrupt, enable IRQ
}

When accessing flag2 in main loop, will the compilier optimize access to it so it won't be fetched or stored to memory every time it is read or written to in code?

It's not clear to me because to set flag1 in ISR, it will need to load whole char, set a bit and store it back.


Solution

  • The volatile flag for just one bit isn't all that meaningful - it is possibly even harmful. What the compiler might do in practice is to allocate two chunks of memory, possibly each 32 bits wide. Because the volatile flag blocks it from combining the two bits inside the same allocated area, since there is no bit-level access instruction available.

    When accessing flag2 in main loop, will the compilier optimize access to it so it won't be fetched or stored to memory every time it is read or written to in code?

    That's hard to tell, depends on how many data registers there are available. Disassemble the code and see.

    Overall, bit-fields are not recommended since they are so poorly defined by the standard. And in this case, the individual volatile bit might lead to extra memory getting allocated.

    Instead, you should do this:

    volatile bool flag1;
    bool flag2;
    

    Assuming those flags aren't part of a hardware register, in which case the code was incorrect from the start and they should both be volatile.