stm32f4 CubeMX生成IAR工程 移植ST官方 Bootloader 教程

一、前言

产品发布后的升级不能再依赖于烧录器,如果能用产品预留的串口就可以更新芯片的APP程序,对于一些不便于拆卸的产品,这种维护方式非常好用。

bootloader的代码有很多选择,比如正点原子的bootloader 和 RT-thread 官方的bootloader。
作者选用ST官方提供的bootloader,使用Ymodem协议传输。

bootloader的工作原理这里不展开说,总结下来就是把bootloader的程序写到原来的0x08000000,而主程序作为App程序,往0x08008000地址烧录,bootloader里提供三个功能,一个是往0x08008000里烧录App,一个是下载0x08008000里的程序,一个是跳转到0x08008000 App程序。
当然刚上电是先进入bootloader,再跳转App。

二、CubeMX生成 IAR 工程

1.CubeMX生成工程

在CubeMX除了选择MCU还可以选择开发板的,有限官方的开发板自带了IAP例程,也就是bootloader。
在这里插入图片描述
Toolchain/IDE 选择EWARM就是生成IAR工程了。注意要配置好烧程序用的串口。
在这里插入图片描述

2.官方的IAP例程

只有默写板子有IAP例程,可以去安装包Applications的这个路径下找到IAP文件夹。
在这里插入图片描述
这是个文件和对应的头文件就是用到的,另外main 函数里有写进入menu.c 的入口函数,也可以复制到自己的程序中。
在这里插入图片描述

三、移植bootloader

1.移植相关代码

将bootloader相关的.c和.h 文件加入工程后就编译一下,如果报有缺少头文件添加一下。
注意下面几个函数:
1.Serial_PutString()函数

这个是代替printf用的(printf文件比较大一般bootloader不使用),这个函数在common.c中,注意修改官方例程中的串口为你的烧录串口,比如你CubeMX 配置的是UART_HandleTypeDef huart1,就把用到串口的地方都改成huart1。

2.Main_Menu ()函数
这个是进入bootloader菜单选择的函数,可以看到串口输入1,2,3,4分别有不同的功能,其中1是烧录app,3是跳转app。

void Main_Menu(void)
{
  uint8_t key = 0;

  Serial_PutString((uint8_t *)"\r\n======================================================================");
  Serial_PutString((uint8_t *)"\r\n=              (C) COPYRIGHT 2016 STMicroelectronics                 =");
  Serial_PutString((uint8_t *)"\r\n=                                                                    =");
  Serial_PutString((uint8_t *)"\r\n=          STM32F4xx In-Application Programming Application          =");
  Serial_PutString((uint8_t *)"\r\n=                                                                    =");
  Serial_PutString((uint8_t *)"\r\n=                       By MCD Application Team                      =");
  Serial_PutString((uint8_t *)"\r\n======================================================================");
  Serial_PutString((uint8_t *)"\r\n\r\n");

  while (1)
  {

    /* Test if any sector of Flash memory where user application will be loaded is write protected */
    FlashProtection = FLASH_If_GetWriteProtectionStatus();
    
    Serial_PutString((uint8_t *)"\r\n=================== Main Menu ============================\r\n\n");
    Serial_PutString((uint8_t *)"  Download image to the internal Flash ----------------- 1\r\n\n");
    Serial_PutString((uint8_t *)"  Upload image from the internal Flash ----------------- 2\r\n\n");
    Serial_PutString((uint8_t *)"  Execute the loaded application ----------------------- 3\r\n\n");

    if(FlashProtection != FLASHIF_PROTECTION_NONE)
    {
      Serial_PutString((uint8_t *)"  Disable the write protection ------------------------- 4\r\n\n");
    }
    else
    {
      Serial_PutString((uint8_t *)"  Enable the write protection -------------------------- 4\r\n\n");
    }
    Serial_PutString((uint8_t *)"==========================================================\r\n\n");

    /* Clean the input path */
    __HAL_UART_FLUSH_DRREGISTER(&huart1);
	
    /* Receive key */
    HAL_UART_Receive(&huart1, &key, 1, RX_TIMEOUT);

    switch (key)
    {
    case '1' :
      /* Download user application in the Flash */
      SerialDownload();
      break;
    case '2' :
      /* Upload user application from the Flash */
      SerialUpload();
      break;
    case '3' :
      Serial_PutString((uint8_t *)"Start program execution......\r\n\n");
      /* execute the new program */
      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
      /* Jump to user application */
      JumpToApplication = (pFunction) JumpAddress;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
      JumpToApplication();
      break;
    case '4' :
      if (FlashProtection != FLASHIF_PROTECTION_NONE)
      {
        /* Disable the write protection */
        if (FLASH_If_WriteProtectionConfig(OB_WRPSTATE_DISABLE) == HAL_OK)
        {
          Serial_PutString((uint8_t *)"Write Protection disabled...\r\n");
          Serial_PutString((uint8_t *)"System will now restart...\r\n");
          /* Launch the option byte loading */
          HAL_FLASH_OB_Launch();
          /* Ulock the flash */
          HAL_FLASH_Unlock();
        }
        else
        {
          Serial_PutString((uint8_t *)"Error: Flash write un-protection failed...\r\n");
        }
      }
      else
      {
        if (FLASH_If_WriteProtectionConfig(OB_WRPSTATE_ENABLE) == HAL_OK)
        {
          Serial_PutString((uint8_t *)"Write Protection enabled...\r\n");
          Serial_PutString((uint8_t *)"System will now restart...\r\n");
          /* Launch the option byte loading */
          HAL_FLASH_OB_Launch();
        }
        else
        {
          Serial_PutString((uint8_t *)"Error: Flash write protection failed...\r\n");
        }
      }
      break;
    default:
	Serial_PutString((uint8_t *)"Invalid Number ! ==> The number should be either 1, 2, 3 or 4\r");
	break;
    }
  }
}

3.Ymodem_Receive() 函数

这个函数是执行Ymodem传输协议功能的,参考https://blog.csdn.net/INT_TANG/article/details/117334848

2.flash_if.h文件修改

修改USER_FLASH_END_ADDRESS(片内Flash结束地址),和APPLICATION_ADDRESS(App起始地址),这里改成0x08008000,0x08000000~0x08007FFF用于存放bootloader(Note: the 1st sector 0x08000000-0x08007FFF is reserved for the IAP code)

/* End of the Flash address */
#define USER_FLASH_END_ADDRESS        0x080FFFFF
/* Define the user application size */
#define USER_FLASH_SIZE   (USER_FLASH_END_ADDRESS - APPLICATION_ADDRESS + 1)

/* Define the address from where user application will be loaded.
   Note: the 1st sector 0x08000000-0x08007FFF is reserved for the IAP code */
#define APPLICATION_ADDRESS   (uint32_t)0x08008000 

这些修改好可以编译跑一下看看bootloader的输出是否正常。
在这里插入图片描述

3.准备App程序

bootloader使用Ymodem下载时用的是bin文件,IAR中要修改ROM起始地址,中断向量起始地址和输出文件。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.烧录*.bin

然后就可以在SecureCRT里调用Send Ymodem来烧录这个*.bin程序了。
在这里插入图片描述
在这里插入图片描述

移植参考 https://blog.csdn.net/INT_TANG/article/details/117235294 IAR和Keil工程的操作都是一样的。

四、调试及其他注意事项

1.中断向量表偏移没设对

如果debug的时候发现程序进入hard fault大概率是中断向量表没设对,在程序最开始加上下面的这段把向量表的起始地址强制设为App的起始地址。

SCB->VTOR=0x08008000;

2.进入App后时钟起不来或时钟混乱

官方手册上说:一旦启用了PLL,就无法更改主PLL配置参数,因此建议在启用PLL之前先对其进行配置(选择HSI或HSE振荡器为PLL时钟源,以及除法因子M,P,Q和乘法因子N的配置)。

也就是说PLL在启动之后便不能够重新配置。可以先把时钟改为内部时钟然后再配置PLL。

参考 https://blog.csdn.net/xiaoyuanwuhui/article/details/108772487

3.在bootloader的工程里怎么调试app程序

只能看Flash里反汇编的程序,一步步反推app哪里出现了问题。
IAR里看PC寄存器的值() PC指向当前程序运行的地址,跑到0x08008000以后就是进入App程序了。
然后通过看Disassembly反汇编查看对应的App的C程序在哪一行出现问题了。
App生成bin文件和hex文件也可以生成汇编文件的,用这里的反汇编和App的汇编文件去对比。
在这里插入图片描述

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32CubeMXSTMicroelectronics提供的一款强大的工具,用于配置和初始化STM32微控制器。它可以帮助开发人员生成初始化代码,并提供了一系列图形化的界面来配置引脚、时钟、外设和中断等。在STM32CubeMX中,可以选择启用Bootloader功能,以便实现固件的升级。引用提到,官方提供的HAL库是常用的开发STM32程序的库,而基于HAL库的Bootloader编写是一种常见且方便的方法。通过编写简单的Bootloader代码,可以实现通过串口或其他接口来进行固件的升级。为了方便升级过程,一般采用boot在前、主APP在后的FLASH存储分布方式,这样可以在升级失败时避免设备变砖。引用提到,STM32还提供了官方的通用Bootloader程序,即OpenBootLoader,支持串口等多种接口。另外,根据引用的描述,当使用Ymodem下载时,可以使用bin文件,并需要在IAR中修改ROM起始地址、中断向量起始地址和输出文件。因此,STM32CubeMX和HAL库提供了方便的开发环境和工具,可以帮助开发人员编写和使用Bootloader来实现STM32微控制器的固件升级功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [基于STM32CubeIDE和MX的HAL库来编写的BootLoader](https://blog.csdn.net/QQ3200028121/article/details/120474722)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [stm32f4 CubeMX生成IAR工程 移植ST官方 Bootloader 教程](https://blog.csdn.net/silent_dusbin/article/details/123511914)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值