Cortex-M3 development experience (three): Print the stack information HardFault

Cortex-M3 development experience (three): Print the stack information HardFault

In the "Cortex-M3 development experience (two): Confirm local occurrence of HardFault", we mentioned how to find the wrong place. But it has a problem that must be linked debugger. So in some cases, we can not connect the debugger, you will not be able to read the stack information yet? We can when entering HardFault, get the stack pointer, then print out the way it through the serial port?

Went ahead and have good ideas, there must also be practical action to verify their ideas.

How to get the stack pointer?

We stuck our first question is how to get the stack pointer. Is how to obtain the SP,, PSP (process stack pointer) the value of the MSP (main stack pointer) a.

In the "Cortex-M3 Definitive Guide", there are so many words: CM3 There are two microcontroller core stack pointer, so that is supported by two stacks, when referring to R13 (writing SP), is a reference to the currently that one (MSP or PSP) used, the other must use special instructions to access (MRS and MSR instructions).

In other words, we need to use assembler instructions to get the stack pointer.

uint32_t get_msp_addr()
{
    __asm("mrs r0, msp");
    __asm("bx lr");
}

uint32_t get_psp_addr()
{
    __asm("mrs r0, psp");
    __asm("bx lr");
}

uint32_t get_sp_addr()
{
    __asm("mov r0, sp");
    __asm("bx lr");
}

NOTE: C different for each embedded assembly supported compiler, some compilers may __asm ​​is not supported.

Acquired by the kernel stack pointer register value

uint32_t reg_buff[10];
uint32_t *sp = NULL;

void HardFault_Handler()
{
    sp = (uint32_t*)get_msp_addr();
    reg_buff[0] = *(sp++);
    reg_buff[1] = *(sp++);
    reg_buff[2] = *(sp++);
    reg_buff[3] = *(sp++);
    reg_buff[4] = *(sp++);
    reg_buff[5] = *(sp++);
    reg_buff[6] = *(sp++);
    reg_buff[7] = *(sp++);
    reg_buff[8] = *(sp++);
    reg_buff[9] = *(sp++);
    while(1){}
}

Compile and run!

The results somewhat unexpected!

LR value and the value of the PC before stepping do not like us! Offset of 12 bytes. why? Looked back and found a single step, we call this function in the get_msp_addr HardFault in, and call the function it implies the use of stack space. If I reg_buff HardFault put in, so that more than offset a 12 bytes!

There is no better way ah! ?

Before we get into the HardFault_Handler function on the value of the SP pointer, and pass as an argument to HardFault_Handler not can it?

Who calls the interrupt handler?

To solve the above problem, we need to know where to call to the kernel interrupt function, so that we can modify the corresponding interrupt handler, so that it can receive arguments.

"Cortex-M3 development experience (two): Confirm local occurrence of HardFault" we mentioned, the interruption / exception, the kernel to interrupt find the corresponding interrupt vector table, find the entry address of interruption. Then we look at what interrupt vector table?

Finally, we find the definition of the vector table in startup_xxx.S file 1 . We also find the definition of HardFault_Handler

.weak   HardFault_Handler
.type   HardFault_Handler, %function

HardFault_Handler:
    B .

Although the compilation may not understand, I do not know what that means, but also to guess about the meaning, may also find information. B is found a jump instruction, this should jump to the C function of the same name. Then we can modify as follows:

.weak   HardFault_Handler
.type   HardFault_Handler, %function

HardFault_Handler:
    MOV     r0, lr
    MOV     r1, sp
    BL      hardfault_handler

This value SP and the value of LR passed to the function hardfault_handler went 2 .

Compile and run!

The result is what we want.


  1. This is a startup file, which contains a number of chips to start the process required.

  2. Saved registers R0 ~ R3 is a parameter passed in the function call, as well as the function return value. hardfault_handler defined as follows: void hardfault_handler (uint32_t LR, SP uint32_t)

Guess you like

Origin www.cnblogs.com/Oushangrong/p/11022858.html