I have a Cortex M3-based MCU (and I also tried this on another MCU - stm32f103, which has the same memory alignment).
I tried Keil 4 and Keil 5 with armcc compiler. I tried 3 different boards and 2 different debuggers (uLink2 and st-link). Problem exists only if I compile with -O1.
The problem looks like this. I have a function, I try to step it line by line and I get a hard fault.
The function looks like this:
bool CanHandle::sendMsg(CanMsg & msg) { bool result = false; CAN_TxMsgTypeDef txMsg; if (format == FrameFormat::EXTENDED) <...>
If I try to step over line 'bool result = false;', I get a hard fault.
But here's the interesting part. If I step over assembly - I get no fault. If I set a breakpoint on the next line and press Run - even though it shouldn't be different from stepping over - I get no fault.
Compiler produces this assembly for that bit:
351: bool result = false; 352: 353: CAN_TxMsgTypeDef txMsg; 0x08000C4E 2700 MOVS r7,#0x00 0x08000C50 7A20 LDRB r0,[r4,#0x08] 0x08000C52 2600 MOVS r6,#0x00 0x08000C54 F04F0801 MOV r8,#0x01 354: if (format == FrameFormat::EXTENDED) 355: { 356: txMsg.ID = msg.id; 357: txMsg.IDE = CAN_ID_EXT; 358: } 359: else 360: { 0x08000C58 2801 CMP r0,#0x01 0x08000C5A D02E BEQ 0x08000CBA
Any minor change to this function - making result equal true, making result volatile, moving result definition lower - produces different assembly and doesn't cause hard fault.
When I don't use debugger I get no fault.
When the fault happens, I see UNDEFINSTR flag set on one MCU and IBUSERR on stm32. PC recovered from stack shows some address 0x0804FE4C - that's in empty memory region.
I removed almost everything from my program - no PLL, no peripheral initialization.
So my question is - how can that happen? Is it a real problem or just an artifact of debugger usage?