1

I wrote a Bootloader for my STM32F042k6 board that functions pretty well. On System Reset the Bootloader is launched and can later jump to the Application. That was great:). Now I wish to do the opposite in my Flash. I wish Launch my Bootloader at a start address other than 0x08000000 lets say at 0x08007000. When I do the modifications in the Linker Script the Programm cannot be debugged. In simple words I wish to place my bootloader at the end of my Flash. Without forget that the Bootloader is always the first Code to run after Reset. Thanks in advance for your help and comments Here is my Linker Script:

/* Entry Point */
ENTRY(Boot_Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20001800;    /* end of 6K RAM */

/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0;      /* required amount of heap  */
_Min_Stack_Size = 0x80; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{   
  BOOTLOADER (rx) : ORIGIN = 0x08007000, LENGTH = 4K    
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 28K 
  RAM (xrw)       : ORIGIN = 0x200000C0, LENGTH = 6K - 192
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}


/* Define output sections */
SECTIONS
{
  /* The startup code goes first into BOOTLOADER */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >BOOTLOADER



  /* The program code and other data goes into BOOTLOADER */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >BOOTLOADER

  /* Constant data goes into BOOTLOADER */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >BOOTLOADER

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >BOOTLOADER
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >BOOTLOADER

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >BOOTLOADER
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >BOOTLOADER
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >BOOTLOADER

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> BOOTLOADER

  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM

  /* MEMORY_bank1 section, code must be located here explicitly            */
  /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */
  .memory_b1_text :
  {
    *(.mb1text)        /* .mb1text sections (code) */
    *(.mb1text*)       /* .mb1text* sections (code)  */
    *(.mb1rodata)      /* read-only data (constants) */
    *(.mb1rodata*)
  } >MEMORY_B1

  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}
McSteve
  • 13
  • 3

4 Answers4

1

You're out of luck I'm afraid, your processor will always start running code from the address 0x00000000 (sort of, it will look at 0x00000004 to see where the reset vector is).

There are a number of boot pins which change whether flash or RAM is aliased at address 0x00000000, but you can't choose which area of flash, it will always be 0x08000000 onwards. If you want to your custom bootloader, and have it be the first thing run, it needs to be at the start of flash.

What is the problem you're trying to solve by moving the bootloader? There is probably another possible solution.

Colin
  • 3,394
  • 1
  • 21
  • 29
  • its that other solution I am looking for. I am try to see how I can manage the Flash Memory of the STM device – McSteve Feb 14 '19 at 16:21
0

I'm afraid you're looking after a solution for the wrong problem. Programs loaded by a bootloader can be debugged. I'm doing it all the time.

So something goes wrong before your application hits the first breakpoint set by the debugger.

A probably incomplete list of things to check

  • The bootloader does something that makes debugging impossible
    • disables the SWD pins
    • does not jump to the application reset handler
    • starts a watchdog
    • does not disable all possible interrupts
    • does not return to thread mode
    • wrong value in the stack pointer
  • loading the application in the debugger damages the bootloader
    • e.g. erases the wrong flash sectors
  • the application startup code fails
    • problem with the application linker script
    • sets wrong value in the stack pointer
    • sets wrong value in NVIC->VTOR - check this one first if you're using HAL
0

Normally, bootloader is the first piece of code that first executed. And with this way, it is not possible to relocate the bootloader to other memory partition. However, there is another concept that able to relocate the bootloader to any memory address. That is the bootloader is only for update software later. With this approach, your main software will be the boot code. And when there is request to update, you jump to bootloader and do update software then reboot for normal operation. The drawback of this approach is that if the updated software fail, there isn't any recovery mechanism and you need to reflash by flashing tools.

ThongDT
  • 162
  • 7
0

The Microsoft Jacdac project places a bootloader in the last 4K of the STM32G0 flash, which has 32K to start with. I found this out the hard way when I tried to use the last page of flash for persistent storage.

The linker.ld file for the bootloader created during build has the content:

MEMORY {
RAM (rwx)   : ORIGIN = 0x20000000, LENGTH = 8K
FLASH (rx)  : ORIGIN = 0x8000000 + 32K - 4K, LENGTH = 4K
}
INCLUDE jacdac-stm32x0/ld/gcc_arm_bl_at_end.ld

The file jacdac-jacdac-stm32x0/ld/gcc_arm_bl_at_end.ld can be found on GitHub at: https://github.com/microsoft/jacdac-stm32x0/blob/05f7b6913a0f6cfcd7a15252daff773ead2834da/ld/gcc_arm_bl_at_end.ld

Oppy
  • 2,662
  • 16
  • 22