bdjinger 发表于 2021-9-4 10:08:38

stm32f103zg程序跳转到系统bootloader失败

目前用的芯片是stm32f103zg,准备使用串口升级程序,看到手册AN2606中,该芯片是支持USART1通过系统boot loader更新程序的。现在的程序是用stm32cubemx生成的,程序如下
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
                if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_10)==GPIO_PIN_RESET)
                {
                        JumpToBootloader();
                }
                else
                {
                        JumpToApp();
                }               
}
/* USER CODE END 3 */
}

/* USER CODE BEGIN 4 */

static void JumpToBootloader(void)
{
      uint32_t i=0;
      void (*SysMemBootJump)(void); /*声明一个函数指针*/
      __IO uint32_t BootAddr =0x1FFFE000;//0x1FFF0000; /* STM32F103 的系统 BootLoader 地址*/
      
      /*关闭全局中断*/
      __disable_irq();
      
      /*关闭滴答定时器,恢复到默认值*/
      SysTick->CTRL = 0;
      SysTick->LOAD = 0;
      SysTick->VAL = 0;
      
      /*设置所有时钟到默认状态,使用HSI时钟*/
      HAL_RCC_DeInit();

      /* 关闭所有中断,清除中断挂起标志 */
      for (i = 0; i < 8; i++)
      {
                NVIC->ICER=0xFFFFFFFF;
                NVIC->ICPR=0xFFFFFFFF;
      }
      
      /* 使能全局中断 */
      __enable_irq();
      
      /*设置重映射到系统Flash */
//      __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
      
      /* 跳转到系统 BootLoader,首地址是MSP,地址 +4 是复位中断服务程序地址 */
      SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));
      
      /* 设置主堆栈地址*/
      __set_MSP(*(uint32_t *)BootAddr);
      
      /*在RTOS工程,这条语句很重要,设置为特权模式,使用MSP指针 */
      __set_CONTROL(0);
      
      /* 跳转到系统 BootLoader */
      SysMemBootJump();
}

static void JumpToApp(void)
{
      uint32_t i=0;
      void (*SysMemBootJump)(void);      /*声明一个函数指针*/
      __IO uint32_t BootAddr = 0x8001800; /* APP程序地址*/      
      

      /*关闭全局中断*/
      __disable_irq();

      /*关闭滴答定时器,恢复到默认值*/
      SysTick->CTRL = 0;
          SysTick->LOAD = 0;
          SysTick->VAL = 0;

      /*设置所有时钟到默认状态,使用HSI时钟*/
      HAL_RCC_DeInit();

      /* 关闭所有中断,清除中断挂起标志 */
      for (i = 0; i < 8; i++)
      {
                NVIC->ICER=0xFFFFFFFF;
                NVIC->ICPR=0xFFFFFFFF;
      }      

      /* 使能全局中断 */
      __enable_irq();

      /* 跳转到系统 BootLoader,首地址是MSP,地址 +4 是复位中断服务程序地址 */
      SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));

      /* 设置主堆栈地址*/
      __set_MSP(*(uint32_t *)BootAddr);
      
      /*在RTOS工程,这条语句很重要,设置为特权模式,使用MSP指针 */
      __set_CONTROL(0);

      /* 跳转到系统 BootLoader */
      SysMemBootJump();
}
/* USER CODE END 4 *现在这个程序是可以正常跳转到APP程序的,就是跳转bootloader不成功,用stm32programmer,连接不上串口。如果直接把BOOT0置高是可以连接上串口的,所以硬件上应该没有问题。
请各位大神帮我看看到底是什么原因不能跳转到系统boot loader呢?

eric2013 发表于 2021-9-4 16:02:51

F103跳转到系统BootLoader确实有一些奇葩问题,无法跳转到系统BootLoader里面。

之前帮一个网友整,也没有搞定。估计还有一些区别于F4和H7的骚操作要执行下。

无关风月 发表于 2021-10-26 17:31:15

我之前也遇到了这个问题,发现要调整一下顺序,否则滴答定时器关不掉,影响跳转
/*设置所有时钟到默认状态,使用HSI时钟*/
HAL_RCC_DeInit();

/*关闭滴答定时器,恢复到默认值*/
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;


最后问一下硬汉哥
/*在RTOS工程,这条语句很重要,设置为特权模式,使用MSP指针 */
__set_CONTROL(0);
这句有用吗?我看M3权威指南中有说只有在中断中才能从1变0


weboser 发表于 2021-12-25 10:42:58

无关风月 发表于 2021-10-26 17:31
我之前也遇到了这个问题,发现要调整一下顺序,否则滴答定时器关不掉,影响跳转
/*设置所有时钟到默认状 ...

有其他人验证过这个吗?
我使用F302也是没法跳转到系统boot,识别不到usb:L

eric2013 发表于 2021-12-26 09:51:02

weboser 发表于 2021-12-25 10:42
有其他人验证过这个吗?
我使用F302也是没法跳转到系统boot,识别不到usb

可以上ST的社区找找F302的跳转地址,像我之前H7的就是,手册上给的地址不对。

illusion_killer 发表于 2024-4-3 15:15:48

可以试试下面的代码,我测试使用后没有问题,代码中的HAL_DeInit()必须调用,经测试可以正常跳转
/*
******************************************************************************************************
*    函 数 名: JumpToBootloader
*    功能说明: 跳转到系统BootLoader   //refstm32AN2606
*    形    参: 无
*    返 回 值: 无
******************************************************************************************************
*/
static void JumpToBootloader(void)
{
    void (*SysMemBootJump)(void);
                if(wdg_dev)
                        rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
                HAL_DeInit();
                HAL_RCC_DeInit();
                SysTick->CTRL = 0;
                SysTick->LOAD = 0;
                SysTick->VAL = 0;
                __disable_irq();
    __IO uint32_t BootAddr = 0x1FFFF000; /* STM32系统BootLoader地址 */
    SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));
    __set_MSP(*(uint32_t *) BootAddr);
    SysMemBootJump();
    while (1);
}
MSH_CMD_EXPORT_ALIAS(JumpToBootloader, reboot_loader, jump to system memory);

eric2013 发表于 2024-4-4 09:19:43

illusion_killer 发表于 2024-4-3 15:15
可以试试下面的代码,我测试使用后没有问题,代码中的HAL_DeInit()必须调用,经测试可以正常跳转


谢谢分享。
页: [1]
查看完整版本: stm32f103zg程序跳转到系统bootloader失败