MMFAR & BFAR read

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MMFAR & BFAR read

Jump to solution
2,648 Views
guylejeune
Contributor III

Hello,

on a MK22 chip, I am modifying the HardFault Handler to record some specific registers (SHCSR,CFSR,HFSR,MMFAR & BFAR).

I have a weird problem: when the code reads the MMFAR & BFAR registers (address 0xE000ED34 & 0xE000ED38), the returned value is their address.  But if I break at that very location, reading with JTAG these registers gives me other values.

This behaviour is not exhibited with other SCB registers (SHCSR, CFSR, HFSR).

I first thought of small bug somewhere, but the code (down to assembly) is identical for all SCB register.

Here is a portion of the assembly code, exhibiting this behaviour: it reads CFSR & HFSR, calls a backup function, than reads MMFAR & BFAR and calls the same backup function.

   10122:       4b0e            ldr     r3, [pc, #56]   ; (1015c <RegBackup+0xa4>)
   10124:       681b            ldr     r3, [r3, #0]
   10126:       9300            str     r3, [sp, #0]
   10128:       4b0d            ldr     r3, [pc, #52]   ; (10160 <RegBackup+0xa8>)
   1012a:       4668            mov     r0, sp
   1012c:       681b            ldr     r3, [r3, #0]
   1012e:       9301            str     r3, [sp, #4]
   10130:       f243 01d0       movw    r1, #12496      ; 0x30d0
   10134:       2208            movs    r2, #8
   10136:       f7ff fca7       bl      fa88 <supervisor_FlashWrite>
   1013a:       4b0a            ldr     r3, [pc, #40]   ; (10164 <RegBackup+0xac>)
   1013c:       681b            ldr     r3, [r3, #0]
   1013e:       9300            str     r3, [sp, #0]
   10140:       4b09            ldr     r3, [pc, #36]   ; (10168 <RegBackup+0xb0>)
   10142:       4668            mov     r0, sp
   10144:       681b            ldr     r3, [r3, #0]
   10146:       9301            str     r3, [sp, #4]
   10148:       f243 01d8       movw    r1, #12504      ; 0x30d8
   1014c:       2208            movs    r2, #8
   1014e:       f7ff fc9b       bl      fa88 <supervisor_FlashWrite>
   10152:       b002            add     sp, #8
   10154:       bd10            pop     {r4, pc}
   10156:       bf00            nop
   10158:       e000ed24        .word   0xe000ed24
   1015c:       e000ed28        .word   0xe000ed28
   10160:       e000ed2c        .word   0xe000ed2c
   10164:       e000ed34        .word   0xe000ed34
   10168:       e000ed38        .word   0xe000ed38‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Stepping the instructions, I observe that instruction 0x1013C leaves R3 unmodified with value 0xE000ED34.  The same thing happens @ instruction 0x10144. 

Conversly, @ instructions 0x10124 & 0x1012C, register R3 correctly loads the pointed value.

Am I missing anything ?  Can it be that these MMFAR & BFAR register have some particular behaviour that I'm not aware of ?

Tags (2)
0 Kudos
1 Solution
2,152 Views
egoodii
Senior Contributor III

You will get these values if IMPRECISERR is set.  That is to say, when the fault is 'discovered' the address bus no longer contains a value related to the fault, so what gets 'stored' is the single address guaranteed NOT to relate to the fault -- that of the register itself.  This is MOST OFTEN due to write-buffering (enabled by default), and THAT is usually due to an attempt to write a peripheral-control-register before enabling the clock to that submodule(powering it up)..  You can either look at your fault-frame stacked-PC and 'work backwards' a bit to find a 'viable culprit', OR you can disable write-buffering for a test-mode (ACTLR DISDEFWBUF, named SCB_ACTLR_DISDEFWBUF_MASK in the header file I use for MK22FA).  The exact statement in DUI0553A_cortex_m4_dgug.pdf is "When set to 1, disables write buffer use during default memory map accesses. This causes all BusFaults to be precise BusFaults but decreases performance because any store to memory must complete before the processor can execute the next instruction."

FWIW the assembly-front-end I use for all unused&fault vectors is this (in crt0.s)

HardFault_Handler
MemManage_Handler
BusFault_Handler

;;;; and other such labels for unused vectors

    movs r0,#4
    movs r1, lr
    tst r0, r1
    beq _MSP
    mrs r0, psp
    b _HALT
  _MSP:
    mrs r0, msp
  _HALT:
    ldr r1,[r0,#20]
    b hard_fault_handler_c
    bkpt #0

The follow-on 'C' code of hard_fault_handler_c is attached.  IMHO this function should be a primary element of ALL 'example projects' -- the first thing many NOOBs run into is hard-faults....

View solution in original post

2 Replies
2,153 Views
egoodii
Senior Contributor III

You will get these values if IMPRECISERR is set.  That is to say, when the fault is 'discovered' the address bus no longer contains a value related to the fault, so what gets 'stored' is the single address guaranteed NOT to relate to the fault -- that of the register itself.  This is MOST OFTEN due to write-buffering (enabled by default), and THAT is usually due to an attempt to write a peripheral-control-register before enabling the clock to that submodule(powering it up)..  You can either look at your fault-frame stacked-PC and 'work backwards' a bit to find a 'viable culprit', OR you can disable write-buffering for a test-mode (ACTLR DISDEFWBUF, named SCB_ACTLR_DISDEFWBUF_MASK in the header file I use for MK22FA).  The exact statement in DUI0553A_cortex_m4_dgug.pdf is "When set to 1, disables write buffer use during default memory map accesses. This causes all BusFaults to be precise BusFaults but decreases performance because any store to memory must complete before the processor can execute the next instruction."

FWIW the assembly-front-end I use for all unused&fault vectors is this (in crt0.s)

HardFault_Handler
MemManage_Handler
BusFault_Handler

;;;; and other such labels for unused vectors

    movs r0,#4
    movs r1, lr
    tst r0, r1
    beq _MSP
    mrs r0, psp
    b _HALT
  _MSP:
    mrs r0, msp
  _HALT:
    ldr r1,[r0,#20]
    b hard_fault_handler_c
    bkpt #0

The follow-on 'C' code of hard_fault_handler_c is attached.  IMHO this function should be a primary element of ALL 'example projects' -- the first thing many NOOBs run into is hard-faults....

2,152 Views
guylejeune
Contributor III

Thank you for this detailed answer & explanation !

0 Kudos