这将适用于任何 Cortex-M 部分......
创建一个汇编函数,如:
__asm void boot_jump( uint32_t address )
{
LDR SP, [R0] ;Load new stack pointer address
LDR PC, [R0, #4] ;Load new program counter address
}
内联汇编语法各不相同;这个例子是 Keil ARM-MDK / ARM RealView。
然后在引导加载程序结束时:
// Switch off core clock before switching vector table
SysTick->CTRL = 0 ;
// Switch off any other enabled interrupts too
...
// Switch vector table
SCB->VTOR = APPLICATION_START_ADDR ;
//Jump to start address
boot_jump( APPLICATION_START_ADDR ) ;
请注意,在这种情况下,APPLICATION_START_ADDR 是链接应用程序代码的基地址或位置地址(在这种情况下为 0x3200),而不是链接映射中指示的入口点。应用程序向量表位于该地址,向量表的开头包含应用程序的初始堆栈指针地址和程序计数器(实际代码入口点)。
该boot_jump()
函数从应用程序的向量表中加载堆栈指针和程序计数器,模拟复位时从闪存的基址(引导加载程序的向量表)加载它们时发生的情况。
请注意,您必须在应用程序代码的链接器设置中将起始地址设置为与引导加载程序将复制映像的起始地址相同。如果您使用的是 Keil 调试器,您将无法在没有引导加载程序存在的情况下在调试器中加载和运行应用程序(或者至少在没有正确手动设置 SP 和 PC 或使用调试器脚本的情况下),因为调试器会加载重置向量地址而不是应用程序向量地址。
在切换向量表之前禁用中断很重要,否则在应用程序初始化之前发生的任何中断都将向量到应用程序的处理程序,并且可能还没有准备好。
请注意您在应用程序和引导代码中使用的任何外围设备,如果外围寄存器已由引导代码设置,则有关复位条件的任何假设都可能不成立。