栈回溯--在栈里挑出返回地址

news2024/11/17 11:29:13

 

GNU Arm Embedded Toolchain project files : GNU Arm Embedded Toolchain

arm-none-eabi-addr2line -e F103_Moduel.axf -a -f 08000350 08001d94 0800260c 

汇编中: 

;HardFault_Handler
;                PROC
;                EXPORT  HardFault_Handler          [WEAK]
;                B       .
;                ENDP

    IMPORT rt_hw_hard_fault_exception
    EXPORT HardFault_Handler
HardFault_Handler    PROC

    ; get current context
    TST     lr, #0x04               ; if(!EXC_RETURN[2])
    ITE     EQ
    MRSEQ   r0, msp                 ; [2]=0 ==> Z=1, get fault context from handler.
    MRSNE   r0, psp                 ; [2]=1 ==> Z=0, get fault context from thread.

    STMFD   r0!, {r4 - r11}         ; push r4 - r11 register
    STMFD   r0!, {lr}               ; push exec_return register

    TST     lr, #0x04               ; if(!EXC_RETURN[2])
    ITE     EQ
    MSREQ   msp, r0                 ; [2]=0 ==> Z=1, update stack pointer to MSP.
    MSRNE   psp, r0                 ; [2]=1 ==> Z=0, update stack pointer to PSP.

    PUSH    {lr}
    BL      rt_hw_hard_fault_exception
    POP     {lr}

    ORR     lr, lr, #0x04
    BX      lr
    ENDP

rt_hw_hard_fault_exception代码 :

#define rt_uint32_t unsigned int
#define uint16_t    unsigned short
struct exception_info
{
    rt_uint32_t exc_return;
    rt_uint32_t r4;
    rt_uint32_t r5;
    rt_uint32_t r6;
    rt_uint32_t r7;
    rt_uint32_t r8;
    rt_uint32_t r9;
    rt_uint32_t r10;
    rt_uint32_t r11;
    rt_uint32_t r0;
    rt_uint32_t r1;
    rt_uint32_t r2;
    rt_uint32_t r3;
    rt_uint32_t r12;
    rt_uint32_t lr;
    rt_uint32_t pc;
    rt_uint32_t psr;
};

/* check the disassembly instruction is 'BL' or 'BLX' */
static int disassembly_ins_is_bl_blx(rt_uint32_t addr) {
    uint16_t ins1 = *((uint16_t *)addr);
    uint16_t ins2 = *((uint16_t *)(addr + 2));

#define BL_INS_MASK         0xF800
#define BL_INS_HIGH         0xF800
#define BL_INS_LOW          0xF000
#define BLX_INX_MASK        0xFF00
#define BLX_INX             0x4700

    if ((ins2 & BL_INS_MASK) == BL_INS_HIGH && (ins1 & BL_INS_MASK) == BL_INS_LOW) {
        return 1;
    } else if ((ins2 & BLX_INX_MASK) == BLX_INX) {
        return 1;
    } else {
        return 0;
    }
}

static int is_in_text(unsigned int addr)
{
	extern int * Image$$ER_IROM1$$Base;
	extern int * Image$$ER_IROM1$$Length;

	unsigned int text_start = (unsigned int)&Image$$ER_IROM1$$Base;
	unsigned int text_len = (unsigned int)&Image$$ER_IROM1$$Length;

	if ((addr >= text_start) && (addr < text_start + text_len))
		return 1;
	else
		return 0;
}

/*
 * fault exception handler
 */
void rt_hw_hard_fault_exception(struct exception_info * exception_info)
{
	unsigned int *app_sp;
	unsigned int lr;
	unsigned int pc;

	int i;
	app_sp = (unsigned int *)(exception_info + 1);  /* context + 16*4 */
	
    printf("psr: 0x%08x\r\n", exception_info->psr);
    printf("r00: 0x%08x\r\n", exception_info->r0);
    printf("r01: 0x%08x\r\n", exception_info->r1);
    printf("r02: 0x%08x\r\n", exception_info->r2);
    printf("r03: 0x%08x\r\n", exception_info->r3);
    printf("r04: 0x%08x\r\n", exception_info->r4);
    printf("r05: 0x%08x\r\n", exception_info->r5);
    printf("r06: 0x%08x\r\n", exception_info->r6);
    printf("r07: 0x%08x\r\n", exception_info->r7);
    printf("r08: 0x%08x\r\n", exception_info->r8);
    printf("r09: 0x%08x\r\n", exception_info->r9);
    printf("r10: 0x%08x\r\n", exception_info->r10);
    printf("r11: 0x%08x\r\n", exception_info->r11);
    printf("r12: 0x%08x\r\n", exception_info->r12);
    printf(" lr: 0x%08x\r\n", exception_info->lr);
    printf(" pc: 0x%08x\r\n", exception_info->pc);


#if 0
	printf("stacks: \r\n");
#else
	printf("use the command to get callback: arm-none-eabi-addr2line -e your.axf -a -f ");
	printf("%08x ", exception_info->pc);
	printf("%08x ", exception_info->lr);
#endif

	i = 0;
	for (i = 0; i < 1024; )
	{
#if 0		
		printf("%08x ", *app_sp);		
		app_sp++;
		i++;
		if (i % 16 == 0)
			printf("\r\n");
#else
		lr = *app_sp;
		app_sp++;
		i++;

		/* lr的bit0必定是1, 表示thumb指令集 
		 * lr必定处于代码段
		 */
		if ((lr & 1) && is_in_text(lr))
		{
			/* 返回地址前面必定是BL或BLX指令 */
			pc = (lr & ~1) - 4;
			if (disassembly_ins_is_bl_blx(pc))
			{
				printf("%08x ", pc);
			}
			
		}
#endif
	}
	printf("\r\n");

    while (1);
}

main.c中

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "driver_usart.h"
#include "driver_key.h"
#include <stdio.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 PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void MX_FREERTOS_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */


ring_buffer test_buffer;

static void A(void);
static void B(void);
static int C(int b);

static void A(void)
{
	printf("Enter A()\r\n");
	B();
	printf("Exit A()\r\n");
}

static void B(void)
{
	printf("Enter B()\r\n");
	C(0);
	printf("Exit B()\r\n");
}

static int C(int b)
{
	//printf("Enter C()\r\n");
	return 100/b;
}

static void D(void)
{	
	printf("Enter D()\r\n");
	C(1);
	printf("Exit D()\r\n");
}


void TestDebug(void)
{
	/* 100ask add */
	/* 使能除0错误
	 * CCR(0xE000ED14)的bit4(DIV_0_TRP)设置为1
	 */
	volatile int *CCR = (volatile int *)0xE000ED14;
	*CCR |= (1<<4);

	A();
	D();
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
    
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */
  
	KEY_GPIO_ReInit();
	
    ring_buffer_init(&test_buffer);
  
    EnableDebugIRQ();
    printf("Hello World!\r\n");

	TestDebug();

  /* USER CODE END 2 */

  /* Init scheduler */
  osKernelInitialize();  /* Call init function for freertos objects (in freertos.c) */
  MX_FREERTOS_Init();
  /* Start scheduler */
  osKernelStart();

  /* We should never get here as control is now taken by the scheduler */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM8 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM8) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1242416.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PTA-用天平找小球

三个球A、B、C&#xff0c;大小形状相同且其中有一个球与其他球重量不同。要求找出这个不一样的球。 输入格式&#xff1a; 输入在一行中给出3个正整数&#xff0c;顺序对应球A、B、C的重量。 输出格式&#xff1a; 在一行中输出唯一的那个不一样的球。 输入样例&#xff…

Docker部署Vue+Springboot项目

一、部署Springboot项目 1.1先将本地的java项目打成jar包。 再右上角进行maven操作。 1.2将jar包上传到服务器当中。 先再目录/home 下创建一个文件夹&#xff08;classRoom&#xff09;用于存放后端打镜像时需要的文件。 如果是服务器的话可以直接将文件拖拽到想要转移的地方…

设计师不能忽视的几个宝藏图标设计工具

在这个快速变化的时代&#xff0c;设计师对创新和实用工具的需求越来越大。这就要求我们及时跟上潮流&#xff0c;不断探索和尝试最新、最有价值的图标设计工具。只有这样&#xff0c;我们才能在竞争激烈的设计市场中脱颖而出。以下是我们精心挑选的2024年值得一试的图标设计工…

2015年1月12日 Go生态洞察:Go语言中错误也是值

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

ios打包,证书获取

HBuilderX 打包ios界面&#xff1a; Bundle ID(AppID)&#xff1a; 又称应用ID&#xff0c;是每一个ios应用的唯一标识&#xff0c;就像一个人的身份证号码&#xff1b; 每开发一个新应用&#xff0c;首先都需要先去创建一个Bundle ID Bundle ID 格式&#xff1a; 一般为&…

Android Studio记录一个错误:Execution failed for task ‘:app:lintVitalRelease‘.

Android出现Execution failed for task :app:lintVitalRelease.> Lint found fatal errors while assembling a release target. Execution failed for task :app:lintVitalRelease解决方法 Execution failed for task ‘:app:lintVitalRelease’ build project 可以正常执…

LeeCode前端算法基础100题(3)- N皇后

一、问题详情&#xff1a; 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后…

Navicat 技术指引 | 适用于 GaussDB 的用户权限设置

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对 GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

项目经理只需要有PMP证书就行?

就目前而言&#xff0c;大部分人对于项目经理的认识还停留在&#xff1a;有项目管理经验&#xff0c;有对应的工作年限&#xff0c;有PMP证书。所以绝大多数人都认为只要报考了PMP项目管理&#xff0c;取得PMP证书&#xff0c;即可加入项目经理的圈子&#xff0c;薪资翻倍。 但…

餐饮门店做小程序的作用是什么

我国餐饮行业市场规模逐步上升&#xff0c;中国到店餐饮平台致力于做深做透大餐饮的战略布局&#xff0c;从营销、配送、IT系统、供应链等多角度全方位服务餐饮行业&#xff0c;数字化赋能商家&#xff0c;促进线上线下融合发展&#xff0c;以形成餐饮行业生态闭环。 餐饮行业…

2023APMCM亚太杯数学建模选题建议及初步思路

大家好呀&#xff0c;亚太杯数学建模开始了&#xff0c;来说一下初步的选题建议吧&#xff1a; 首先定下主基调&#xff0c;本次亚太杯推荐选择B题。 C题如果想做好&#xff0c;搜集数据难度并不低&#xff0c;并且模型比较简单&#xff0c;此外目前选择的人数过多&#xff0c…

2023上海小学生古诗文大会复赛(复选)在线模拟题库更新到503题

为了帮助参加2023年上海小学生古诗文大会复选&#xff08;复赛&#xff09;的孩子们更好地练习和备考&#xff0c;我这几天制作了一个在线练习的模拟题库。 这个在线模拟题对标市级比赛的形式和样式&#xff0c;具有以下特点和功能&#xff1a; 1、可以通过手机、电脑、平板&a…

C语言--给定一个数组,把第一项的值减去第二项的值,第二项的值减去第三项的值,第三项的值减去第四项的值,依次类推。放到一个新的数组中,并打印新的数组

一.题目描述&#xff1a; 给定一个数组&#xff0c;把第一项的值减去第二项的值&#xff0c;第二项的值减去第三项的值&#xff0c;第三项的值减去第四项的值&#xff0c;依次类推。放到一个新的数组中&#xff0c;并打印新的数组。 比如&#xff1a;输入一个数组是5&#xff…

springboot 拦截器中使用@Value注解为null

拦截器中获取配置参数为null 代码如下&#xff1a; 解决方式一&#xff1a; 检查你的WebMvcConfigurer实现类&#xff0c;比如我的是CCBWebMvcConfig 将拦截器以bean的形式注入&#xff1a; 我之前的写法是new 一个放进去的&#xff0c;这种会导致Value为null AutowiredJSCCB…

如何在Linux系统上检测GPU显存和使用情况?

如何在Linux系统上检测GPU显存和使用情况&#xff1f; 在Linux系统上&#xff0c;你可以使用一些命令行工具来检测GPU显存和使用情况。以下是一些常用的方法&#xff1a; 1. 使用nvidia-smi&#xff08;仅适用于NVIDIA GPU&#xff09; 如果你使用的是NVIDIA的显卡&#xff0…

服务器安全如何保障

主机安全是指保护计算机主机&#xff08;也称为服务器、终端或主机设备&#xff09;免受潜在的安全威胁和攻击的一系列措施和实践。主机安全旨在防止未经授权的访问、数据泄露、恶意软件感染和其他安全漏洞的利用&#xff0c;主机一旦被黑客入侵&#xff0c;企业会面临很多安全…

【实用】mysql配置 及将线上数据导入本地 问题解决及记录

[ERR] 1292 - Incorrect datetime value: ‘0000-00-0000:00:00‘ for column ‘BIRTH_DATE‘ at row 1 此问题是mysql当前配置不支持日期为空&#xff0c;或者为‘0000-00-0000:00:00‘得情况 1、直接在数据库执行 # 修改全局 set global.sql_mode ONLY_FULL_GROUP_BY,STR…

PC8259(CC-CV控制)同步降压芯片5V/4.8A 输出频率可调 带电流限制 QFN20封装

概述 PC8259是一个同步降压转换器输出电流为4.8A在9V至36V。外部关闭功能可以由逻辑电平控制以下拉COMP/EN引脚&#xff0c;然后进入待机模式。外部补偿使反馈控制具有良好的线性以及具有灵活外部设计的负载调节。PC8259在CC&#xff08;恒定输出电流&#xff09;模式或CV&…

完美解决AttributeError: module ‘numpy‘ has no attribute ‘typeDict‘

文章目录 前言一、完美解决办法安装低版本1.21或者1.19.3都可以总结 前言 这个问题从表面看就是和numpy库相关&#xff0c;所以是小问题&#xff0c;经过来回调试安装numpy&#xff0c;发现是因为目前的版本太高&#xff0c;因此我们直接安装低版本numpy。也不用专门卸载目前的…

python pymodbus库使用教程(以Modbus RTU为例)

文档&#xff1a; https://pymodbus.readthedocs.io/en/latest/ 源码&#xff1a; https://github.com/riptideio/pymodbus/ 文章目录 Python PyModbus库使用教程&#xff1a;以Modbus RTU为例介绍安装PyModbus配置串行连接导入必要的模块创建Modbus客户端实例 建立连接连接…