我的bootloader无法在stm32上启动我的新程序

时间:2022-03-03 00:06:54

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)

我为STM32L1板制作了自己的引导程序。我的算法很简单: - 首先,我擦除了在闪存上编写新程序所需的内存。 - 然后,我每4字节写4个字节我的新程序(我从电路板的USART收到它)

  • then i push the RESET button of my card, and nothing happens ...
  • 然后我按下我的卡的RESET按钮,没有任何反应......

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

我的新程序应该闪烁一个LED,但没有任何反应,我理解为什么......

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

我必须编写自己的RESET功能吗?如果你想尝试一下,这是我的代码。

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 :

Receive_data_boot代码:

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));
}

1 个解决方案

#1


2  

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

要在RESET后从FLASH启动新程序,必须满足以下条件:

  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:

    写入的图像包含正确的Reset_Handler,它将在POR之后执行。通常,这是在startup.S中定义的,并以以下内容结束:

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

    处理器的引脚BOOT0必须设置为0。

Example.

例。

From startup.S:

从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:

从hex文件:

    :020000040800F2
    :1000000000000220D98F0008F9070008FD0700084A

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

注意匹配带有LSB设置(Thumb2模式)的Reset_Handler的十六进制文件(:1000000000000220D98F0008F9070008FD0700084A)中的地址0x08008fd9。

#1


2  

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

要在RESET后从FLASH启动新程序,必须满足以下条件:

  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:

    写入的图像包含正确的Reset_Handler,它将在POR之后执行。通常,这是在startup.S中定义的,并以以下内容结束:

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

    处理器的引脚BOOT0必须设置为0。

Example.

例。

From startup.S:

从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:

从hex文件:

    :020000040800F2
    :1000000000000220D98F0008F9070008FD0700084A

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

注意匹配带有LSB设置(Thumb2模式)的Reset_Handler的十六进制文件(:1000000000000220D98F0008F9070008FD0700084A)中的地址0x08008fd9。