/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
*
© Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* 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 "stm32f1xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* 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 -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern TIM_HandleTypeDef htim1;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M3 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
__WEAK void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f1xx.s). */
/******************************************************************************/
/**
* @brief This function handles TIM1 update interrupt.
*/
void TIM1_UP_IRQHandler(void)
{
/* USER CODE BEGIN TIM1_UP_IRQn 0 */
/* USER CODE END TIM1_UP_IRQn 0 */
HAL_TIM_IRQHandler(&htim1);
/* USER CODE BEGIN TIM1_UP_IRQn 1 */
/* USER CODE END TIM1_UP_IRQn 1 */
}
/* USER CODE BEGIN 1 */
struct exception_stack_frame
{
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;
};
struct stack_frame
{
#if USE_FPU
rt_uint32_t flag;
#endif /* USE_FPU */
/* r4 ~ r11 register */
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;
struct exception_stack_frame exception_stack_frame;
};
struct exception_info
{
rt_uint32_t exc_return;
struct stack_frame stack_frame;
};
#include
#include
#if defined(__ARMCC_VERSION)
/* C stack block name, default is STACK */
#ifndef CMB_CSTACK_BLOCK_NAME
#define CMB_CSTACK_BLOCK_NAME Image$$ARM_LIB_STACK$$ZI
#endif
/* code section name, default is ER_IROM1 */
#ifndef CMB_CODE_SECTION_NAME
#define CMB_CODE_SECTION_NAME FLASH_CODE
#endif
#elif defined(__ICCARM__)
/* C stack block name, default is 'CSTACK' */
#ifndef CMB_CSTACK_BLOCK_NAME
#define CMB_CSTACK_BLOCK_NAME "CSTACK"
#endif
/* code section name, default is '.text' */
#ifndef CMB_CODE_SECTION_NAME
#define CMB_CODE_SECTION_NAME ".text"
#endif
#elif defined(__GNUC__)
/* C stack block start address, defined on linker script file, default is _sstack */
#ifndef CMB_CSTACK_BLOCK_START
#define CMB_CSTACK_BLOCK_START _sstack
#endif
/* C stack block end address, defined on linker script file, default is _estack */
#ifndef CMB_CSTACK_BLOCK_END
#define CMB_CSTACK_BLOCK_END _estack
#endif
/* code section start address, defined on linker script file, default is _stext */
#ifndef CMB_CODE_SECTION_START
#define CMB_CODE_SECTION_START _stext
#endif
/* code section end address, defined on linker script file, default is _etext */
#ifndef CMB_CODE_SECTION_END
#define CMB_CODE_SECTION_END _etext
#endif
#else
#error "not supported compiler"
#endif
#if __STDC_VERSION__ < 199901L
#error "must be C99 or higher. try to add '-std=c99' to compile parameters"
#endif
#if defined(__CC_ARM)
#define SECTION_START(_name_) _name_##$$Base
#define SECTION_END(_name_) _name_##$$Limit
#define IMAGE_SECTION_START(_name_) Image$$##_name_##$$Base
#define IMAGE_SECTION_END(_name_) Image$$##_name_##$$Limit
#define CSTACK_BLOCK_START(_name_) SECTION_START(_name_)
#define CSTACK_BLOCK_END(_name_) SECTION_END(_name_)
#define CODE_SECTION_START(_name_) IMAGE_SECTION_START(_name_)
#define CODE_SECTION_END(_name_) IMAGE_SECTION_END(_name_)
extern const int CSTACK_BLOCK_START(CMB_CSTACK_BLOCK_NAME);
extern const int CSTACK_BLOCK_END(CMB_CSTACK_BLOCK_NAME);
extern const int CODE_SECTION_START(CMB_CODE_SECTION_NAME);
extern const int CODE_SECTION_END(CMB_CODE_SECTION_NAME);
#elif defined(__ICCARM__)
#pragma section=CMB_CSTACK_BLOCK_NAME
#pragma section=CMB_CODE_SECTION_NAME
#elif defined(__GNUC__)
extern const int CMB_CSTACK_BLOCK_START;
extern const int CMB_CSTACK_BLOCK_END;
extern const int CMB_CODE_SECTION_START;
extern const int CMB_CODE_SECTION_END;
#else
#error "not supported compiler"
#endif
static bool is_in_text(uint32_t addr)
{
#if 0
uint32_t code_start_addr = (uint32_t)&CODE_SECTION_START(CMB_CODE_SECTION_NAME);
uint32_t code_size = (uint32_t)&CODE_SECTION_END(CMB_CODE_SECTION_NAME) - code_start_addr;
#else
uint32_t code_start_addr = (uint32_t)__section_begin(CMB_CODE_SECTION_NAME);
uint32_t code_size = (uint32_t)__section_end(CMB_CODE_SECTION_NAME) - code_start_addr;
#endif
if (code_start_addr < addr && addr <= code_start_addr + code_size)
{
return true;
}
return false;
}
static bool disassembly_ins_is_bl_blx(uint32_t addr)
{
#define BL_INS_MASK 0xF800
#define BL_INS_HIGH 0xF800
#define BL_INS_LOW 0xF000
#define BLX_INX_MASK 0xFF00
#define BLX_INX 0x4700
uint16_t ins1 = *((uint16_t *)addr);
uint16_t ins2 = *((uint16_t *)(addr + 2));
if ((ins2 & BL_INS_MASK) == BL_INS_HIGH && (ins1 & BL_INS_MASK) == BL_INS_LOW)
{
return true;
}
else if ((ins2 & BLX_INX_MASK) == BLX_INX)
{
return true;
}
else
{
return false;
}
}
void rt_hw_hard_fault_exception(struct exception_info *exception_info)
{
//struct exception_stack_frame *exception_stack = &exception_info->stack_frame.exception_stack_frame;
struct stack_frame *context = &exception_info->stack_frame;
rt_kprintf("psr: 0x%08x\n", context->exception_stack_frame.psr);
rt_kprintf("r00: 0x%08x\n", context->exception_stack_frame.r0);
rt_kprintf("r01: 0x%08x\n", context->exception_stack_frame.r1);
rt_kprintf("r02: 0x%08x\n", context->exception_stack_frame.r2);
rt_kprintf("r03: 0x%08x\n", context->exception_stack_frame.r3);
rt_kprintf("r04: 0x%08x\n", context->r4);
rt_kprintf("r05: 0x%08x\n", context->r5);
rt_kprintf("r06: 0x%08x\n", context->r6);
rt_kprintf("r07: 0x%08x\n", context->r7);
rt_kprintf("r08: 0x%08x\n", context->r8);
rt_kprintf("r09: 0x%08x\n", context->r9);
rt_kprintf("r10: 0x%08x\n", context->r10);
rt_kprintf("r11: 0x%08x\n", context->r11);
rt_kprintf("r12: 0x%08x\n", context->exception_stack_frame.r12);
rt_kprintf(" lr: 0x%08x\n", context->exception_stack_frame.lr);
rt_kprintf(" pc: 0x%08x\n", context->exception_stack_frame.pc);
rt_kprintf("use command: addr2line -e your.out -a -f ");
rt_kprintf("%08x ", context->exception_stack_frame.pc);
rt_kprintf("%08x ", context->exception_stack_frame.lr);
uint32_t lr;
uint32_t pc;
uint32_t *app_sp = (unsigned int *)(exception_info + 1); // 得到栈顶;
for(int i = 0; i < 1024; i++)
{
lr = *app_sp;
app_sp++;
if ((lr & 0x01) && true == is_in_text(lr))
{
pc = (lr & ~0x01) - 4;
if (true == disassembly_ins_is_bl_blx(pc))
{
rt_kprintf("%08x ", pc);
}
}
}
while(1);
}
void svc_exception(struct exception_info *exception_info)
{
//struct exception_stack_frame *exception_stack = &exception_info->stack_frame.exception_stack_frame;
struct stack_frame *context = &exception_info->stack_frame;
unsigned int addr;
unsigned short swi_inst;
unsigned int *old_sp;
unsigned int value;
/* 取出swi指令 */
addr = context->exception_stack_frame.pc;
addr -= 2;
swi_inst = *((unsigned short *)addr);
rt_kprintf("swi_inst = 0x%04x\n", swi_inst);
swi_inst = swi_inst & 0xff;
/* 分析swi指令 */
old_sp = (unsigned int *)(exception_info + 1); // 得到栈顶
unsigned int *p_reg = &context->exception_stack_frame.r0; // 得到r0的地址
if (swi_inst == 0xff)
{
/* POP {PC} */
value = *old_sp;
old_sp++;
context->exception_stack_frame.pc = value;
}
else
{
for (int i = 0; i < 8; i ++)
{
if (swi_inst & (1 << i))
{
/* POP {r0, PC} */
value = *old_sp;
old_sp++;
p_reg[i] = value; // 哪个寄存器就保存哪个值
/* POP {PC} */
value = *old_sp;
old_sp++;
context->exception_stack_frame.pc = value;
}
}
}
rt_kprintf("old_sp = 0x%0x\n", old_sp);
rt_kprintf("context->exception_stack_frame.pc= 0x%0x\n", context->exception_stack_frame.pc);
/* 模拟swi指令 */
struct exception_info stack_frame = *exception_info;
unsigned int old_pos = (unsigned int)(exception_info + 1);
unsigned int new_pos = (unsigned int)old_sp;
unsigned int offset = new_pos - old_pos;
exception_info = (struct exception_info *)((unsigned int)exception_info + offset);
*exception_info = stack_frame;
/* 返回 */
}
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/