STM32L073RZ(版本Z)IAP跳转到引导加载程序(系统内存)

STM32L073RZ(版本Z)IAP跳转到引导加载程序(系统内存),stm32,bootloader,Stm32,Bootloader,我使用STM32L073RZ(核仁64板) 我想跳到应用程序编程(IAP)的系统内存中 我的代码在STM32L073微控制器的版本B上工作,但在最新版本Z上失败 我阅读了勘误表,没有给出任何细节,只是根据BFB2位对进入系统内存的双引导机制进行了限制 系统内存是否不再支持IAP跳转以执行其代码(通过USB或UART闪存固件而不使用BOOT0引脚) 该函数是我的主程序的第一行,它测试代码是否必须跳转到booloader: void jumpBootLoader(void) { /* to

我使用STM32L073RZ(核仁64板)

我想跳到应用程序编程(IAP)的系统内存中

我的代码在STM32L073微控制器的版本B上工作,但在最新版本Z上失败

我阅读了勘误表,没有给出任何细节,只是根据BFB2位对进入系统内存的双引导机制进行了限制

系统内存是否不再支持IAP跳转以执行其代码(通过USB或UART闪存固件而不使用BOOT0引脚)

该函数是我的主程序的第一行,它测试代码是否必须跳转到booloader:

void jumpBootLoader(void)
{
    /* to do jump? */
    if ( *((unsigned long *)0x20003FF0) == 0xDEADBEEF  ) 
    {
        /* erase the label */
        *((unsigned long *)0x20003FF0) = 0xCAFEFEED;

        /* set stack pointer to the bootloader start address */
        __set_MSP(*((uint32_t*)(0x1FF00000)));

        /* system memory mapped at 0x00000000 */
        __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();

        /* jump to @bootloader + 4 */
        ((void (*)(void))(*((uint32_t*)(0x1FF00004))))();
    }
}   
重置µC后,按下BP1按钮触发跳转操作后,我立即调用这两行:

*((unsigned long *)0x20003FF0) = 0xDEADBEEF;
NVIC_SystemReset();

我使用HSI 16Mhz时钟源。

调用
时,程序计数器在哪里


当您在同一个内存区域外执行时,重新映射该内存区域将导致糟糕的结果!您可能需要将此代码重新定位到SRAM中,或者在PC设置为固定闪存映射(
0x0800xxx
)的情况下执行此代码。

第一件重要的事情:您使用
0x1FF0 0000
作为存储SP的地址,这是正确的。然后使用
0x1 FF00 0004
作为加载函数指针的地址。这是不正确的-一个零太多了

请注意,如果同时使用MSP作为堆栈指针(很可能是),则使用
\u set\u MSP()
通常不是一个好主意。该函数的最新定义将“sp”标记为clobbered register,导致您的更改几乎立即恢复。顺便说一句,今天我做的和你做的完全一样,我发现了这个问题。在程序集列表中,您将看到SP被保存到
msr msp,…
指令之前的其他寄存器中,然后立即恢复

最后,我手动编写了(STM32F4,不同的地址):

constexpr uint32\u t systemMemoryBase{0x1ff0000};
挥发性物质
(
msr msp,%[sp]\n
“bx%[pc]\n”
:[sp]“r”(*重新解释_cast(systemMemoryBase)),
[pc]“r”(*重新解释(systemMemoryBase+4))
);

顺便说一句,您不需要设置内存重新映射,引导加载程序就可以工作。

谢谢您的帮助。我有我的答案

v4.0引导加载程序(初始版本)未实现双银行机制,但v4.1支持此功能

软件可以跳转到引导加载程序,但它将执行双引导机制。 因此引导加载程序返回bank1(如果代码“有效”,则返回bank2)

今天,不可能绕过双银行机制来使用我的配置执行引导加载程序:
boot0引脚复位,保护级别为0(请参阅参考手册中的“表11.boot0引脚和BFB2位配置”)。

解决方案是两次跳转到系统内存。 首先跳转到引导加载程序启动以初始化RAM中的数据,直到程序计数器由Dualbank管理返回闪存。 第二次跳转:跳转到Dualbank绕过的地址

如何使用:用户必须首先在闪存中初始化变量“Data_Address”(必须是偏移闪存扇区对齐地址),以区分第一次/第二次跳转

EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = Data_Address;
EraseInitStruct.NbPages     = 1;


    First_jump = *(__IO uint32_t *)(Data_Address);

    if (First_jump == 0) {  
        HAL_FLASH_Unlock();
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Data_Address, 0xAAAAAAAA);
        HAL_FLASH_Lock();

        /* Reinitialize the Stack pointer and jump to application address */ 
        JumpAddress = *(__IO uint32_t *)(0x1FF00004);
    }
    if (First_jump != 0) {  
        HAL_FLASH_Unlock();
        HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
        HAL_FLASH_Lock();

        /* Reinitialize the Stack pointer and jump to application address */ 
        JumpAddress =  (0x1FF00369);
    }

    Jump_To_Application = (pFunction) JumpAddress;
    __set_MSP(*(__IO uint32_t *)(0x1FF00000));
    Jump_To_Application(); 

如果您不向我们展示代码,很可能没有人能够帮助您…很抱歉“0x1FF0 0 0004”,我的代码复制/过期失败,我在帖子中更正了它。它是C++代码吗?“constexpr”和“reinterpret_cast”不是为我编译的,我使用了“const”和一个简单的cast表达式(uint32_t*)。我在没有调用uu set_MSP()的情况下测试了我的代码,它仍然有效…@hbevil-是的,我发布的代码片段是C++11,但是您的更改也可以。至于你剩下的评论——“它仍然有效……”或者它仍然无效?(;是的,它在stm32l073修订版B上“仍然有效”,在修订版Z上“仍然无效”,尽管它是相同的代码……我发现引导加载程序的版本不同,版本B为v4.0,版本Z为4.1。@hbevil-即使在main()中跳转到引导加载程序是您要做的第一件事),这并不意味着这是固件要做的第一件事。如果使用HAL/SPL,很可能RCC中的时钟在main()之前初始化,执行引导加载程序的要求之一是使用“重置状态”运行它所有内容,包括RCC时钟和PLL设置。请在问题中发布更新的代码,并验证程序集输出是否正确(您也可以在此处发布)。
EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = Data_Address;
EraseInitStruct.NbPages     = 1;


    First_jump = *(__IO uint32_t *)(Data_Address);

    if (First_jump == 0) {  
        HAL_FLASH_Unlock();
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Data_Address, 0xAAAAAAAA);
        HAL_FLASH_Lock();

        /* Reinitialize the Stack pointer and jump to application address */ 
        JumpAddress = *(__IO uint32_t *)(0x1FF00004);
    }
    if (First_jump != 0) {  
        HAL_FLASH_Unlock();
        HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
        HAL_FLASH_Lock();

        /* Reinitialize the Stack pointer and jump to application address */ 
        JumpAddress =  (0x1FF00369);
    }

    Jump_To_Application = (pFunction) JumpAddress;
    __set_MSP(*(__IO uint32_t *)(0x1FF00000));
    Jump_To_Application();