Search code examples
cgccstm32cortex-mstm32h7

Why PC is loaded with address containing undefined instruction? - STM32H745


I have a problem enabling the MPU on the STM32H745 MCU. I wanted to just disable MPU, set region and then enable it. However, HardFault showed up. I thought it was a matter of wrong region settings. But after commenting, I noticed the problem occurs just by turning on the MPU.

Code:

static syslog_status_t setMPU_sysLog(void)
{
    [...]
    ARM_MPU_Disable();
    /* ARM_MPU_SetRegion(ARM_MPU_RBAR(0, (uint32_t)NON_CACHABLE_RAM4_D3_BASE_ADDR),
        ARM_MPU_RASR(0UL, ARM_MPU_AP_FULL, 1UL, 0UL, 0UL, 1UL, 0x00UL, ARM_MPU_REGION_SIZE_8KB)); */
    HALT_IF_DEBUGGING();
    ARM_MPU_Enable(0);
    return SYSLOG_OK;
}

I use just CMSIS API, so I check assembly and woops:

>0x80003ec <setMPU_sysLog+36>    bkpt    0x0001
  0x80003ee <setMPU_sysLog+38>    ldr     r3, [pc, #28]   ; (0x800040c <setMPU_sysLog+68>)
  0x80003f0 <setMPU_sysLog+40>    movs    r2, #1
  0x80003f2 <setMPU_sysLog+42>    str.w   r2, [r3, #148]  ; 0x94
  0x80003f6 <setMPU_sysLog+46>    ldr     r2, [r3, #36]   ; 0x24
  0x80003f8 <setMPU_sysLog+48>    orr.w   r2, r2, #65536  ; 0x10000
  0x80003fc <setMPU_sysLog+52>    str     r2, [r3, #36]   ; 0x24
  0x80003fe <setMPU_sysLog+54>    dsb     sy
  0x8000402 <setMPU_sysLog+58>    isb     sy
  0x8000406 <setMPU_sysLog+62>    movs    r0, #0
  0x8000408 <setMPU_sysLog+64>    bx      lr
  0x800040a <setMPU_sysLog+66>    nop
  0x800040c <setMPU_sysLog+68>                    ; <UNDEFINED> instruction: 0xed00e000
  0x8000410 <initSysLog>          push    {r3, lr}

Load UNDEFINED instruction to PC in 0x80003ee? What could cause this compilator(?) error? Has anyone encountered such a problem? How to start of debugging it? Additional debug information below:

0x08000398 in my_fault_handler_c (frame=0x2001ffb0) at CM7/exceptionHandlers.c:29
29        HALT_IF_DEBUGGING();
(gdb) p/a *frame
$1 = {r0 = 0xde684c0e, r1 = 0x6cefc92c, r2 = 0xed5b5cfb, r3 = 0xa3feeed1, r12 = 0xef082047, lr = 0xd7121a9e, return_address = 0xf16a13cf, xpsr = 0xf60e2caf}


Fields in SCB > HFSR:
        VECTTBL:   0  Vector table hard fault
        FORCED:    1  Forced hard fault
        DEBUG_VT:  0  Reserved for Debug use
        
Fields in SCB > CFSR_UFSR_BFSR_MMFSR:
        IACCVIOL:     1
        DACCVIOL:     0
        MUNSTKERR:    0
        MSTKERR:      1
        MLSPERR:      0
        MMARVALID:    0
        IBUSERR:      0  Instruction bus error
        PRECISERR:    0  Precise data bus error
        IMPRECISERR:  0  Imprecise data bus error
        UNSTKERR:     0  Bus fault on unstacking for a return from exception
        STKERR:       0  Bus fault on stacking for exception entry
        LSPERR:       0  Bus fault on floating-point lazy state preservation
        BFARVALID:    0  Bus Fault Address Register (BFAR) valid flag
        UNDEFINSTR:   0  Undefined instruction usage fault
        INVSTATE:     0  Invalid state usage fault
        INVPC:        0  Invalid PC load usage fault
        NOCP:         0  No coprocessor usage fault.
        UNALIGNED:    0  Unaligned access usage fault
        DIVBYZERO:    0  Divide by zero usage fault
arm-none-eabi-gcc -v
cc version 10.2.1 20201103 (release) (GNU Arm Embedded Toolchain 10-2020-q4-major)

Solution

  • The problem was to not set PRIVDEFENA bit. So turning on the MPU as follows helped:

    ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);