Bus fault when accessing mcu internal peripheral

0

I am struggling with a bus fault error on my samg55 µC based on arm cortex m4 architecture. The issue occurs sporadically and is not 100% reproductible. Let me give some details.

Application code writes periodically some datas into reserved internal flash memory. To do this I use the EFC (embedded flash controller) of the µC which is mapped at address 0x400E0A00 in system controller.

This writing leads in certain conditions to a hard fault. I dumped registers and got the following:

R4_20001368  R5_00000001  R6_00000338  R7_00000020
R8_00000020  R9_2001bcc8 R10_200128cc R11_0043d3a9
R0_402e0a00  R1_5a03380b  R2_5a033800  R3_20000067
R12_200129cc  LR_0043320b  PC_2000006a PSR_010f0000

SHCSR: 0x00000000
CFSR:  0x00008600
HFSR:  0x40000000
DFSR:  0x00000000
MMFAR: 0x402e0a08
BFAR:  0x402e0a08
AFSR:  0x00000000

CFSR indicates a bus fault with BFARVALID flag set. Looking at BFAR register I can see the value 0x402e0a08 which base address 0x402e0a00 is just one bit different from the EFC address 0x400E0A00.

I digged into the code but could not find the bug. Here is suspected code:

Assembler code

004331d4 <efc_perform_command>:
  4331d4:   f1a1 030e   sub.w   r3, r1, #14
  4331d8:   2b01        cmp r3, #1
  4331da:   b537        push    {r0, r1, r2, r4, r5, lr}
  4331dc:   d91d        bls.n   43321a <efc_perform_command+0x46>
  4331de:   f3ef 8310   mrs r3, PRIMASK
  4331e2:   fab3 f383   clz r3, r3
  4331e6:   095b        lsrs    r3, r3, #5
  4331e8:   9301        str r3, [sp, #4]
  4331ea:   b672        cpsid   i
  4331ec:   f3bf 8f5f   dmb sy
  4331f0:   4c0b        ldr r4, [pc, #44]   ; (433220 <efc_perform_command+0x4c>)
  4331f2:   2300        movs    r3, #0
  4331f4:   7023        strb    r3, [r4, #0]
  4331f6:   4b0b        ldr r3, [pc, #44]   ; (433224 <efc_perform_command+0x50>)
  4331f8:   9d01        ldr r5, [sp, #4]
  4331fa:   ea03 2202   and.w   r2, r3, r2, lsl #8
  4331fe:   f042 42b4   orr.w   r2, r2, #1509949440 ; 0x5a000000
  433202:   b2c9        uxtb    r1, r1
  433204:   4311        orrs    r1, r2
  433206:   4b08        ldr r3, [pc, #32]   ; (433228 <efc_perform_command+0x54>)
  433208:   4798        blx r3
  43320a:   b125        cbz r5, 433216 <efc_perform_command+0x42>
  43320c:   2301        movs    r3, #1
  43320e:   7023        strb    r3, [r4, #0]
  433210:   f3bf 8f5f   dmb sy
  433214:   b662        cpsie   i
  433216:   b003        add sp, #12
  433218:   bd30        pop {r4, r5, pc}
  43321a:   f04f 30ff   mov.w   r0, #4294967295 ; 0xffffffff
  43321e:   e7fa        b.n 433216 <efc_perform_command+0x42>
  433220:   20001368    .word   0x20001368
  433224:   00ffff00    .word   0x00ffff00
  433228:   20000067    .word   0x20000067

20000066 <efc_perform_fcr>:
20000066:   b082        sub sp, #8
20000068:   6041        str r1, [r0, #4]
2000006a:   6883        ldr r3, [r0, #8]
2000006c:   9301        str r3, [sp, #4]
2000006e:   9b01        ldr r3, [sp, #4]
20000070:   07db        lsls    r3, r3, #31
20000072:   d5fa        bpl.n   2000006a <efc_perform_fcr+0x4>
20000074:   9801        ldr r0, [sp, #4]
20000076:   f000 000e   and.w   r0, r0, #14
2000007a:   b002        add sp, #8
2000007c:   4770        bx  lr

C code

/**
 * \brief Perform the given command and wait until its completion (or an error).
 *
 * \note Unique ID commands are not supported, use efc_perform_read_sequence.
 *
 * \param p_efc Pointer to an EFC instance.
 * \param ul_command Command to perform.
 * \param ul_argument Optional command argument.
 *
 * \note This function will automatically choose to use IAP function.
 *
 * \return 0 if successful, otherwise returns an error code.
 */
uint32_t efc_perform_command(Efc *p_efc, uint32_t ul_command,
        uint32_t ul_argument)
{
    uint32_t result;
    irqflags_t flags;

    /* Unique ID commands are not supported. */
    if (ul_command == EFC_FCMD_STUI || ul_command == EFC_FCMD_SPUI) {
        return EFC_RC_NOT_SUPPORT;
    }

    flags = cpu_irq_save();
    /* Use RAM Function. */
    result = efc_perform_fcr(p_efc,
            EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(ul_argument) |
            EEFC_FCR_FCMD(ul_command));
    cpu_irq_restore(flags);
    return result;
}


/**
 * \brief Perform command.
 *
 * \param p_efc Pointer to an EFC instance.
 * \param ul_fcr Flash command.
 *
 * \return The current status.
 */
__no_inline
RAMFUNC
uint32_t efc_perform_fcr(Efc *p_efc, uint32_t ul_fcr)
{
    volatile uint32_t ul_status;

    p_efc->EEFC_FCR = ul_fcr;
    do {
        ul_status = p_efc->EEFC_FSR;
    } while ((ul_status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);

    return (ul_status & EEFC_ERROR_FLAGS);
}

Code is compiled with arm-none-eabi-gcc (gcc-arm-none-eabi-7-2017-q4-major) with -Os optimization.

Note: issue seems to occurs more frequently in low temperature (0°C), so I don't exclude hardware related problem, even though operating range of µC is -40 to 85 °C...

Any idea what could go wrong ? Thanks for your help !

PS: I am not ready to blame cosmic ray... ;-)

embedded
asked on Super User Jan 23, 2019 by Kev1

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0