[STM32]

STM32在线升级固件两种常用实现方式

[复制链接]
553|0
手机看帖
扫描二维码
随时随地手机跟帖
forgot|  楼主 | 2022-11-17 10:54 | 显示全部楼层 |阅读模式
本帖最后由 forgot 于 2022-11-17 10:57 编辑

#申请原创#
现在物联网越来越发达,很多嵌入式产品设计完成之后需要进行BUG修复升级或者个性化功能定制升级,今天主要说一说以STM32为代表的嵌入式产品可以远程升级的两种方式,标题说是两种常用的升级方式,其实无非也就是我本人用过的两种方式,在此做一个简单的分享,说得可能不好,但是希望能有帮助到第一次做远程升级功能的朋友们。
两种方式:
1、通过串口Ymodem协议进行升级,
2、通过网口TFTP方式进行升级

既然要升级,那程序必须是两部分构成:
1、Bootloader程序,实现程序的启动引导和升级固件接收的功能;
该程序应烧录于0x8000000地址,并且分配一定的code空间,如0x3000
2、APP用户应用程序,实现用户功能程序的运行和接收升级命令的功能;
该程序应该烧录于Bootloader程序之后,如0x8003000;并且在Bootloader程序中需要指定该程序跳转的位置:#define ApplicationAddress  0x8003000
如图:
微信图片_20221117104837.png
一、串口Ymodem协议进行升级方式:
1、首先设计Bootloader程序,在程序中奖基本的外设配置完成,如串口,因为需要用到串口进行Ymodem协议固件接收来升级,所以用到哪个串口升级就必须配置好哪个串口;然后需要进行ymodem.c程序的移植。这样就可以通过串口进行.BIN固件的接收升级(这里可以参考网上的官方IAP例程)。
void IAP_Init(void)
{
//结构体变量
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//开启总线时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//管脚配置
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
//串口配置   
      USART_InitStructure.USART_BaudRate = 115200;
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
      USART_InitStructure.USART_StopBits = USART_StopBits_1;
      USART_InitStructure.USART_Parity = USART_Parity_No;
      USART_InitStructure.USART_HardwareFlowControl =                                         USART_HardwareFlowControl_None;
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

      USART_Init(USART2, &USART_InitStructure);
      USART_Cmd(USART2, ENABLE);        
}
Bootloader程序启动后,应有判断是否需要进行固件升级,并且在后续需要通过跳转函数跳转到APP应用程序:
void APP_RUN(void)
{
    JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
    /* Jump to user application */
    Jump_To_Application = (pFunction) JumpAddress;
    /* Initialize user application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) ApplicationAddress);
    Jump_To_Application();        
}
3、APP应用程序中应该有判断是否需要升级的入口,如按键、远程命令等,通过软件复位等方式可以让程序回到Bootloader程序并开始接收固件包进行FLASH设定的位置进行烧写新固件。

二、网口TFTP方式进行升级方式
跟串口升级原理类似,首先设计Bootloader程序,就是要配置好网卡驱动外设,开UDP套接字等操作,并且一直TFTP.c,这样就可以通过网络TFTP方式来实现.BIN固件的接收升级;然后通过跳转函数跳转到APP应用程序,具体不在重复描述;

/**tftp  初始化**/
void TFTP_init()
{
//初始化TFTP
    init_tftp();
    open_tftp_socket(SOCK_TFTP); /*初始化套接字*/
    g_tftp_rcv_buf = g_socket_rcv_buf;/*指向内存*/
}

因为以上两种方式升级固件都是以.bin的方式进行固件发送与升级,顺便说一下KEIL.BIN文件的编译生成方法:

1、点击KEIL魔术棒"Options for Target" → 单击" Output " → 按下面截图所示配置,设置完成后 → 点击"Build"编译 → 生成axf输入文件
微信截图_20221117103904.png

2、单击User” → 按下面截图所示配置,配置完成后→ 点击"Build"编译 → 生成bin输出文件,实际是调用KEIL安装目录下的一个工具生成的.BIN。(具体的命令格式每人的项目工程目录不一样就说了,大家可以参照网上的命令解析)
微信截图_20221117103938.png

最后提醒一点:在APP程序开头需要重新设置向量表的偏移位置:NVIC_SetVectorTable( NVIC_VectTab_FLASH,0x3000);



使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1244

主题

10779

帖子

49

粉丝