2

I made my own bootloader for an STM32L1 board. My algorithm is simple : - first, I erase the memory I need to write my new program on my flash. - then, I write 4 bytes per 4 bytes my new program ( I receive it from the USART of the board)

  • then i push the RESET button of my card, and nothing happens ...

My new program should blink a LED but nothing happens and I d'ont understand why ...

Do i have to write my own RESET function? Here is my code if you want to give a try.

void BootLoader(void) {

    //clear all ITs
    USART_ITConfig_boot( USART1, USART_IT_RXNE, 0);
    uint32_t start_adr, end_adr;
    uint8_t status, i;
    uint8_t buffer[4096];
    uint8_t sizeRcv[2];
    uint16_t tailleSector = 0x1000;
    uint32_t adr;
    uint8_t nbSector = 0;

    //size fixée en dur
    uint16_t k = 0;
    uint8_t size1 = 0;
    uint8_t size2 = 0;
    uint16_t sizeBin = 0;
    //taille sector
    uint16_t tailleSecteurDec = 4096;
    SendString_boot("BOOTLOADER ON.....\r\n", USART2);
    //adress
    //First Sector
    start_adr = WRITE_START_ADDR;
    end_adr = start_adr + tailleSector;
    //erasing flags

    FLASH_ClearFlag_boot(
                FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR
                        | FLASH_FLAG_SIZERR | FLASH_FLAG_OPTVERR
                        | FLASH_FLAG_OPTVERRUSR | FLASH_FLAG_RDERR);

    FLASH_Unlock_boot();
    sizeBin = 51400;
    nbSector = (uint8_t) (sizeBin / tailleSecteurDec) + 1;
    if(nbSector > 30){
        SendString_boot("cannot overrite memory : too much sectors used\r\n",USART2);

    }

    for (i = 0; i <= (127 - 1); i++) {
        if(end_adr < 0x0808FFFF){
            status = Flash_Erase(start_adr, end_adr);
            start_adr = end_adr;
            end_adr = end_adr + tailleSector;
            SendString_boot(" ERASING SECTOR DONE \r\n", USART2);
        }
        else{
            SendString_boot("END OF FLASH MEMORY\r\n", USART2);

        }
    }

    SendString_boot("ERASING COMPLETE\r\n", USART2);
    start_adr = WRITE_START_ADDR;
    //receive frames

    adr = WRITE_START_ADDR;
    do {

        SendString_boot("ACK_READY", USART1);
        SendString_boot("ACK_READY\r\n", USART2);
        //receive 32 bytes
        if (sizeBin - k > 4096)
            Receive_Data_boot(buffer, 4096);
        else
            Receive_Data_boot(buffer, sizeBin - k);


        //write 32 bytes in memory
        if (sizeBin - k > 4096)
            status = Flash_Write(adr, buffer, 4096);
        else
            status = Flash_Write(adr, buffer, sizeBin - k);
        //on check si on ecrit bien au bon endroit

        //increment cpt
        k = k + 4096;
        adr = adr + 0x1000;
        i++;
        //check CRC
        //TODO
        SendString_boot("...FLASH DONE ON  ", USART2);
        SendString_boot("\r\n", USART2);


        SendString_boot("  SECTOR DONE \r\n", USART2);

    } while (k < sizeBin);

    SendString_boot("END", USART1);
    SendString_boot("ACK_END\r\n", USART2);
    FLASH_Lock_boot();

}

The linker script is:

/* Entry Point */
ENTRY(Reset_Handler)

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

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

/* Specify the memory areas */
MEMORY
{
  BOOT (rx)       : ORIGIN = 0x0801E000, LENGTH = 8K
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K-8K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 80K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

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




    /* The program code and other data goes into FLASH */
  .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 */
  } >FLASH

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

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

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

  /* 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 */
    *(.RamFunc)        /* .RamFunc sections */

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




  /* 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 ( * )
  }

    .bootsection :
  {
    . = ALIGN(4);
    KEEP(*(.bootsection)) /* Bootloader code */
    . = ALIGN(4);
  } >BOOT 

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

Receive_data_boot code :

void Receive_Data_boot(uint8_t * buffer, int size) {

    uint16_t i = 0;
    do {

        buffer[i] = Uart2ReadChar_boot();
        i++;

    } while (i < size);

}

uint8_t Uart2ReadChar_boot(void) {


    while(USART_GetFlagStatus_boot(USART1, USART_FLAG_RXNE) == 0);
    return USART_ReceiveData_boot(USART1);
}

uint16_t USART_ReceiveData_boot(USART_TypeDef_boot* USARTx)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH_BOOT(USARTx));
  SendChar_boot((uint8_t)USARTx->DR,USART1);
  /* Receive Data */
  return ((uint16_t)(USARTx->DR & (uint16_t)0x01FF));
}
14
  • What's the value of WRITE_START_ADDR? Where the bootloader belongs, in which sector/address? Commented Jun 23, 2015 at 8:03
  • WRITE_START_ADDR : 0x08000000 ( at the begining of my flash) Commented Jun 23, 2015 at 8:12
  • And your bootloader still at the end of your flash? Commented Jun 23, 2015 at 8:16
  • Yes , my bootloader is at the end of the flash MEMORY { BOOT (rx) : ORIGIN = 0x0801E000, LENGTH = 8K FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K-8K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 80K MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K } Commented Jun 23, 2015 at 8:17
  • Could you post the linker script of application? And the whole linker script of bootloader Commented Jun 23, 2015 at 8:24

1 Answer 1

3

To start your new program from FLASH after RESET the following conditions must be satisfied:

  1. Written image contains correct Reset_Handler which will be executed after POR. Typically this is defined in startup.S and ended with something like:

    bl SystemInit
    bl main
    bx lr
    
  2. Pin BOOT0 of your processor must be set 0.

Example.

From startup.S:

      .section  .isr_vector,"a",%progbits
      .type  g_pfnVectors, %object
      .size  g_pfnVectors, .-g_pfnVectors

    g_pfnVectors:
      .word  _estack
      .word  Reset_Handler
      .word  NMI_Handler
      .word  HardFault_Handler
      ...

From program assembly listing:

      08008fd8 <Reset_Handler>:
        .weak  Reset_Handler
        .type  Reset_Handler, %function
    Reset_Handler:

      /* Copy the data segment initializers from flash to SRAM */
        movs  r1, #0
        8008fd8:    2100        movs    r1, #0

From hex-file:

    :020000040800F2
    :1000000000000220D98F0008F9070008FD0700084A

Note address 0x08008fd9 in hex file (:1000000000000220D98F0008F9070008FD0700084A) that match Reset_Handler with LSB set (Thumb2-mode).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.