1、参考链接
https://blog.csdn.net/freedompoi/article/details/122039939
2、下载
CmBacktrace的github目录:
https://gitcode.com/armink/CmBacktrace/tree/master?utm_source=csdn_github_accelerator&isLogin=1
下载解压:
3、移植CmBacktrace
复制CmBacktrace源码到工程文件夹下
在keil中添加源码,我这里使用的keil5,cmbacetrace.c在cm_backtrace下,cmb_fault.s在CmBacktrace-master\cm_backtrace\fault_handler\keil下。
包含头文件
4、在工程里做环境适配
(1)屏蔽HardFault_Handler函数
在使用了cmbacetrace库提供的 cmb_fault.s 汇编文件时,因为该汇编文件内部已经定义了 HardFault_Handler ,所以如果项目中还有其他地方定义了该函数,则会提示 HardFault_Handler 被重复定义的错误。注释/删除其他文件中定义的 HardFault_Handler 函数,仅保留 cmb_fault.s 中的。
原工程的HardFault_Handler函数在stm32f4xx_it.c文件中。
(2)main文件
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2024 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "can.h"
#include "dma.h"
#include "fatfs.h"
#include "iwdg.h"
#include "lwip.h"
#include "sdio.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "change_data.h"
#include <cm_backtrace.h>
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* 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 */
#define HARDWARE_VERSION "V1.0.0"
#define SOFTWARE_VERSION "V0.1.0"
/* 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 */
/* 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_DMA_Init();
MX_SDIO_SD_Init();
MX_USART1_UART_Init();
MX_CAN2_Init();
MX_IWDG_Init();
CAN_Init();
MX_TIM2_Init();
// MX_TIM3_Init();
MX_TIM4_Init();
/* USER CODE BEGIN 2 */
/* init code for FATFS */
/* init code for FATFS */
MX_FATFS_Init();
/* init code for LWIP */
MX_LWIP_Init();
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim4);
cm_backtrace_init("CmBacktrace",HARDWARE_VERSION,SOFTWARE_VERSION);
/* Call init function for freertos objects (in freertos.c) */
fault_test_by_unalign();
// FATFS deviceFatFs;
// FIL file;
// FRESULT fres;
// uint32_t bw;
//
// /* ×¢²áÒ»¸ö¹¤×÷ÇøÓò */
// fres = f_mount(&deviceFatFs, "0:", 0);
//
// /* ´ò¿ªÎļþ£¬Ã»Óоʹ´½¨Ò»¸öеÄÎļþ */
// fres = f_open(&file, "0:/TEST.txt", FA_CREATE_ALWAYS | FA_WRITE);
// /* дÈë±êÌâÊý¾Ý */
// fres = f_write(&file, "ÐòºÅ,Ãû³Æ,Êý¾Ý\n", sizeof("ÐòºÅ,Ãû³Æ,Êý¾Ý\n"), &bw);
// /* ¹Ø±ÕÎļþ */
// f_close(&file);
//
// /* ´ò¿ªÎļþ£¬Ã»Óоʹ´½¨Ò»¸öÐÂÎļþ£¬¶Á/дָÕëÉèÖÃΪÎļþĩβ*/
// fres = f_open(&file, "0:/TEST.txt", FA_OPEN_APPEND | FA_WRITE); //·½Ê½Ò»£º´ò¿ª¾Í°Ñ¶ÁдָÕëÒƶ¯µ½Îļþĩβ
// /* дÈëÊý¾Ý */
// fres = f_write(&file, "1,aa,123\n", sizeof("1,aa,123\n"), &bw);
// /* ¹Ø±ÕÎļþ */
// f_close(&file);
//
// /* ´ò¿ªÎļþ */
// fres = f_open(&file, "0:/TEST.txt", FA_WRITE);
// /* Òƶ¯¶ÁдָÕë */
// fres = f_lseek(&file, f_size(&file)); //·½Ê½2£º´ò¿ªºó¸ù¾ÝÎļþ×Ö½Ú´óСÒƶ¯¶Á/дָÕë
// /* дÈëÊý¾Ý */
// fres = f_write(&file, "2,bb,255\n", sizeof("2,bb,255\n"), &bw);
// /* ¹Ø±ÕÊý¾Ý */
// f_close(&file);
// fres = f_open(&file, "0:/TEST.txt", FA_WRITE);
// /* Òƶ¯¶ÁдָÕë */
// fres = f_lseek(&file, f_size(&file)); //·½Ê½2£º´ò¿ªºó¸ù¾ÝÎļþ×Ö½Ú´óСÒƶ¯¶Á/дָÕë
// /* дÈëÊý¾Ý */
// fres = f_write(&file, "2,bb,255\n", sizeof("2,bb,255\n"), &bw);
// /* ¹Ø±ÕÊý¾Ý */
// f_close(&file);
// //×¢ÏúÒ»¸ö¹¤×÷ÇøÓò
// fres = f_mount(0, "0:", 0);
/* USER CODE END 2 */
/* 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};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses 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_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE BEGIN 4 */
#pragma import(__use_no_semihosting)
//±ê×¼¿âÐèÒªµÄÖ§³Öº¯Êý
struct __FILE
{
int handle;
};
FILE __stdout;
//¶¨Òå_sys_exit()ÒÔ±ÜÃâʹÓðëÖ÷»úģʽ
void _sys_exit(int x)
{
x = x;
}
//Öض¨Òåfputcº¯Êý
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//Ñ»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï
USART1->DR = (uint8_t) ch;
return ch;
}
/* USER CODE END 4 */
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM1 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 == TIM1) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
if(htim->Instance == TIM2) {
/* tim2 3ms*/
if(recv_time == can_push_flag) {
// HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
CanResive_data_handle(data_error_push,50);//Ï·¢Ä¬ÈÏÊý¾Ý
TimeWriteRunFlag = true;
} else can_push_flag = recv_time;
}
if(htim->Instance == TIM4) {
/* tim4 3ms*/
// HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
/* 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,
tex: 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****/
(3)cmb_cfg.h文件
/*
* This file is part of the CmBacktrace Library.
*
* Copyright (c) 2016, Armink, <armink.ztl@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Function: It is the configure head file for this library.
* Created on: 2016-12-15
*/
#ifndef _CMB_CFG_H_
#define _CMB_CFG_H_
/* print line, must config by user */
#define cmb_println(...) printf(__VA_ARGS__);printf("\r\n")/* e.g., printf(__VA_ARGS__);printf("\r\n") */
/* enable bare metal(no OS) platform */
/* #define CMB_USING_BARE_METAL_PLATFORM */
/* enable OS platform */
#define CMB_USING_OS_PLATFORM
/* OS platform type, must config when CMB_USING_OS_PLATFORM is enable */
#define CMB_OS_PLATFORM_TYPE CMB_OS_PLATFORM_FREERTOS
/* cpu platform type, must config by user */
#define CMB_CPU_PLATFORM_TYPE CMB_CPU_ARM_CORTEX_M4 /* CMB_CPU_ARM_CORTEX_M0 or CMB_CPU_ARM_CORTEX_M3 or CMB_CPU_ARM_CORTEX_M4 or CMB_CPU_ARM_CORTEX_M7 */
/* enable dump stack information */
#define CMB_USING_DUMP_STACK_INFO
/* language of print information */
/* #define CMB_PRINT_LANGUAGE CMB_PRINT_LANGUAGE_ENGLISH(default) or CMB_PRINT_LANGUAGE_CHINESE */
#define CMB_PRINT_LANGUAGE CMB_PRINT_LANGUAGE_CHINESE
#endif /* _CMB_CFG_H_ */
(4)task.c修改
static void prvInitialiseNewTask添加
pxNewTCB->uxSizeOfStack = ulStackDepth; /< Support For CmBacktrace >/
(5)FreeRTOS.h修改
5、测试
测试使用官方demo里的用例测试
串口输出:
addline查看错误具体位置
这里的axf文件是自己工程生成的axf文件,addline的使用可参考我最开始贴的链接使用。