https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87373
Murat Ursavaş <murat.ursavas at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |UNCONFIRMED Resolution|INVALID |--- --- Comment #34 from Murat Ursavaş <murat.ursavas at gmail dot com> --- I think I've got what's going on. (I know this case turned to a monologue, but I would like to improve it for the future search references. In ARM architecture we have one simple linear address space for everything, flash, RAM and other hardware like peripherals. This makes many things quite easy. If you would like to setup a USART, you just write some information on this address space and you get what you want, like in this case. But If you are like me, trying to make everything deterministic, you may want to enable packed-structs. No problem with that. GCC takes care of the rest. It can access the RAM unaligned anyway as default. But, one thing can stay under the radar. We see peripheral registers as usual RAM addresses, but they are not. They may have limitations like no unaligned access. In this case with GCC 4.9.3, if I access to the register it uses this: ldr r3,[pc,#0x4c] ldr r2,[r3,#0x54] movs r2,#0x0 orr r2,r2,#0xb str r2,[r3,#0x54] ;<<<< Important instruction This part easily sets a 32bit register and everything works as expected. But after GCC 5+, It uses byte by byte access an uses the instructions below; ldr r3,[pc,#0x70] ldrb.w r2,[r3,#0x54] movs r2,#0x0 orr r2,r2,#0xb strb.w r2,[r3,#0x54] ;<<<< Important instruction ldrb.w r2,[r3,#0x55] movs r2,#0x0 strb.w r2,[r3,#0x55] ldrb.w r2,[r3,#0x56] movs r2,#0x0 strb.w r2,[r3,#0x56] ldrb.w r2,[r3,#0x57] movs r2,#0x0 strb.w r2,[r3,#0x57] There is nothing wrong, if it was a normal RAM location. It would set the register as 0x0000000b. But since this is a peripheral location, and has to be accessed as aligned, it takes just the first strb.w instruction into consideration, and leaves further ones useless. 0 - 7bits are OK, but 8-31 bits are left to decide by entropy. In my case the entropy wants to move the physical pins to a different location. I'm not sure whether this is a GCC regression, or must be taken care by the hardware manufacturer, but this is my conclusion at the end. So what will be my workaround; Project wide packed structs are dangerous, I'll remove it from the project settings and limit it down to necessary structs, leaving others relaxed. This should make the peripheral access aligned. P.S: I'm reopening this record for one final evaluation by the GNU team. From my perspective, this looks like a regression, but it's up to you guys.