0

I am working on a NUCLEO-L476RG board, trying to start the bootloader from my firmware code but its not working for me. here is the code that i am trying to execute :

#include "stm32l4xx.h"
#include "stm32l4xx_nucleo.h"
#include "core_cm4.h"
#include "stm32l4xx_hal_uart.h"

GPIO_InitTypeDef GPIO_InitStructure;
UART_HandleTypeDef UartHandle;

UART_InitTypeDef UART_InitStructre;


void BootLoaderInit(uint32_t BootLoaderStatus){

    void (*SysMemBootJump)(void) = (void (*)(void)) (*((uint32_t *) 0x1FFF0004));

    if(BootLoaderStatus == 1) {
        HAL_DeInit(); // shut down running tasks

        // Reset the SysTick Timer
        SysTick->CTRL = 0;
        SysTick->LOAD = 0;
        SysTick->VAL =0;

        __set_PRIMASK(1); // Disable interrupts
        __set_MSP((uint32_t*) 0x20001000);

        SysMemBootJump();
    }
}

int main(void)
{
     HAL_Init();

    __GPIOC_CLK_ENABLE();
    GPIO_InitStructure.Pin   = GPIO_PIN_13;
    GPIO_InitStructure.Mode  = GPIO_MODE_INPUT;
    GPIO_InitStructure.Pull  = GPIO_PULLUP;
    GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

    while (1) {
        if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)) {
            BootLoaderInit(1);
        }
    }

    return 0;
}

What i hope to get after the execution of the firmware is that i can connect to the board with a UART and send commands/get responses from the bootloader. the commands i am trying to use come from here: USART protocol used in the STM32 bootloader.

I don't see and response from the board after connecting with the UART.

3 Answers3

0

Here are some ideas taken from the answers to this question.

  • HAL_RCC_DeInit();

This is apparently needed to put the clocks back into the state after reset, as the bootloader expects them to be.

  • __HAL_REMAPMEMORY_SYSTEMFLASH();

Maps the system bootloader to address 0x00000000

  • __ASM volatile ("movs r3, #0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp");

Set the stack pointer from bootloader ROM. Where does your 0x20001000 come from? If it's an arbitrary value, then the stack can clobber the bootloader's variables.

Then there is this alternate solution:

When I want to jump to the bootloader, I write a byte in one of the backup register and then issue a soft-reset. Then, when the processor will restart, at the very beginning of the program, it will read this register.

Note that you need LSI or LSE clock for accessing the backup registers.

Community
  • 1
  • 1
  • "Note that you need LSI or LSE clock for accessing the backup registers." - this is not true. Neither of these clocks is needed to access anything in STM32. They are required as clock source only if a peripheral explicitly selects them as a source. – Freddie Chopin Feb 20 '17 at 16:28
0

Try to avoid using __set_MSP(), as current implementation of this function does NOT allow you to change MSP if it is also the stack pointer which you currently use (and you most likely are). The reason is that this function marks "sp" as clobbered register, so it will be saved before and restored afterwards.

See here - STM32L073RZ (rev Z) IAP jump to bootloader (system memory)

Community
  • 1
  • 1
Freddie Chopin
  • 8,440
  • 2
  • 28
  • 58
  • Is this still the case? What is the alternative to `__set_MSP()`? – Jon Nordby Sep 12 '19 at 09:26
  • @jonnor - no, current versions of CMSIS are fixed. Check whether your copy has "sp" in the clobber list or not. – Freddie Chopin Sep 12 '19 at 10:36
  • Actually the CMSIS included with STM32Cube_FW_L4_V1.13.0 (quite recent) still had the problem. Thanks for the heads up! Version 14 for L4 fixes has the fix. https://github.com/STMicroelectronics/STM32CubeL4/blob/d00623f229d09f3a1be050bdb0606b8870fa5d1c/Drivers/CMSIS/Core/Include/cmsis_gcc.h#L331 – Jon Nordby Sep 12 '19 at 11:23
  • @jonnor - you can always replace what is in Cube packages with the most recent CMSIS directly from ARM (; It works without issues. – Freddie Chopin Sep 12 '19 at 16:48
0

Find your bootloader start address from the reference manual.

Then use the following code.

Make sure you have cleaned and disabled the interrupts before do so.

/* Jump to different address */
JumpAddress = *(__IO uint32_t*) (BootloaderAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();

Please have a look at Official STM32 AppNote as well.

SamR
  • 384
  • 3
  • 12
  • I tried this but it doesn't work for my board. The link that you gave is for a different MCU - STM32F10xxx . Thanks for trying . – David Lichterov Feb 26 '17 at 10:34