与其他在复位时直接跳转到地址 0 的 ARM 控制器不同,Cortex-M 系列从向量表中获取起始地址。如果程序直接加载(没有引导加载程序),向量表位于二进制文件的开头(加载或映射到地址 0)。偏移量 0 处的第一个条目是堆栈指针的初始值,地址 4 处的第二个条目称为复位向量,它包含要执行的第一条指令的地址。
使用引导加载程序加载的程序通常会0x08008000
保留这种安排,并在您的情况下将向量表放在二进制文件的开头。然后重置向量将在0x08008004
。但这是你的应用程序,你应该检查你把向量表放在哪里。提示:查看.map
链接器生成的文件以确定。如果它确实在0x08008000
,那么您可以将控制权转移到应用程序重置向量,这样:
void (*app)(void); // declare a pointer to a function
app = *(void (**)(void))0x08008004; // see below
app(); // invoke the function through the pointer
第二行中的复杂转换将物理地址转换为指向函数指针的指针,获取指向它的值,该值现在是指向函数的指针,并将其分配给app
。
然后,您应该管理到应用程序向量表的切换。您可以在引导加载程序或应用程序中执行此操作,或者在它们之间划分步骤。
- 禁用所有中断并停止 SysTick。注意SysTick 不是一个中断,不要调用
NVIC_DisableIRQ()
它。我会在引导加载程序中执行此步骤,因此它负责禁用已启用的任何内容。
- 将新的向量表地址分配给
SCB->VTOR
。请注意,样板SystemInit()
函数system_stm32l1xx.c
无条件地变SCB->VTOR
回 flash 的开头,即0x08000000
,您应该编辑它以使用正确的偏移量。
您也可以从向量表中加载堆栈指针值,但要正确执行此操作很棘手,而且并非真正必要,应用程序可以继续使用在引导加载程序中设置的堆栈。只需检查它以确保它是合理的。