Cortex-M0中断向量表偏移
前言
因为公司项目中用到了一个Coretex-M0架构的MCU,需要让我实现bootloader功能,当实现中断向量表偏移时发现这个架构的MCU竟然不支持寄存器设置中断偏移,于是在网上查询之后发现了解决方案,在这里也记录下我的实现。
一、中断向量表重定向
将app的中断向量表拷贝至ram中,在bootloader的中断处理函数判别调用者的身份,选择不同的中断处理函数。
1.1、bootloader 处理
在bootloader中需要重新实现中断处理函数函数 。首先将app的中断向量表拷贝到ram 0x2000 0000 处,定义中断处理函数重映射结构体,然后定义结构体指针指向0x2000 0000地址,最后中断处理函数进行重定义。
定义中断处理函数结构体:
typedef struct
{
void (*pInitial_SP); /* Top of Stack */
void (*pReset_Handler)(void);
void (*pNMI_Handler)(void);
void (*pHardFault_Handler)(void);
void (*pMemManage_Handler)(void);
void (*pBusFault_Handler)(void);
void (*pUsageFault_Handler)(void);
void (*pReserved0_Handler)(void);
void (*pReserved1_Handler)(void);
void (*pReserved2_Handler)(void);
void (*pReserved3_Handler)(void);
void (*pSVCall_Handler)(void);
......
......
void (*pDebugMon_Handler)(void);
void (*pReserved4_Handler)(void);
void (*pUART3_4_IRQHandler)(void);
void (*pFLEXCAN_IRQHandler)(void);
void (*pUSB_IRQHandler)(void);
}NVIC_TABLE_t;
定义结构体指针指向0x2000 0000:
//拷贝中断向量表(注意:这里需要按照自己真实的中断向量表大小进行处理)
for(i = 0; i < 48; i++)
{
*((uint32_t*)(0x20000000 + (i<<2))) = *(__IO uint32_t*)(YTD_APP1_BASE_ADDR + (i<<2));
}
NVIC_TABLE_t* tNVIC_Table = 0x20000000;
中断函数重定义实例:
void UART2_IRQHandler(void){
//如果此时是bootloader
u16 update_flag = 0x0;
flash_read(UPGRADE_FLAGE_ADDR, (uint8_t *)&update_flag, 2); //这里的标识为当跳转app动作发生时写入的表示,读到0xa1b1值即能确认调用者的身份为app,
if(update_flag == 0xa1b1)
tNVIC_Table->pUART2_IRQHandler(); //调用映射的中断处理函数
else
Boot_UART2_IRQHandler(); //bootloader 自己的处理函数
}
1.2、app处理
app程序处理相对简单,只需要重新执行一遍中断向量表拷贝动作即可。因为跳转app时首先进入的是Reset_Handler中断处理函数,对堆栈应该是进行了重新分配,因此需要重新拷贝一次,否则发生中断时将无法找到中断处理函数。
//拷贝中断向量表
for(i = 0; i < 48; i++)
{
*((uint32_t*)(0x20000000 + (i<<2))) = *(__IO uint32_t*)(YTD_APP1_BASE_ADDR + (i<<2));
}
1.3、MDK配置RAM
在程序运行时会使用ram资源,为了防止中断向量表所在位置被占用,需要在keil中配置应用程序(这里包含bootloader和app)的ram使用范围。我这里因为是48个中断:48 * 4 = 192 = 0xc0, 所以设置ram范围为 0x2000000c0 ~
0x20003ffff
本文参考文章:
http://www.weilez.cn/?p=1310
https://mp.weixin.qq.com/s/D-zA7Fb3bHEZM8WsSHHBaQ
https://ask.csdn.net/questions/7918618