0

I want to jump to system memory from user application in STM32L072KBUx microcontroller.

I think someone has already answered this question but unfortunately, I don't understand this code:

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

Is it possible to use Internal EEPROM instead of using flash to do jumping?

I would greatly appreciate it if someone can help me to use this code in my own application.

Thanks so much.

1 Answers1

1

You don't need the FLASH calls at all. These are some checks to validate if a valid application code has been stored.

Just load the stack pointer and reset address from the bootloader vector table and jump to the reset address.

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

You probably need to disable also all interrupts and restore several controller states before entering the system bootloader.

See also: https://stm32f4-discovery.net/2017/04/tutorial-jump-system-memory-software-stm32/

Edit2: New bootloader versions of the device always jumps to the application code again as long as in either bank1 or bank2 valid stack pointer resides in the vector table. This is also the case if jumping to the bootloader from the application code.

Edit3: Your provided code is some hacky way to force entering the bootloader anyway. Therefore a magic word is stored in some place of the flash rom. And during reentering the application code, at an early stage, this value is checked to reenter the bootloader. To bypass the bank check a new jump address is supplied (0x1FF00369). (Determined by reverse engineering?) It is assumed that the controller and the RAM is previously already initialized correctly.

Because the vendor can change the bootloader code whenever he want the use of this code snippet should be done with caution. My suggestion is not to use this code at all.

Jump To Bootloader using magic value in SRAM [not for production]

Reference: 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();
}
veeman
  • 780
  • 1
  • 8
  • 17
  • Hi mate, thanks for your help but this one it’s not going to work. Stm32l072 has different boot loader mechanism because of dual bank of flash memory. Please have a look of stm system memory document. – Ahmad Shokati Jun 04 '19 at 09:52
  • For STM32L07xxx use 0x1FF00000 as system bootloader vector table address. The dual bank configuration of the device affects only how the lower address region is mapped and how the device during system sartup/reset decides wich bank to setup to run the user application code. If you jump directly to the bootloader in the upper address space it should work without any furhter settings. – veeman Jun 04 '19 at 11:15
  • https://stackoverflow.com/questions/42020893/stm32l073rz-rev-z-iap-jump-to-bootloader-system-memoryI have used this address 0x1ff00000 to jump to the boot loader but it didn’t work. Could you please have a look at this link: – Ahmad Shokati Jun 04 '19 at 11:28
  • It seems that st updated the bootloader and this bootloader decides when to enter the application code. As long as either bank1 or bank2 contains valid application code, in case the fist entry in the vector table (stack pointer) points to the sdram location, it will always enter the application code again. Call it a feature. Anyway i added a brief explanation what the provided code does. I think instead of storing the magic value in flash you can also do it in a unused sdram location. – veeman Jun 04 '19 at 13:01
  • Hi veeman, thanks for your information. So do you think is there any better way to jump to system memory for user application in this case? – Ahmad Shokati Jun 04 '19 at 22:12
  • I added an example wich uses a magic value stored in SRAM instead in Flash. I cant test it because i have no such device here. But it could work for the specified device with the given bootloader. I also do not check if the bypass address is correct. You must simple try it. Also it may break in the feature on new devices if the vendor updates the bootloader code. – veeman Jun 05 '19 at 10:32
  • Hi mate, I really appreciate your support. As you said using built-in bootloader in this way is device dependent. – Ahmad Shokati Jun 05 '19 at 23:19