This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Cortex M3 hard faults only when I step over C code

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?