在M0内核的芯片中没有向量表偏移量寄存器VTOR,就需要手动帮程序寻找向量表地址。
首先,先分配好boot程序与app程序的Flash地址。我使用的是士兰微公司生产的sc32f5664这块芯片,flash:0x0~0xFFFF(64k),RAM:0x2000 0000~0x2000 17FF(6k)。boot程序在0x0~0x27FF(10K),app程序:0x2800~0xFFFF(54k)。
其次,把RAM中的前0x100字节存放应用程序中断向量表,程序运行空间后移0x100字节。
最后,在boot程序中断函数中,判断是应用程序还是boot程序触发中断,应用程序触发时,跳转至RAM中保存的中断向量表地址。
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
跳转到user区
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
void jumpappfunc(void)
{
uint32_t jumpaddr;
uint32_t applicationaddr = APPFSADDR; //0X2800
if(((*(uint32_t*)applicationaddr)&0x2FFE0000) == 0x20000000) //判断栈空间
{
jumpaddr = *(uint32_t*)(applicationaddr+4);
jumpapp = (iapfun)jumpaddr; //跳转函数在应用程序中断向量表复位中断源
__set_MSP(*(uint32_t*)applicationaddr);
memcpy((void*)0x20000000,(const void*)APPFSADDR,(unsigned int )0x100);//拷贝中断向量表至RAM前0x100字节空间
__disable_irq();
jumpapp(); //开始跳转
}
}
area interrupt_vector_func,code,readonly
export interrupt_vector_relay
interrupt_vector_relay
;ldr r0,ipsr
lsls r0,r0,#0x02
ldr r1,=0x20000000
adds r1,r1,r0
ldr r1,[r1]
bx r1
nop
end
void JumpVectorTable(void)
{
uint32_t flag,addr;
memcpy((void*)&flag,(void *)0XF000,4); //在flash中设置一个标志位,boot程序为0,应用程序为1
addr = (SCB->ICSR&0x3F); //判断中断异常触发是什么
if(flag)
interrupt_vector_relay(addr); //跳转至中断向量表函数,汇编代码执行,在上面
}
void UART0_IRQHandler(void) //每个中断函数都进行判断
{
JumpVectorTable();
}
void UART1_IRQHandler(void)
{
JumpVectorTable();
}