史上最牛逼的单片机升级方式汇总(含bootloader自升级)

一、概述        

        绝大多数嵌入式项目都离不开升级,因为远程升级可以大大降低产品的售后成本。单片机根据实际项目应用以及自身资源性能,在执行升级设计的时候需要考虑适合自身的升级方式,本文总结了常见的几种实用升级方式,供大家参考学习。

1.1 boot+app+backup(拷贝升级)

        两个大小相同的分区app、backup,app分区存放要执行的固件,当OTA升级时会先把OTA数据包写入backup分区,然后再将OTA数据搬移到app数据区,最后从app数据区启动执行。

优点:

①有备份区,可用于在线升级和网络升级

②程序安全性和鲁棒性较好

缺点:

①需要和app相同大小的额外flash空间

②需要增加判断升级异常后的处理逻辑,增加了程序设计的难度

③不能对boot进行升级

1.2 boot+app1+app2(A/B分区、乒乓升级)

        两个大小相同的分区APP1、APP2,如果当前在APP1分区执行代码,升级时就把固件下载到APP2分区。升级成功后设备重启,模组切换到APP2分区执行;下次再升级就切换到APP1分区,一直这样轮询。

优点:

①有A/B两个不同内容的分区,可用于在线升级和网络升级;

②升级更加灵活,下载好升级固件后是直接跳转,而不需要再次拷贝,相对拷贝升级减少一次拷贝步骤。

缺点:

①需要和app相同大小的额外flash空间

②同样需要增加判断升级异常后的处理逻辑,增加了程序设计的难度;

③不能对boot进行升级。

1.3 Boot0+boot1+标志区+app(APP和boot两重升级)

         按照上述的流程图可以明白,只要是标志区的跳转标记是正常模式或者bootloader_flag未被置位,说明是没有升级过boot1或者已经升级成功的,进而就跳转到boot1。否则都直接进入APP,这样可以防止APP里面升级boot1失败了而且不小心断电了,不用经过Boot1进入APP再次升级boot1。

        在boot0里面会根据标志区的升级模式(正常和升级)和升级标志(boot0是否升级,app是否升级)选择启动方式,正常执行boot0->boot1->app的流程;boot1里面可进入app和进行app升级,在app里可进行boot1的升级和设置app升级标志位。

优点:

①不仅可以升级app,而且可以升级bootloader;

②并且可以有效避免boot因升级失败导致需重新拆箱进行JTAG升级的麻烦;

缺点:

①由于需要设置boot0和标志区占用空间特别小,但又要单独设置一个片区,对于flash单个片区较大的情况就存在严重浪费;

②流程相对比较复杂,设计过程中容易出现问题。

1.4 boot+app

这种方案是最简单的升级方案,当boot里检测到升级标志会直接更新app,然后复位。

优点:

①逻辑简单;

②FLASH占用最少;

③最基础的本地升级方式。

缺点:

①无备份区,不适合进行网络升级和在线升级(如果想,可以借助另一块带网络功能的单片机来实现);

②不能升级boot

1.5 boot0+boot1+app(APP和boot两重升级)

        上电进入boot0;判断是否有升级指令,如果没有则进入boot1,然后进入app正常运行,因为无升级指令所以此过程不可能有升级flag;如果有升级指令且为app升级,则擦除app区域并在app起始地址写入app_flag=1,然后跳入boot1等待app升级固件,然后按照国网协议进行升级,升级完成之后将app_flag复位然后进行系统复位;如果为boot升级,则擦除boot1区域并在boot1起始地址写入boot_flag=1,然后跳入app等待boot1升级固件,然后按照国网协议进行升级,升级完成之后将boot_flag复位然后进行系统复位。

优点:

①稳定可靠,不会因为断电导致变砖的情况,他可以上电继续重新升级;

②对于boot和app双升级方案来说,用了最少的flash配置,因为一般单片机的flash启动必须从0地址开始,所以要刷新boot必须要有一个引导区来引导程序跳转执行。

③不仅可以升级app,而且可以升级bootloader。

缺点:

①无法备份,只能是本地升级。

二、总结提升

        根据第一部分的介绍,本质上将5种升级方式概括为带备份去不带boot升级(①②)不带备份区带boot升级(③⑤)不带备份区不带boot升级(④)这三种,当然你flash足够大并且有升级bootloader的需求也可以优化为带备份区带boot升级。

       升级方式有很多,JTAG、串口、CAN、网口等,但是本质上也就2种,本地升级在线升级

本地升级不需要备份区,因为即便升级过程中断电了,仍然可以重新再来。当然本地升级也可以实现在线升级,我们只需要接一个能联网的单片机,确保这个单片机接收到完整固件后再升级,不也相当于本地升级嘛~

        在线升级一定需要备份区,因为如果没有备份区,假如升级过程中断网,因app已经被破坏所以无法正常运行。当然备份区可实现的功能不止是简单的对app进行备份,我们还可以扩展为A/B分区、后台升级、以及实现不断电升级等等更加高级和人性化的功能,这里不一一谈啦~

        综上分析,我们可以做出如下决策:

①假如我们是本地升级且升级容许断电,那就不需要备份区;

②假如我们需要boot更新,那就需要带boot升级;

③假如我们需要在线升级,那就一定需要备份区。

还有什么升级的骚操作,或者我写的有bug?,留言留言^3^

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是STM32G0系列单片机远程升级bootloader的CAN升级数据接收代码的示例: ```c #include "stm32g0xx_hal.h" #include "stm32g0xx_hal_can.h" #include "bootloader.h" CAN_HandleTypeDef hcan; void CAN_Config(void) { CAN_FilterTypeDef can_filter; hcan.Instance = CAN; hcan.Init.Prescaler = 8; hcan.Init.Mode = CAN_MODE_NORMAL; hcan.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan.Init.TimeSeg1 = CAN_BS1_13TQ; hcan.Init.TimeSeg2 = CAN_BS2_2TQ; hcan.Init.TimeTriggeredMode = DISABLE; hcan.Init.AutoBusOff = ENABLE; hcan.Init.AutoWakeUp = DISABLE; hcan.Init.AutoRetransmission = ENABLE; hcan.Init.ReceiveFifoLocked = DISABLE; hcan.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan) != HAL_OK) { Error_Handler(); } can_filter.FilterBank = 0; can_filter.FilterMode = CAN_FILTERMODE_IDMASK; can_filter.FilterScale = CAN_FILTERSCALE_32BIT; can_filter.FilterIdHigh = 0x0000; can_filter.FilterIdLow = 0x0000; can_filter.FilterMaskIdHigh = 0x0000; can_filter.FilterMaskIdLow = 0x0000; can_filter.FilterFIFOAssignment = 0; can_filter.FilterActivation = ENABLE; if (HAL_CAN_ConfigFilter(&hcan, &can_filter) != HAL_OK) { Error_Handler(); } if (HAL_CAN_Start(&hcan) != HAL_OK) { Error_Handler(); } if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) { Error_Handler(); } } void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { CAN_RxHeaderTypeDef can_rx_header; uint8_t can_rx_data[8]; if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can_rx_header, can_rx_data) == HAL_OK) { if (can_rx_header.StdId == CAN_UPGRADE_MSG_ID) { bootloader_process_can_upgrade_data(can_rx_data, can_rx_header.DLC); } } } ``` 该示例代码中,CAN_Config()用于配置CAN硬件,并将CAN接收滤波器设置为接收CAN_UPGRADE_MSG_ID标准帧。HAL_CAN_RxFifo0MsgPendingCallback()是CAN接收中断回调函数,用于接收CAN数据并处理远程升级bootloader的CAN升级数据。在示例代码中,假设远程升级bootloader的CAN升级数据使用CAN_UPGRADE_MSG_ID标准帧发送。可以根据实际需求修改CAN接收滤波器和CAN接收中断回调函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值