STM32 outages

Crash course

The basic concept:
the link register LR: address mobilize subroutine return address of the next automatic storage time, in fact, recently called it a function.

Crash course:


Here we need the most attention is the first step onto the stack:
the order in which eight registers are


Wherein the value of LR is an abnormality occurs inside the fixed

Last updated stack pointer, stack based on the content we last used inside, you can know when the last scene of the problem.

Positioning crash

Simply put, the idea is this:
find a crash when the lr register, and then depending on the value lr register to find at this time is pushed psp stack, or msp stack. Then (the last value pushed onto the stack of eight registers) in accordance with the contents of the stack. Which is pressed into the return address stack inside the critical value, this is the last time, pushed on the stack last function, whereby it can locate the crash position.

Positioning keil debug environment using a direct

With examples of actual analysis:
First, write a code that enables single-chip crashes, debug run up:

The deliberate use of a null pointer to the program run death


debug when opening the view, select register,

Judgment based on the value of LR, using psp stack, and then open the memory windows, view the address for the memory data 0x20002FF0, namely the content of the stack last. Right select, long display


The sixth 0x08034a17 find the address, view, disassembly window this window, see the disassembled file in the disassembly window, right-click on the show disassembly at address, enter an address, you can find the location of the corresponding assembly file, and can navigate to the c language in a corresponding position.

So that you can navigate to the location before the crash
2. There is a way, by looking at the relationship between function calls, directly see where the program is dead
click view call stack window, you can see a direct function of the program before the crash call relationship

This also quickly locate, in fact, the principle is the same, is by looking at the stack data, the first method is just to manually go again this process it.

Perfect solution

Because the actual project in crash problem many of which are difficult to reproduce, the products in the course of long-term is difficult to debug, resulting in more ways actually is not very practical. Therefore, we need a more convenient solution.
Ideas: equivalent to the microcontroller to be a black box, whenever the system crashes. We will record important registers and stack information, there is a flash inside. So if there are problems. As long as we look to re-debug, which will save from the flash information read out. So difficult to reproduce the crash problem, we also have a way to the locked position.

Modify .s file
will replace the original content HardFault_Handler more new content, hard_fault_handler_c is a function that will jump to this function when the crash.
The PROC HardFault_Handler    
                 IMPORT hard_fault_handler_c
                 the TST the LR, #. 4 
                 ITE the EQ    
                 MRSEQ R0, the MSP
                 MRSNE R0, the PSP
                 B hard_fault_handler_c               
                 ENDP

selected region as a crash, where the information is stored.

#define ADDR_FLASH_SECTOR_2 ((u32) 0x08008000) // start address of the sector 2, 16 Kbytes
when #define SYS_CRASH_INFO_ADDR ADDR_FLASH_SECTOR_2 // Important information recording system crashes  
. 1
2
defined crash structure for storing information

typedef struct {
     unsigned int crash_time;
     unsigned int is_crash;
     /* register info*/
     unsigned long stacked_r0;
     unsigned long stacked_r1; 
     unsigned long stacked_r2;
     unsigned long stacked_r3;   
     unsigned long stacked_r12; 
     unsigned long stacked_lr; 
     unsigned long stacked_pc; 
     unsigned long stacked_psr; 
     unsigned long SHCSR; 
     unsigned long MFSR; 
     unsigned long BFSR;  
     unsigned long UFSR; 
     unsigned long HFSR; 
     unsigned long DFSR; 
     unsigned long MMAR; 
     unsigned long BFAR;
} System_Crash_Info;

void hard_fault_handler_c(unsigned int * hardfault_args)
{    
   static System_Crash_Info crash_info;
   memset(&crash_info, 0, sizeof(System_Crash_Info));
  
   crash_info.is_crash = 1;
   crash_info.crash_time = (unsigned int)HAL_GetTick();
  
   crash_info.stacked_r0 = ((unsigned long) hardfault_args[0]); 
   crash_info.stacked_r1 = ((unsigned long) hardfault_args[1]); 
   crash_info.stacked_r2 = ((unsigned long) hardfault_args[2]); 
   crash_info.stacked_r3 = ((unsigned long) hardfault_args[3]); 
   crash_info.stacked_r12 = ((unsigned long) hardfault_args[4]);   
   crash_info.stacked_lr = ((unsigned long) hardfault_args[5]);  
   crash_info.stacked_pc = ((unsigned long) hardfault_args[6]); 
   crash_info.stacked_psr = ((unsigned long) hardfault_args[7]);

  crash_info.MFSR = (* ((volatile unsigned char *) (0xE000ED28))); // the memory management fault status register  
   crash_info.BFSR = (* ((volatile unsigned char *) (0xE000ED29))); // bus fault state register  
   crash_info.UFSR = (* ((volatile unsigned short int *) (0xE000ED2A))); // use fault status register   
   crash_info.HFSR = (* ((volatile unsigned long *) (0xE000ED2C))); // hard fault status register    
   crash_info.DFSR = (* ((volatile unsigned long *) (0xE000ED30))); // debug fault status register 
   crash_info.MMAR = (* ((volatile unsigned long *) (0xE000ED34))); // storage management address register 
   crash_info.BFAR = (* ((volatile unsigned long *) (0xE000ED38))); // bus fault address register 
  
   u8 ret = STMFLASH_EraseSector (STMFLASH_GetFlashSector (SYS_CRASH_INFO_ADDR ));
   u8 ret2 = STMFLASH_Write(SYS_CRASH_INFO_ADDR, (u32 *)(&crash_info), (3+sizeof(System_Crash_Info))/4);

  the while (. 1); 
}

normal code plus

   = {0} crash_info System_Crash_Info;
   crash_info = * (System_Crash_Info *) (SYS_CRASH_INFO_ADDR);
   IF (= crash_info.is_crash. 1!) {
       STMFLASH_EraseSector (STMFLASH_GetFlashSector (SYS_CRASH_INFO_ADDR));
   } the else {
       CT_PRINTF ( "code of Ever has Crash \ n-") ;
       // die before the case when viewing here, or is crash_info the information in the analysis can also be printed out
   }

practical example:

Such code is re-debug, you can see the situation before the crash. Lr directly see the value of the register, take a look at the disassembled code, you know where the code is finally dead.
----------------
Disclaimer: This article is the original article CSDN bloggers "txsonfire", and follow CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement. .
Original link: https: //blog.csdn.net/qq_27087571/article/details/84580532

Guess you like

Origin www.cnblogs.com/xiumusheng/p/11576762.html