Skip to main content
Visitor II
April 18, 2020
Solved

Custom Bootloader Testing & Debug

  • April 18, 2020
  • 3 replies
  • 1487 views

I am trying to write a custom bootloader. I have compiled both bootloader and application binaries and concatenated them in the makefile. When I flash the device with the binary (via ST-Link) my application is not booting up.

1) I suspect the issue is with incorrectly setting the location of SCB->VTOR. If my application starts at address 0x8002000 what is the correct location of the application VTOR?

2) I suspect the issue could also be with incorrect concatenation of the .bin files (i.e. padding the application binary). I have posted the code which I used to concatenate the files. Is this the correct way to do so?

3) Is there a way for me to debug what is exactly wrong? Its difficult because I cannot go into debug mode with the concatenated binary.

Appreciate your time.

My bootloader memory config is as follows: 

// In bootloader.ld
 
MEMORY
{
 RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 160K
 BOOT (rx) : ORIGIN = 0x8000000, LENGTH = 8K
 FLASH (rx) : ORIGIN = 0x8002000, LENGTH = 502K
}
 
__bootrom_start__ = ORIGIN(BOOT);
__bootrom_size__ = LENGTH(BOOT);
__approm_start__ = ORIGIN(FLASH);
__approm_size__ = LENGTH(FLASH);

My application memory config is as follows: 

// In application.ld
 
MEMORY
{
 RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 160K
 FLASH (rx) : ORIGIN = 0x8002000, LENGTH = 498K
}

Below is the code in for my bootloader: 

// In bootloader.h
 
#pragma once
 
#include <stdint.h>
#include "stm32l4xx_hal.h"
 
extern int __bootrom_start__;
extern int __bootrom_size__;
extern int __approm_start__;
extern int __approm_size__;
 
void bootloader_init(void);

// In bootloader.c
 
void bootloader_init(void)
{
	uint32_t *app_code = (uint32_t) &__approm_start__;
	uint32_t sp = &(app_code[0]);
	uint32_t pc = &(app_code[1]);
	__disable_irq();
 
	SCB->VTOR = &(app_code[0]);
 
	// Jumping to application stack pointer
 
	__asm__ __volatile__("mov sp,%0\n\t"
			"bx %1\n\t"
			: /* no output */
			: "r" (sp), "r" (pc)
			: "sp");
 
	// Should never reach here
	while (1) {}
}

I have compiled both bootloader and application binaries and concatenated them via the following lines in the makefile. Where STM32L452RE _Bootloader_Boot.bin is just the bootloader binary and STM32L452RE _Boot.bin is the bootloader+application concatenated library.

STM32L452RE_Bootloader_Boot.bin: $(EXECUTABLES)
	arm-none-eabi-objcopy --gap-fill=0xFF --pad-to 0x2000 -O binary $(EXECUTABLES) "STM32L452RE_Bootloader_Boot.bin"
	@echo 'Finished building: $@'
	@echo ' '
 
STM32L452RE_Bootloader.bin: $(OBJCOPY_BIN) $(APPLICATION)
	cat $^ > $@
	@echo 'Finished concatenating: $@'
	@echo ' '

    This topic has been closed for replies.
    Best answer by NWeis.19

    Check out the examples for STm32F4 etc.. should be the same.

    On F4 with Keil I had no issues.

    in file system_stm32xxx.c (can be system_stm32f4xx. c or similar)

    at the end of SystemInit function add the following:

     /* Configure the Vector Table location add offset address ------------------*/

    #ifdef BOOT_LOADER

     // Vector Table Relocation in Internal BL area FLASH

     NVIC_SetVectorTable(FLASH_BASE_ADDR, BL_VEC_OFFSET);

    #else

     // Vector Table Relocation in Internal APP area FLASH

     NVIC_SetVectorTable(FLASH_BASE_ADDR, APP_VEC_OFFSET); 

    #endif

    You can use the same file for the boot loader and application. In your boot loader project you just need to add a define in your compiler settings BOOT_LOADER

    This solves the VTOR definition. If you do not have NVIC_SetVectorTable you can simply change the code to

    #ifdef BOOT_LOADER

     // Vector Table Relocation in Internal BL area FLASH

     SCB->VTOR = FLASH_BASE | BL_VEC_OFFSET; 

    #else

     // Vector Table Relocation in Internal APP area FLASH

     SCB->VTOR = FLASH_BASE | APP_VEC_OFFSET; 

    #endif

    ------------------------------------------------------------------------------------------------------

    As for the boot loader the jump to application is done from main as follows:

    typedef void (*pFunction)(void);

    static void LoadUserApp(void)

    {

     static pFunction Jump_To_Application;

     static uint32_t JumpAddress;

     /* Initialize Flash */

     HAL_FLASH_Lock();

     // test if jump address to were vector table is located is in RAM

     // starts at address0x20xxxxxx

     if(((*(__IO uint32_t*)APP_BASE_ADDR) & 0x2F000000) == 0x20000000)

     {

       JumpAddress = *(__IO uint32_t*)(APP_BASE_ADDR + 4);

       // Jump to user application

       Jump_To_Application = (pFunction) JumpAddress;

       // Initialize user application's Stack Pointer

       __set_MSP(*(__IO uint32_t*)APP_BASE_ADDR);

       __set_CONTROL(0);

       Jump_To_Application();

       // we should not get here !!!

       while(1);

     }

    The above worked for me but for some reason in the WB55 with Atollic it does not ????

    What IDE are you using ?

    3 replies

    NWeis.19Answer
    Visitor II
    April 18, 2020

    Check out the examples for STm32F4 etc.. should be the same.

    On F4 with Keil I had no issues.

    in file system_stm32xxx.c (can be system_stm32f4xx. c or similar)

    at the end of SystemInit function add the following:

     /* Configure the Vector Table location add offset address ------------------*/

    #ifdef BOOT_LOADER

     // Vector Table Relocation in Internal BL area FLASH

     NVIC_SetVectorTable(FLASH_BASE_ADDR, BL_VEC_OFFSET);

    #else

     // Vector Table Relocation in Internal APP area FLASH

     NVIC_SetVectorTable(FLASH_BASE_ADDR, APP_VEC_OFFSET); 

    #endif

    You can use the same file for the boot loader and application. In your boot loader project you just need to add a define in your compiler settings BOOT_LOADER

    This solves the VTOR definition. If you do not have NVIC_SetVectorTable you can simply change the code to

    #ifdef BOOT_LOADER

     // Vector Table Relocation in Internal BL area FLASH

     SCB->VTOR = FLASH_BASE | BL_VEC_OFFSET; 

    #else

     // Vector Table Relocation in Internal APP area FLASH

     SCB->VTOR = FLASH_BASE | APP_VEC_OFFSET; 

    #endif

    ------------------------------------------------------------------------------------------------------

    As for the boot loader the jump to application is done from main as follows:

    typedef void (*pFunction)(void);

    static void LoadUserApp(void)

    {

     static pFunction Jump_To_Application;

     static uint32_t JumpAddress;

     /* Initialize Flash */

     HAL_FLASH_Lock();

     // test if jump address to were vector table is located is in RAM

     // starts at address0x20xxxxxx

     if(((*(__IO uint32_t*)APP_BASE_ADDR) & 0x2F000000) == 0x20000000)

     {

       JumpAddress = *(__IO uint32_t*)(APP_BASE_ADDR + 4);

       // Jump to user application

       Jump_To_Application = (pFunction) JumpAddress;

       // Initialize user application's Stack Pointer

       __set_MSP(*(__IO uint32_t*)APP_BASE_ADDR);

       __set_CONTROL(0);

       Jump_To_Application();

       // we should not get here !!!

       while(1);

     }

    The above worked for me but for some reason in the WB55 with Atollic it does not ????

    What IDE are you using ?

    AAgar.2Author
    Visitor II
    April 19, 2020

    Dude sweet.

    Just tried the examples and got it working!

    I'm using the STM32CubeIDE.

    Thanks

    Visitor II
    April 19, 2020

    Great for you,

    for some reason I cannot get it to work with Atollic :face_with_tears_of_joy: