简体   繁体   中英

Find which instruction caused a trap on Cortex M3

I am currently debugging a hard fault trap which turned out to be a precise data bus error on a STM32F205 Cortex-M3 processor, using Keil uVision. Due to a lengthy debugging and googling process I found the assembly instruction that caused the trap. Now I am looking for a way to avoid this lengthy process next time a trap occurs.

In the application note 209 by Keil it says:

PRECISEERR: Precise data bus error: 0 = no precise data bus error 1 = a data bus error has occurred, and the PC value stacked for the exception return points to the instruction that caused the fault. When the processor sets this bit it writes the faulting address to SCB->BFAR

and also this:

An exception saves the state of registers R0-R3, R12, PC & LR either the Main Stack or the Process Stack (depends on the stack in use when the exception occurred).

The last quote I am interpreting as such that there should be 7 registers plus the respective stack. When I look up my SP address in the memory I see the address that caused the error at an address 10 words higher than the stack pointer address.

My questions are:

  • Is the address of the instruction that caused the trap always saved 10 words higher than the current stack pointer? And could you please point out a document where I can read up on how and why this is?

  • Is there another register that would contain this address as well?

As you said, exceptions (or interrupts) on ARM Cortex-M3 will automatically stack some registers, namely :

  • Program Counter (PC)
  • Processor Status Register (xPSR)
  • r0-r3
  • r12
  • Link Register (LR).

For a total of 8 registers (reference : Cortex™-M3 Technical Reference Manual, Chapter 5.5.1 ).

Now, if you write your exception handler in a language other than assembly, the compiler may stack additional registers, and you can't be sure how many.

One simple solution is to add a small code before the real handler, to pass the address of the auto-stacked registers :

void myRealHandler( void * stack );

void handler(void) {
    asm volatile("mov r0, sp");
    asm volatile("b myRealHandler");
}

The register BFAR is specific to bus faults. It will contain the faulty address, not the address of the faulty instruction. For example, if there was an error reading an integer at address 0x30005632 , BFAR will be set to 0x30005632 .

The precise stack location of the return address depends on how much stack the interrupt handler requires. If you look at the disassembly of your HardFault_Handler, you should be able to see how much data is stored on the stack / how many registers are pushed in addition to the registers pushed by the hardware interrupt machinery (R0-R3, R12, PC, LR & PSR)

I found this to be a pretty good idea on how to debug Hard Faults, though it requires a bit of inline assembly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM