CH579(M0内核)中断向量表偏移处理

针对CH579(M0内核)单片机,由于不支持VTOR设置中断向量表偏移,文章介绍了如何将中断向量表重映射到RAM中,包括将所有中断函数设置为同一映射函数、编写映射函数、修改RAM配置信息以及在跳转到App前拷贝App的中断向量表到RAM,确保中断处理正确。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通常情况下,为了产品后续的升级,程序都会分为两部分Bootloader+App,因为有两个程序,所以需要对中断向量表进行处理,否则,当程序已经跳转到app中运行,当中断产生的时候,响应函数仍然是Bootloader的中断函数,而不是app的
在STM32F103 M3内核上是可以配置寄存器SCB->VTOR设置中断向量表偏移,CH579是M0内核,并不支持这样操作,中断向量表位置固定在(地址0x00000000)位置上

解决思路:

  1. 将中断向量表重映射到RAM(内存)
  2. 根据当前运行程序将FLASH中的向量表拷贝到RAM中

解决步骤

  1. 将地址0x00000000的中断向量表中的全部中断函数都设置为同一个函数,用于映射
  2. 编写映射函数
  3. 修改RAM配置信息
  4. 根据前当前运行的程序拷贝中断向量表到RAM

(注意:以下代码都是编写在Bootloader程序中)
第一步:设置映射
这里利用编译器设置函数属性的就可以简单实现

#define ALIAS(x) __attribute__ ((alias (#x)))

void NMI_Handler(void)      ALIAS(interrupt_vector_relay);
void HardFault_Handler(void)ALIAS(interrupt_vector_relay);
void SVC_Handler(void)      ALIAS(interrupt_vector_relay);
void PendSV_Handler(void)   ALIAS(interrupt_vector_relay);
void SysTick_Handler(void)  ALIAS(interrupt_vector_relay);
通常情况下,为了产品后续的升级,程序都会分为两部分Bootloader+App,因为有两个程序,所以需要对中断向量表进行处理,否则,当程序已经跳转到app中运行,当中断产生的时候,响应函数仍然是Bootloader的中断函数,而不是app的 在STM32F103 F3内核上是可以配置寄存器SCB->VTOR设置中断向量表偏移,CH579是M0内核,并不支持这样操作,中断向量表位置固定在(地址0x00000000)位置上 解决思路: 将中断向量表重映射到RAM(内存) 根据当前运行程序将FLASH中的向量表拷贝到RAM中 解决步骤 将地址0x00000000中断向量表中的全部中断函数都设置为同一个函数,用于映射 编写映射函数 修改RAM配置信息 根据前当前运行的程序拷贝中断向量表到RAM (注意:以下代码都是编写在Bootloader程序中) 第一步:设置映射 这里利用编译器设置函数属性的就可以简单实现 #define ALIAS(x) __attribute__ ((alias (#x))) void NMI_Handler(void) ALIAS(interrupt_vector_relay); void HardFault_Handler(void)ALIAS(interrupt_vector_relay); void SVC_Handler(void) ALIAS(interrupt_vector_relay); void PendSV_Handler(void) ALIAS(interrupt_vector_relay); void SysTick_Handler(void) ALIAS(interrupt_vector_relay); void TMR0_IRQHandler(void) ALIAS(interrupt_vector_relay); void GPIO_IRQHandler(void) ALIAS(interrupt_vector_relay); void SLAVE_IRQHandler(void) ALIAS(interrupt_vector_relay); void SPI0_IRQHandler(void) ALIAS(interrupt_vector_relay); void BB_IRQHandler(void) ALIAS(interrupt_vector_relay); void LLE_IRQHandler(void) ALIAS(interrupt_vector_relay); void USB_IRQHandler(void) ALIAS(interrupt_vector_relay); void ETH_IRQHandler(void) ALIAS(interrupt_vector_relay); void TMR1_IRQHandler(void) ALIAS(interrupt_vector_relay); void TMR2_IRQHandler(void) ALIAS(interrupt_vector_relay); void UART0_IRQHandler(void) ALIAS(interrupt_vector_relay); void UART1_IRQHandler(void) ALIAS(interrupt_vector_relay); void RTC_IRQHandler(void) ALIAS(interrupt_vector_relay); void ADC_IRQHandler(void) ALIAS(interrupt_vector_relay); void SPI1_IRQHandler(void) ALIAS(interrupt_vector_relay); void LED_IRQHandler(void) ALIAS(interrupt_vector_relay); void TMR3_IRQHandler(void) ALIAS(interrupt_vector_relay); void UART2_IRQHandler(void) ALIAS(interrupt_vector_relay); void UART3_IRQHandler(void) ALIAS(interrupt_vector_relay); void WDT_IRQHandler(void) ALIAS(interrupt_vector_relay); 这里利用**attribute ((alias ()))**,将全部的中断函数都设置为函数interrupt_vector_relay()的别名,通过这样声明函数,所有的中断函数等于interrupt_vector_relay()这个函数 步骤2:编写映射函数 我们只需要读取寄存器查看当前是发生了哪个中断,然后对应跳转到真正执行动作的函数即可 _vector_table_pointer 这个是RAM地址,这里利用RAM前面的0x100字节作为中断向量表存放位置 //中断向量表位置 #define _vector_table_pointer 0x20000000 __asm void interrupt_vector_relay(void) { //IPSR是中断状态寄存器,因为每个中断函数地址是4个字节,因此将读取数值*4(左移两位)得到的就是地址偏移 mrs r0, ipsr; //将值左移2位 lsls r0, r0, #0x02; //从存储器地址取数据到R1 ldr r1, =_vector_table_pointer; //计算出偏移 adds r1, r1, r0; //将该地址的值给r1 ldr r1, [r1]; //跳转到相对应的中断 bx r1; nop } 在跳转到APP前,将APP的中断向量表拷贝到RAM里面即可 //APP的地址,根据实际修改 #define APP_BASE 0x00004000 //拷贝中断向量表 memcpy((void *)(_vector_table_pointer),(void *)(APP_BASE),0x100); . 补充:app的中断函数编写和使用与正常情况下一致,无需特殊处理 但如果在Bootloader需要用到中断,比如使用定时器中断 UINT32 TIM_IRQ_ADDR; TIM_IRQ_ADDR = (UINT32)DFU_TMR0_IRQHandler; memcpy((void *)(_vector_table_pointer + 0x40),&TIM_IRQ_ADDR,4); Bootloader不能直接编写TMR0_IRQHandler() 因为这个名字已经被占用了, 需要自定义一个函数比如DFU_TMR0_IRQHandler(),然后将该函数的地址拷贝到RAM中的特定位置,这里的0x40就是对应定时器的中断函数. 根据上述 帮我生成完整的代码
07-25
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值