c - STM32L072KBU 从应用程序代码跳转到引导加载程序(系统内存)

标签 c embedded stm32

我想从 STM32L072KBUx 微 Controller 中的用户应用程序跳转到系统内存。

我认为有人已经回答了这个问题,但不幸的是,我不明白这段代码:

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();

是否可以使用内部EEPROM代替flash来进行跳转?

如果有人可以帮助我在我自己的应用程序中使用此代码,我将不胜感激。

非常感谢。

最佳答案

您根本不需要 FLASH 调用。这些是一些检查,用于验证是否已存储有效的应用程序代码。

只需从引导加载程序 vector 表中加载堆栈指针和复位地址,然后跳转到复位地址即可。

void (*JumpToSystemBootloader)(void);

// set vector table start address
// volatile uint32_t addr = 0x1FFF0000;  // for STM32F4
volatile uint32_t addr = 0x1FF00000;  // for STM32L07xxx


// load reset vector address @+0x4
JumpToSystemBootloader = (void (*)(void)) (*((uint32_t *)(addr + 4)));  

// load stack pointer address @+0x0
__set_MSP(*(uint32_t *)addr);       

// jump to address loaded previously from @+0x4
JumpToSystemBootloader();

在进入系统引导加载程序之前,您可能还需要禁用所有中断并恢复多个 Controller 状态。

另请参阅:https://stm32f4-discovery.net/2017/04/tutorial-jump-system-memory-software-stm32/

编辑2: 只要bank1或bank2中有效的堆栈指针驻留在 vector 表中,设备的新引导加载程序版本总是会再次跳转到应用程序代码。 如果从应用程序代码跳转到引导加载程序,情况也是如此。

编辑3: 您提供的代码是某种强制进入引导加载程序的黑客方法。 因此,Flash ROM 的某个位置存储有一个魔字。 在重新输入应用程序代码的早期阶段, 检查此值以重新进入引导加载程序。 为了绕过库检查,提供了一个新的跳转地址(0x1FF00369)。 (通过逆向工程确定?) 假设 Controller 和 RAM 之前已正确初始化。

因为供应商可以随时更改引导加载程序代码 应谨慎使用此代码片段。 我的建议是根本不要使用此代码。

使用 SRAM 中的魔法值跳转到引导加载程序[不适用于生产]

引用:https://stackoverflow.com/a/43072025/5388805

// vector table start address (STM32L07xxx)
volatile uint32_t   u32_boot_vector_addr   = 0x1FF00000;  

// bootloader bypass offset address
volatile uint32_t   u32_boot_vector_offset = 0x369;                             // substituted from https://stackoverflow.com/a/43072025/5388805 

// bootloader check definitions
volatile uint32_t * pu32_boot_tag          = (volatile uint32_t *)0x20001800;   // AN2606 states bootloader uses up to 5kByte RAM, add some offset
const uint32_t      u32_boot_tag_reenter   = 0xCAFEFEED;
const uint32_t      u32_boot_tag_clear     = 0xFFFFFFFF;

// call this at an early stage during startup (preferably right after entering the reset routine)
void checkBootloader()
{
    // if magic tag is set jump back to bootloader
    if (*pu32_boot_tag == u32_boot_tag_reenter)
    {
        // erase magic tag
        *pu32_boot_tag = u32_boot_tag_clear;

        // load bypass address
        void (*JumpToSystemBootloader)(void) = (void (*)(void)) (*((uint32_t *)(u32_boot_vector_addr + u32_boot_vector_offset)));  

        // load stack pointer address @+0x0
        __set_MSP(*(uint32_t *)u32_boot_vector_addr);       

        // jump to bypass address
        JumpToSystemBootloader();
    }
}

// call this anywhere from your application code
void jumpToBootloader()
{
    // set magic tag
    *pu32_boot_tag = u32_boot_tag_reenter;

    // load reset vector address @+0x4
    void (*JumpToSystemBootloader)(void) = (void (*)(void)) (*((uint32_t *)(u32_boot_vector_addr + 4)));  

    // load stack pointer address @+0x0
    __set_MSP(*(uint32_t *)u32_boot_vector_addr);       

    // jump to address loaded previously from @+0x4
    JumpToSystemBootloader();
}

关于c - STM32L072KBU 从应用程序代码跳转到引导加载程序(系统内存),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56438811/

相关文章:

我可以将两个端口的位相加来形成新的位序列吗?

stm32 - 如何确定目标内部Flash的大小?

c - 关于 K&R 的问题 - 重定向输入

c - 嵌入式C函数宏问题

在 C-mbed 平台中每 10 秒调用一个函数

c - USART3初始化STM32F103RB

STM32 bootloader删除失败

cmake - 带有 CMake 的 STM32 项目

c - 编写混合 MPI/OpenACC 程序

c - 在 C 中使用进程