cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L475RG - Having trouble jumping between multiple .bin programs in flash, program stops working.

RSikk.493
Associate II

CURRENT PRODUCT

Our existing devices have a custom USB DFU bootloader starting at address 0x08000000. Our main application starts at 0x08008000, after 32Kb of space. I can jump from the main app to the bootloader with no issues (using a NVIC_Systemreset) and back from the bootloader to the main application.

NEW FEATURE

I need to extend the capability of the bootloader to include OTA, however, existing customers are not able to re-program the bootloader without special tools. So the bootloader code (0x08000000) portion MUST stay the same.

ATTEMPT

My solution is to add the OTA portion at 0x08008000 (PROGRAM 1) and shift the main application up to 0x08010000 (PROGRAM 2). I made adjustments to each linker script and in the system_stm32l4xx.c to ensure the VTOR is 0x08008000 for PROGRAM 1 and 0x08010000 for PROGRAM 2. When I look at the memory map the SP seems correct with each address 0x08008000 and 0x08010000 having a value of 0x20010000.

When I jump I use the following code block from DFU example:

void Jump2App(void)
{
    /* Test if user code is programmed starting from address USBD_DFU_APP_DEFAULT_ADD */
    JumpAddress = *(__IO uint32_t*) (USBD_DFU_APP_DEFAULT_ADD);
    /* At location should be 0x20010000 which when & with 0x2FFE0000 = 0x2000000*/
    if(((*(__IO uint32_t*)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFE0000 ) == 0x20000000)
    {
        /* Jump to user application */
        JumpAddress = *(__IO uint32_t*) (USBD_DFU_APP_DEFAULT_ADD + 4);
        JumpToApplication = (pFunction) JumpAddress;
    
        /* Initialize user application's Stack Pointer */
        __set_MSP(*(__IO uint32_t*) USBD_DFU_APP_DEFAULT_ADD);
        JumpToApplication();
    }
}

In which I have the USDB_DFU_APP_DEFAULT_ADD to 0x08010000 in PROGRAM 1, so PROGRAM 1 should be able to jump to PROGRAM 2.

PROBLEM

I program the device by creating a .DFU file of both PROGRAM binaries at the correct address. I put the device in bootloader mode and then I program the DFU file. The program correctly jumps to my new OTA bootloader code at 0x08008000. The program then correctly jumps to PROGRAM 2 at 0x08010000. However, on power up/down, this no longer works! The device fails to boot-up, and I'm measuring 3.3V at the appropriate pins.

I Am not even sure if my approach is the best solution, regardless, it does not seem to work.

Any help would be appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions
RSikk.493
Associate II

The problem was when flashing the binaries to the chip as a combined DFU file. The image was over 256kb and it seemed that DfuSe Demo (a program from ST to flash DFU files) was limiting the download to 256kb.

#define FLASH_DESC_STR      "@Internal Flash   /0x08000000/016*2Ka,240*02Kg"

If I flash each binary separately, everything works as expected.

Yes, I have ensured that VTO register was correctly configured in the startup code.

Further, I also needed to jump from PROGRAM 2 to PROGRAM 1. I would be getting stuck in the default handler loop because i was not disabling some interrupts. After I disabled all used interrupts (including the sys stick interrupt), the jump from PROGRAM 2 to PROGRAM 1 works as expected as well.

View solution in original post

5 REPLIES 5
turboscrew
Senior III

The approach looks OK to me. I'm just a bit concerned about "*(__IO uint32_t*) (USBD_DFU_APP_DEFAULT_ADD".

Is that location on RAM or flash? Remember, that reset also runs cinit (and reinitializes also global variables).

If you don't do it already, I suggest you spare some small area of flash for storing the application address(es)

with, maybe, a GPIO for selection of which image to boot.

Also note that all images have their own copy of the c runtime and libraries.

Also note that, if needed, you can have several boot addresses in that specific flash area: when you erase, all bits turn to ones. When you program, you overwrite some ones with zeros. So you can program a flash word of 0xFFFFFFFF to whatever without erasing. Make a list of addresses, and if an address is not used, write it to zero and write a new address to the next word. When searching for the address, start from the beginning of the list and find the next non-zero address. Only erase when you run out of list space.

Thank you for the feedback!

The location of USDB_DFU_APP_DEFAULT_ADD is a location on FLASH memory. The device I am using has 1MB of flash memory, divided into two banks, starting at 0x08000000, and 128KB of RAM starting at 0x20000000.

#define USBD_DFU_APP_DEFAULT_ADD               0x08010000 	/* The first 16 pages (32 KB -> 0x0008 0000) are reserved for OTA code */

On your comment about GPIO selection, I will implement something similar, where I jump from the main application image (PROGRAM 2) to the OTA application (PROGRAM 1) with an external trigger from a UART module.

I do not understand the purpose of your comment about each image having their own runtime libraries, are you stating that this results in unnecessary usage of extra space in flash? If that's the case I think I'm OK with that as the flash size is big enough for me!

What is the reasoning for your advise on having several boot addresses in a reserved specified flash area? Do you believe it is a better approach than defining the addresses in some .c file.

I also still haven't been able to solve my issue on why my application doesn't launch anymore after a reboot event. Thanks for the help and I will continue to investigate.

#define USBD_DFU_APP_DEFAULT_ADD               0x08010000 	/* The first 16 pages (32 KB -> 0x0008 0000) are reserved for OTA code */

turboscrew
Senior III

My comment about runtime libraries: all images reset their variables at startup, and they don't see each others variables without absolute linking of the variables.

My comment about several boot addresses: You can change images and their boot addresses several times without erasing the boot address region.

If your image boot addresses are constant, there is no use for the list.

BTW, have you set VTOR to point to your application image vectors (early in the application start-up)?

RSikk.493
Associate II

The problem was when flashing the binaries to the chip as a combined DFU file. The image was over 256kb and it seemed that DfuSe Demo (a program from ST to flash DFU files) was limiting the download to 256kb.

#define FLASH_DESC_STR      "@Internal Flash   /0x08000000/016*2Ka,240*02Kg"

If I flash each binary separately, everything works as expected.

Yes, I have ensured that VTO register was correctly configured in the startup code.

Further, I also needed to jump from PROGRAM 2 to PROGRAM 1. I would be getting stuck in the default handler loop because i was not disabling some interrupts. After I disabled all used interrupts (including the sys stick interrupt), the jump from PROGRAM 2 to PROGRAM 1 works as expected as well.