stm32L476RG - 如何从固件

时间:2017-02-20 10:10:35

标签: embedded stm32 bootloader

我正在使用NUCLEO-L476RG板,尝试从我的固件代码启动引导程序,但它不适用于我。这是我试图执行的代码:

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

我希望在执行固件后获得的是我可以使用UART连接到电路板并从引导加载程序发送命令/获取响应。我试图使用的命令来自这里:USART protocol used in the STM32 bootloader.

在连接UART后,我没有看到并回复电路板。

3 个答案:

答案 0 :(得分:0)

以下是对this question的答案中的一些想法。

  • HAL_RCC_DeInit();

显然需要在重置后将时钟重新置于状态,因为引导加载程序需要它们。

  • __HAL_REMAPMEMORY_SYSTEMFLASH();

将系统引导加载程序映射到地址0x00000000

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

从引导加载程序ROM设置堆栈指针。你的0x20001000来自哪里?如果它是一个任意值,那么堆栈可以破坏引导加载程序的变量。

然后有另一种解决方案:

  

当我想跳转到引导程序时,我在其中一个中写了一个字节   备份寄存器然后发出软复位。然后,当处理器   将重新启动,在程序的最开始,它将读取此   注册

请注意,您需要LSI或LSE时钟来访问备份寄存器。

答案 1 :(得分:0)

尽量避免使用__set_MSP(),因为此函数的当前实现 NOT 允许您更改MSP,如果它也是您当前使用的堆栈指针(并且您很可能是)。原因是这个函数将“sp”标记为破坏寄存器,因此它将被保存并在之后恢复。

请参阅此处 - STM32L073RZ (rev Z) IAP jump to bootloader (system memory)

答案 2 :(得分:0)

从参考手册中找到您的引导加载程序起始地址。

然后使用以下代码。

确保在执行此操作之前清理和禁用了中断。

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

请同时查看Official STM32 AppNote