Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22061

What makes the difference between direct and indirect access to volatile objects in C?

$
0
0

I am dealing with hardware registers on an STM32 controller.

I have defined a bunch of structures like the following:

#define PACKED __attribute__ ((packed))#define ASSERT(cond) _Static_assert(cond, #cond)typedef union {    struct PACKED {        uint16_t value;        uint16_t reserved;    };    uint32_t bits;} LOL_LPTIM_16_BIT_VALUE;ASSERT(sizeof(LOL_LPTIM_16_BIT_VALUE) == sizeof(uint32_t)); // OK

Then, I have a structure like this:

typedef struct PACKED {    // ...    volatile LOL_LPTIM_16_BIT_VALUE autoreload;    // ...} LOL_LPTIM;

The offset of the autoreload field in the structure agrees with the documentation. I also have the following objects available (following the documentation and header files provided by ST):

#define LOL_LPTIM1_BASE (LOL_APB1PERIPH_BASE + 0x7C00UL)#define LOL_LPTIM2_BASE (LOL_APB1PERIPH_BASE + 0x9400UL)#define LOL_LPTIM1 ((volatile LOL_LPTIM *) LOL_LPTIM1_BASE)#define LOL_LPTIM2 ((volatile LOL_LPTIM *) LOL_LPTIM2_BASE)

I have a static const structure that stores these pointers:

static const struct {    volatile LOL_LPTIM *lptim;} timer[2] = {    { .lptim = LPTIM1 },    { .lptim = LPTIM2 }}

Now, when I write

*(uint32_t *) &(timer[0].lptim->autoreload.bits) = 0xffff;

or

*(uint16_t *) &(timer[0].lptim->autoreload.value) = 0xffff;

the code works correctly, but when I write

timer[0].lptim->autoreload.bits = 0xffff;

(which should be exactly equivalent) or

timer[0].lptim->autoreload.value = 0xffff;

then it does not work as expected - it works differently than the indirected variant, and the value of the autoreload register doesn't seem to be set properly (the perpipherals behave differently).

What could be a possible reason of this discrepancy?

Godbolt shows that the compiler generates very different set of operations for these two cases: https://godbolt.org/z/cno9yf

They get more similar when the indirect version is changed to

*(volatile uint32_t *) &(timer[0].lptim->autoreload.bits) = 0xffff;

(there's many more instructions in the output)


Viewing all articles
Browse latest Browse all 22061

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>