Bootloader - migration from NucleoL432-KC to Bluepill with F103 (128k)

Hello,
one years ago i wrote my own bootloader for Nucleo-L432KC and everything works OK. Now I am changing the board to Bluepill with 128 kB flash and i trying modify the bootloader for this board, but without success:
(I am using the online compiler )

In bootloader I have this settings:

  • target device is Nucleo-F103RB (it was recommended in forum, because the same flash size as on Bluepill)

  • in main code I changed only seqence of writing to flash (because F103 has 4 bytes page, L432 has 8 bytes page)

  • in embed_app.json I have

                {
      	 "target_overrides": {
      			"NUCLEO_F103RB": {
          				"target.restrict_size": "0x00009000"
                       			}
      			}
      	}
    
  • it means the bootloader will start at 0x08000000

  • POST_APPLICATION_ADDR will be 0x08009000 here I have got the error message from compiler, that POST_APPLICATION_ADDR is not defined
    -> I have enable the the bootloader in targets.json by parameter “bootloader_supported”: true and the error message disappeared

  • when the bootloader is finished i call the main program mbed_start_application(POST_APPLICATION_ADDR);

In the main program I have set:

  • again target device is Nucleo-F103RB

  • in embed_app.json I have

            {
      	"target_overrides": {
      			"NUCLEO_F103RB": {
           		"target.mbed_app_start": "0x08009000"
      		}
    		}
      }
    

Results of tests:

  • the bootloader starts and works without problem - I am able to upload main program into flash, but the main program will not start
  • when I checked the flash memory by ST-LINK it looks OK - the bootloader is from 0x08000000 to 0x00007A90, then few FF
  • the main program is uploaded from 0x00009000
  • I also compare the bin files with memory and it is uploaded without error

Have you any idea, what I am doing wrong??
How to solve it?

My feeling is that maybe - mbed_start_application(POST_APPLICATION_ADDR) don’t jump to the main program, but why?
or the main program isn’t compiled with mbed_app_start parameter (because when I upload the same main program compiled with same parameter “target.mbed_app_start”: “0x08009000” into flash memory from address 0x08000000 it works fine )

Thank you very much for your help.

Hello Lukas,

When building the bootloader .bin file, are you sure that POST_APPLICATION_ADDR = 0x08009000 and that that address is passed on when making call to the mbed_start_application function?

  • when I checked the flash memory by ST-LINK it looks OK - the bootloader is from 0x08000000 to 0x00007A90, then few FF
  • the main program is uploaded from 0x00009000

I assume that 0x00007A90 and 0x00009000 are typos (should be 0x08007A90 and 0x08009000).

In the main program I have set:

  • in embed_app.json I have
        {
  	"target_overrides": {
  			"NUCLEO_F103RB": {
       		"target.mbed_app_start": "0x08009000"
  		}
		}
  }

I would recommend to follow the bootloader documentation for Creating the main program which suggests the following:

To create an application using a bootloader, you must first have created the bootloader binary and added it to the current project. You must then specify the bootloader image in mbed_app.json in the target_overrides section:

"target_overrides": {
    ...
    "<TARGET_NAME>": {
        "target.bootloader_img": "<path to padded bootloader binary>"
    },
    ...
  • When a build occurs, the application builds for the address immediately after the bootloader. The build system does this automatically by defining the symbols MBED_APP_START and MBED_APP_SIZE in the linker script ( .sct , .ld or .icf ).
  • At the end of building, the build image is automatically combined with the bootloader to create the final image. Note: When building offline, the original uncombined image is in the same directory <project-name>_application.bin .
  • It defines the symbols APPLICATION_ADDR , APPLICATION_SIZE , BOOTLOADER_ADDR and BOOTLOADER_SIZE .

Best regards,

Zoltan

Dear Zoltan,
thank you very much for your feedback.

Yes you are right, there are typos in my text. The bootloader is uploaded from 0x08000000 to 0x08007A90 , then few FF and the main program is from 0x08009000.

I have checked the bootloader documentation. I don’t need the " path to padded bootloader binary" because I don’t generate the one file which including the bootloader and the main app. I am generating two separate bin files: bootloader and mainapp. The reason is that we have few versions of main app - our bootloader is uploaded on every board as a standard and the main application is uploaded by this bootloader later - based on the customer’s request.

I have two question, which can help me maybe…

  1. regarding my change in targets.json
  • when the “bootloader_supported”: false than compiler don’t give me the POST_APPLICATION_ADDR to my bootloader despite in json_app is define ```
    target.restrict_size": "0x00009000
  • when the “bootloader_supported”: true it is without error message (and I have also tested to define it directly in bootloader #define POST_APPLICATION_ADDR 0x8009000, but with the same result)
  1. when the main application is compiled with mbed_app.json parameter target.mbed_app_start": "0x08009000 I am expecting that the vector will be moved and it can run only if is uploaded in flash from 0x08009000. Is it normal that this bin file runs correctly if I cleared flash and uploaded it by ST-link directly from addr 0x08000000 ?

Hello Lukas,

  • when the “bootloader_supported”: true it is without error message (and I have also tested to define it directly in bootloader #define POST_APPLICATION_ADDR 0x8009000, but with the same result)

I think you should set “bootloader_supported”: true. My guess is that the bootloader is trying to start the application but because it is not built correctly it fails.

  • Is it normal that this bin file runs correctly if I cleared flash and uploaded it by ST-link directly from addr 0x08000000 ?

No, that is not normal. It indicates that the linker built the application program assuming that it will be loaded at the 0x08000000 address.

I don’t need the " path to padded bootloader binary" because I don’t generate the one file which including the bootloader and the main app. I am generating two separate bin files: bootloader and mainapp.

I think your bootloader binary is correct. But to build the second binary file (the application program binary) correctly you should follow the bootloader documentation as explained above. Then two binaries will be created. One binary will contain the bootloader plus the application program (you dont need this file). But the other one will contain only the application program linked in a way that it will run correctly when loaded at the 0x08009000 address (however, it won’t run correctly when loaded at 0x08000000).

Best regards,

Zoltan

Hello Lukas,

It seems that the mbed-os/targets/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/device/TOOLCHAIN_GCC_ARM/STM32F103XB.ld linker file (or the mbed-os/targets/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/device/TOOLCHAIN_ARM/stm32f103xb.sct in case you the ARM toolchain rather that the GCC ARM) is not adapted for bootloader builds (the MBED_APP_START and MBED_APP_SIZE symbols are not used). To fix that for the GCC ARM toolchaing modify the STM32F103XB.ld as follows:

/* Linker script to configure memory regions. */
/* 0xEC reserved for vectors; 8-byte aligned = 0xF0 */

#if !defined(MBED_APP_START)
  #define MBED_APP_START 0x08000000
#endif

#if !defined(MBED_APP_SIZE)
  #define MBED_APP_SIZE 128K
#endif

#if !defined(MBED_BOOT_STACK_SIZE)
    #define MBED_BOOT_STACK_SIZE 0x400
#endif

STACK_SIZE = MBED_BOOT_STACK_SIZE;

MEMORY
{ 
  FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE
  RAM (rwx) : ORIGIN = 0x200000F0, LENGTH = 20K - (0xEC+0x4)
}
...

Or for the ARM toolchain modify the stm32f103xb.sct as below:

#if !defined(MBED_APP_START)
  #define MBED_APP_START 0x08000000
#endif

; STM32F411RE: 128 KB FLASH (0x20000)
#if !defined(MBED_APP_SIZE)
  #define MBED_APP_SIZE 0x20000
#endif

#if !defined(MBED_BOOT_STACK_SIZE)
  #define MBED_BOOT_STACK_SIZE 0x400
#endif

#define Stack_Size MBED_BOOT_STACK_SIZE

LR_IROM1 MBED_APP_START MBED_APP_SIZE  {    ; load region size_region

  ER_IROM1 MBED_APP_START MBED_APP_SIZE  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }

  ; 59 vectors (16 core + 43 peripheral) * 4 bytes = 236 bytes to reserve (0xEC) 8-byte aligned = 0xF0
  RW_IRAM1 (0x20000000+0xF0) (0x5000-0xF0-Stack_Size)  {  ; RW data
   .ANY (+RW +ZI)
  }

  ARM_LIB_HEAP AlignExpr(+0, 16) EMPTY (0x20000000+0x5000-Stack_Size-AlignExpr(ImageLimit(RW_IRAM1), 16)-0xF0) {
  }

  ARM_LIB_STACK (0x20000000+0x5000) EMPTY -Stack_Size { ; stack
  }
}

Best regards, Zoltan

Dear Zoltan,
thank you very much. I have made few tests and I was sure that the problem isn’t in my code, but somewhere in setting. I will test your recommendation during the weekend and I will inform you…
Thank you once again for you excellent support and help.

Lukas

Hello Lukas,

It seems that the linker files in the mbed-os 6.1.0 library have been fixed. So it should be sufficient to update the mbed library.

Best regards, Zoltan

Dear Zoltan,
i forget to inform you that after update it is working.

Best regards Lukas