活动介绍
file-type

定位程序跑飞与Hardfault:ARM7与Cortex异常指令追踪法

PDF文件

下载需积分: 50 | 277KB | 更新于2024-09-09 | 8 浏览量 | 3 下载量 举报 收藏
download 立即下载
本文主要针对嵌入式程序开发中遇到的程序跑飞导致硬件异常中断Hardfault问题提供解决方案。作者以Aduc7026(ARM7内核)和LM3S8962(Cortex内核,包括STM32)为例,详细解释如何通过调试来定位问题。 首先,理解ARM7内核的工作模式非常重要,它拥有多种工作模式下的17个寄存器,如R0-R15和CPSR,其中LR寄存器(R14)用于保存函数调用和中断返回地址。在异常中断发生时,LR寄存器中保存的地址附近通常会包含引发异常的指令。 文章强调,当程序跑飞时,大部分情况下会导致硬件异常中断,这些中断服务函数的入口地址存储在中断向量表中,如keil开发环境中的startup.s文件。该文件定义了一系列的处理程序,比如Reset_Handler、ADI_UNDEF_Interrupt_Setup等,对应不同的中断类型。 通过构造一个指令异常,例如利用LDR(Load Register)指令引发未定义指令异常(Undef_Addr),然后分析中断向量表,可以看到异常处理程序的地址。接着,通过反汇编或者断点调试技术,逐步追溯到异常发生的代码行,即导致硬故障的指令。 对于Cortex内核,虽然处理方式相似,但可能涉及的寄存器和向量表结构略有不同,因为它们遵循不同的中断机制。不过,基本的思路都是利用异常返回地址来定位问题源。 总结来说,本文提供的方法包括:1)理解寄存器的作用,特别是LR寄存器;2)熟悉中断向量表的结构和功能;3)通过模拟或实际触发异常,结合工具进行逆向工程,找出引发Hardfault的指令。这对于嵌入式程序员来说是一份实用的故障排除指南。

相关推荐

filetype

/* USER CODE BEGIN Header */ /** ****************************************************************************** * File Name : * Description : ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "MyApplication.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN Variables */ /* USER CODE END Variables */ osThreadId defaultTaskHandle; osThreadId SystemTaskHandle; osTimerId Shut_WaterTimerHandle; /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ /* USER CODE END FunctionPrototypes */ void StartDefaultTask(void const * argument); void System_Task(void const * argument); void Shut_WaterCallback(void const * argument); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /* GetIdleTaskMemory prototype (linked to static allocation support) */ void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); /* GetTimerTaskMemory prototype (linked to static allocation support) */ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ); /* USER CODE BEGIN GET_IDLE_TASK_MEMORY */ static StaticTask_t xIdleTaskTCBBuffer; static StackType_t xIdleStack[configMINIMAL_STACK_SIZE]; void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) { *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer; *ppxIdleTaskStackBuffer = &xIdleStack[0]; *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* place for user code */ } /* USER CODE END GET_IDLE_TASK_MEMORY */ /* USER CODE BEGIN GET_TIMER_TASK_MEMORY */ static StaticTask_t xTimerTaskTCBBuffer; static StackType_t xTimerStack[configTIMER_TASK_STACK_DEPTH]; void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) { *ppxTimerTaskTCBBuffer = &xTimerTaskTCBBuffer; *ppxTimerTaskStackBuffer = &xTimerStack[0]; *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* place for user code */ } /* USER CODE END GET_TIMER_TASK_MEMORY */ /** * @brief FreeRTOS initialization * @param None * @retval None */ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* USER CODE BEGIN RTOS_MUTEX */ /* add mutexes, ... */ /* USER CODE END RTOS_MUTEX */ /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ /* Create the timer(s) */ /* definition and creation of Shut_WaterTimer */ osTimerDef(Shut_WaterTimer, Shut_WaterCallback); Shut_WaterTimerHandle = osTimerCreate(osTimer(Shut_WaterTimer), osTimerOnce, NULL); /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ /* definition and creation of defaultTask */ osThreadDef(defaultTask, StartDefaultTask, osPriorityLow, 0, 192); defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); /* definition and creation of SystemTask */ osThreadDef(SystemTask, System_Task, osPriorityIdle, 0, 384); SystemTaskHandle = osThreadCreate(osThread(SystemTask), NULL); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ /* USER CODE END RTOS_THREADS */ } /* USER CODE BEGIN Header_StartDefaultTask */ /** * @brief Function implementing the defaultTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void const * argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ for(;;) { if (Stopcock_STA_Instruct.Data_Receive_Receive == 1) { Stopcock_Comm.Data_Parser_Deal(); } osDelay(1); } /* USER CODE END StartDefaultTask */ } /* USER CODE BEGIN Header_System_Task */ /** * @brief Function implementing the SystemTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_System_Task */ void System_Task(void const * argument) { /* USER CODE BEGIN System_Task */ /* Infinite loop */ for(;;) { System.Run(); osDelay(1); } /* USER CODE END System_Task */ } /* Shut_WaterCallback function */ void Shut_WaterCallback(void const * argument) { /* USER CODE BEGIN Shut_WaterCallback */ Stopcock_STA_Instruct.Out_Shut_Water_Instruct = 3; Stopcock_STA_Instruct.Shut_Water_Type = 2; // Stopcock_STA_Instruct.Shut_Water_Type = 3; Stopcock_Signal_Deal.Lock_Flag2 = 0; Stopcock_Signal_Deal.Lock_Flag1 = 0; /* USER CODE END Shut_WaterCallback */ } /* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application */ /* USER CODE END Application */ /* Includes ------------------------------------------------------------------*/ #include "MyApplication.h" /* Private define-------------------------------------------------------------*/ extern uint8_t flag1; extern uint8_t flag2; /* Private variables----------------------------------------------------------*/ static void Run(void); static void Error_Handle(void); static void Assert_Failed(void); /* Public variables-----------------------------------------------------------*/ System_t System = { Run, Error_Handle, Assert_Failed }; /* Private function prototypes------------------------------------------------*/ /* * @name Run * @brief 系统运行函数 * @param None * @retval None */ static void Run() { static uint8_t counter = 0;// 去抖动 uint8_t HALL_IO0 ; uint8_t HALL_IO1 = 0; //HALL_IO0 = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0); if (Stopcock_STA_Instruct.Total_Control == 1) // 总控制打开,才开始采样处理 { HALL_IO0 = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0); if(HALL_IO0 == 0) { counter=0; Stopcock_Signal_Deal.HALL_Signal_Deal(); HALL_IO1 = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3); if(HALL_IO1 == 0) { Stopcock_Signal_Deal.Scan_Signal_Deal(); // Stopcock_Signal_Deal.Block_Signal_Deal(); } }else if(HALL_IO0 == 1) { counter++; if(counter>10){ //防止干扰 osDelay(100); counter=0; //printf("进入io=%d关水水\r\n",HALL_IO0); Stopcock_Comm.pucSend_Buffer[0] = 0xAA; Stopcock_Comm.pucSend_Buffer[1] = 0x03; Stopcock_Comm.pucSend_Buffer[2] = 0x01; Stopcock_Comm.pucSend_Buffer[3] = 0x0D; Stopcock_Comm.SendArray(Stopcock_Comm.pucSend_Buffer, 4); Stopcock_STA_Instruct.Out_Shut_Water_Instruct = 0; Public.Memory_Clr(Stopcock_Comm.pucRec_Buffer, sizeof(Stopcock_Comm.pucRec_Buffer)); // 清除接收缓存 } } } if (Stopcock_STA_Instruct.Out_Shut_Water_Instruct == 1) // 发送开水指令 { Public.Memory_Clr(Stopcock_Comm.pucSend_Buffer, sizeof(Stopcock_Comm.pucSend_Buffer)); // 清除发送缓存 osTimerStop(Shut_WaterTimerHandle); Stopcock_Comm.pucSend_Buffer[0] = 0xAA; Stopcock_Comm.pucSend_Buffer[1] = 0x02; Stopcock_Comm.pucSend_Buffer[2] = 0x01; Stopcock_Comm.pucSend_Buffer[3] = 0x0D; Stopcock_Comm.SendArray(Stopcock_Comm.pucSend_Buffer, 4); Stopcock_STA_Instruct.Out_Shut_Water_Instruct = 0; Public.Memory_Clr(Stopcock_Comm.pucRec_Buffer, sizeof(Stopcock_Comm.pucRec_Buffer)); // 清除接收缓存 } else if (Stopcock_STA_Instruct.Out_Shut_Water_Instruct == 2) // 发送关水指令 { Public.Memory_Clr(Stopcock_Comm.pucSend_Buffer, sizeof(Stopcock_Comm.pucSend_Buffer)); // 清除发送缓存 Stopcock_Comm.pucSend_Buffer[0] = 0xAA; Stopcock_Comm.pucSend_Buffer[1] = 0x03; Stopcock_Comm.pucSend_Buffer[2] = 0x01; Stopcock_Comm.pucSend_Buffer[3] = 0x0D; Stopcock_Comm.SendArray(Stopcock_Comm.pucSend_Buffer, 4); // Public.Memory_Clr(Stopcock_Comm.pucRec_Buffer, sizeof(Stopcock_Comm.pucRec_Buffer)); // 清除接收缓存 Stopcock_Signal_Deal.Lock_Flag1 = 0;//锁定位清除 Stopcock_Signal_Deal.Lock_Flag2 = 0; Stopcock_STA_Instruct.Out_Shut_Water_Instruct = 0; //printf("关水完成\r\n"); }else if (Stopcock_STA_Instruct.Out_Shut_Water_Instruct == 3) // 发送关水指令 { if(Stopcock_Comm.block != 0x03) { //printf("完成\r\n"); Public.Memory_Clr(Stopcock_Comm.pucSend_Buffer, sizeof(Stopcock_Comm.pucSend_Buffer)); // 清除发送缓存 Stopcock_Comm.pucSend_Buffer[0] = 0xAA; Stopcock_Comm.pucSend_Buffer[1] = 0x03; Stopcock_Comm.pucSend_Buffer[2] = 0x01; Stopcock_Comm.pucSend_Buffer[3] = 0x0D; Stopcock_Comm.SendArray(Stopcock_Comm.pucSend_Buffer, 4); Public.Memory_Clr(Stopcock_Comm.pucRec_Buffer, sizeof(Stopcock_Comm.pucRec_Buffer)); // 清除接收缓存 Stopcock_Signal_Deal.Lock_Flag1 = 0;//锁定位清除 Stopcock_Signal_Deal.Lock_Flag2 = 0; Stopcock_STA_Instruct.Out_Shut_Water_Instruct = 0; //Stopcock_Comm.block =0; } } } /* * @name Error_Handler * @brief 系统错误处理 * @param None * @retval None */ //程序异常,所给的提示信息 static void Error_Handle() { /* User can add his own implementation to report the HAL error return state */ } /* * @name Assert_Failed * @brief 函数参数错误处理 * @param None * @retval None */ static void Assert_Failed() { /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ } /******************************************************** End Of File ********************************************************/ 运行完这个函数之后就跑飞 有时候跑飞有时候不跑飞else if (Stopcock_STA_Instruct.Out_Shut_Water_Instruct == 3) // 发送关水指令

一生U你
  • 粉丝: 11
上传资源 快速赚钱