STM32103 自定义引导加载程序 - 跳转到主要固件问题

STM32103 custom bootloader - jump to main firmware issue

我已根据我在此处找到的示例 (lbus) 成功为 STM32103C8T6 芯片实现了 CAN 总线引导加载程序 https://github.com/alphalove/stm32-projects/tree/master/lbus_bootloader

我用过libopencm3.

在我对引导加载程序代码做了一个非常小的更改之前,我的这个工作一直很好。之后,bootloader 将不再启动主固件。

引导加载程序从 0x08000000 开始,大小为 8k。 主固件从0x08002000开始。

除此之外,booloader 还会检查主固件的完整性,如果正常,则通过调用 run_firmware() 函数启动它。该函数在设置向量 table 地址、初始化主堆栈指针、然后跳转到主固件的开始之前关闭引导加载程序中使用的所有芯片外设。 run_firmware() 函数的示例/片段如下。

#define FW_ADDR    0x08002000

run_firmware() {     // Set vector table base address.
   // bunch of code to reset all peripherals

   // Set Vector Table address
   SCB_VTOR = FW_ADDR & 0xFFFF;

   // Initialise master stack pointer
   __asm__ volatile("msr msp, %0"::"g"(*(volatile uint32_t *)FW_ADDR));

   // Jump to application
   (*(void (**)())(FW_ADDR + 4))();
}

直到今天,我添加了一些额外的引导加载程序代码,这些代码也调用了 run_firmware() 函数,这一直运行良好。现在调用 run_firmware 函数不会启动主固件,而是在看门狗重置芯片之前失败。虽然第二次调用 run_firmware() 是在代码中,但该函数不再有效。

这是地址跳转的限制吗?添加额外的调用是否改变了现在导致问题的二进制文件中 run_firmware() 代码的位置? asm 中的 %0 和 "g" 在做什么?

老实说,启动主固件的代码是我从上面链接的 lbus 示例中借用的黑魔法。所以我不太确定为什么会失败。

如果你看不出来...我是个硬件爱好者!

任何指导将不胜感激!

提前致谢。

亚历克斯

跳转地址没有限制,但必须放在扇区的起始地址。要解决您的问题,请确保您的引导加载程序代码大小不超过 8 KB,如果增加引导加载程序的大小并更改主应用程序的起始地址

  1. 使用由 STM 寄存器定义提供的标准。
  2. 您的 VTOR 分配有误
    //FW_ADDR has to be aligned to 0x100
    SCB -> VTOR = FW_ADDR;
    __set_MSP(*(volatile uint32_t *)FW_ADDR);
  1. 跳转到应用程序开始:
    void (*start)(void) = (void *)*(volatile uint32_t *)(FW_ADDR + 4);
    start();

或者如果你喜欢怪异的表达方式

    ((void(*)(void))(FW_ADDR + 4))();

请记住,必须链接您的应用才能匹配新的起点。

static inline __attribute__((always_inline)) void __set_MSP(uint32_t topOfMainStack)
{
  __asm volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
}

@P_J_,谢谢你的帮助,它确实帮助我理解了跳转到主固件的机制。

就是说,我找到了解决问题的方法而不是正确的解决方案(因为主固件的 FW_ADDR 似乎正确对齐,并且在工作版本和非工作版本之间没有变化引导加载程序)。

我刚刚添加

static inline __attribute__((always_inline)) 

到我的 run_firmware() 函数,它现在可以在 main() 中调用的两个地方正常工作。现在就可以了!

再次感谢您的宝贵时间!

干杯,

亚历克斯

没有足够的评论点,但我想补充一点,有 github 项目 (marcinbor85/can-prog) 支持通过 stm32 的内置 (rom) 引导加载程序进行引导。

不确定 Alex 是否会开源他的引导加载程序,但有很多蓝色药丸可以从中受益(包括我的!)