首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么需要在从引导加载器跳转到应用程序之前更新堆栈指针?

为什么需要在从引导加载器跳转到应用程序之前更新堆栈指针?
EN

Stack Overflow用户
提问于 2019-12-23 16:02:46
回答 1查看 2.7K关注 0票数 4

当从引导器跳转到应用程序时,我们通常会将堆栈指针更新到应用程序堆栈指针,然后将程序计数器更新为应用程序的Reset_Handler。

代码语言:javascript
运行
复制
void jump_to_application(void)
{
    /* Function pointer to the address of the user application. */
    fnc_ptr_for_app jump_to_app;
    jump_to_app = (fnc_ptr_for_app)(*(volatile uint32_t*) (FLASH_APP_START_ADDRESS+4u));
    __CRC_CLK_DISABLE();
    HAL_DeInit();

    /* Change the main stack pointer. */
    __set_MSP(*(volatile uint32_t*)FLASH_APP_START_ADDRESS);

    jump_to_app();
}

Reset_Handler的第一行代码如下所示,它将堆栈指针初始化为自己的堆栈指针值

代码语言:javascript
运行
复制
Reset_Handler:
ldr   sp, =_estack    /* Atollic update: set stack pointer */

/* Copy the data segment initializers from flash to SRAM */
movs    r1, #0
b   LoopCopyDataInit

但是仍然建议用应用程序的指针更新堆栈指针。

为什么需要它,如果我们跳过而不更新它会产生什么副作用?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-23 16:25:17

在ARM Cortex-M中,初始堆栈指针存储在向量表的前4个字节中,初始程序计数器存储在第二个4个字节中。在重置时,硬件从这8个字节加载SP和PC。例如,这允许用C而不是汇编程序编写Cortex-M启动代码.

引导加载器模拟这种重置行为,方法是将硬件去初始化到它的重置状态,并从应用程序的向量表中加载SP和PC。这允许应用程序启动,就好像它是从重置开始的,而不依赖于引导加载程序的任何初始化或设置。

引导加载程序是独立于应用程序编译和链接的,并且必须能够用适当的起始地址加载任何应用程序代码。因此,引导加载程序无法确定或强制执行加载的任何应用程序代码都将设置堆栈指针,因为它可能合理地假定硬件已经设置了堆栈指针。同样,在这种情况下,_estack != *(volatile uint32_t*)FLASH_APP_START_ADDRESS)在任何情况下都是完全可能的。

但是,引导加载器上的一个注意事项是,它没有将向量表设置为应用程序的表,这是潜在的危险--如果启动代码允许中断而不首先设置向量表,则可能会导致引导加载程序中断处理程序被错误地调用。更安全的做法是:

代码语言:javascript
运行
复制
// Switch vector table
SCB->VTOR = APPLICATION_START_ADDR ;

jump_to_app()之前。或者如果您选择使用HAL:

代码语言:javascript
运行
复制
NVIC_SetVectorTable( NVIC_VectTab_FLASH, APPLICATION_START_ADDR ) ;
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59458156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档