[PSOC™ Creator] ModusToolbox环境下PSOC C3的双启动区DFU固件升级实现方法

[复制链接]
82|11
在海边聆听 发表于 2026-8-17 15:50 | 显示全部楼层 |阅读模式
在ModusToolbox环境下,PSoC C3系列MCU支持通过双启动区(Dual-Bank)机制实现设备固件升级(DFU)。该机制利用Flash存储器的两个独立分区(Bank A和Bank B)分别存放运行固件和新固件,配合启动加载程序(Bootloader)在复位时选择有效分区启动,实现了固件更新过程中的数据完整性和系统可靠性。

PSoC C3系列的Flash存储器通常被划分为两个等大小的Bank,每个Bank可独立擦除和编程。在双Bank DFU方案中,系统运行于其中一个Bank(活动区),同时通过串行接口(如UART或USB)接收新固件数据,并将其写入另一个Bank(备用区)。固件接收完成后,系统对备用区固件进行完整性校验(如CRC32),校验通过则设置启动标志并触发系统复位。复位后Bootloader根据启动标志选择更新后的Bank启动,完成一次完整的DFU流程。

在ModusToolbox中实现此功能需要创建一个包含Bootloader和Bootloadable两个组件的项目。Bootloader项目负责启动时的分区选择和跳转逻辑,Bootloadable项目则包含实际应用程序固件。以UART为传输介质的DFU实现为例,Bootloader中通过Cy_Bootloader_Start()函数启动Bootloader组件,并在循环中监听来自串口的DFU命令帧。当接收到擦除指令时,Bootloader调用Cy_Flash_EraseRow()擦除备用Bank的Flash区域;接收到编程数据帧时,调用Cy_Flash_WriteRow()将数据写入Flash。写入完成后,Bootloader通过Cy_Bootloader_VerifyApplication()验证固件校验和,验证通过后设置下一次启动的Bank并复位进入应用程序。

以下是一个简化的DFU流程示例,展示Bootloader判断启动分区并跳转的过程:

c
#include "cy_pdl.h"
#include "cy_bootloader.h"

int main(void)
{
    /* 初始化系统 */
    SystemInit();
   
    /* 检查启动标志,决定从哪个Bank启动 */
    uint32_t boot_flag = Cy_Bootloader_GetBootFlag();
   
    if (boot_flag == BOOT_FROM_BANK_B)
    {
        /* 设置栈顶指针和中断向量表为Bank B的地址 */
        __set_MSP(*(uint32_t*)BANK_B_START_ADDR);
        SCB->VTOR = BANK_B_START_ADDR;
        
        /* 跳转到Bank B的复位处理函数 */
        void (*app_entry)(void) = (void(*)(void))(*(uint32_t*)(BANK_B_START_ADDR + 4));
        app_entry();
    }
    else
    {
        /* 默认从Bank A启动 */
        __set_MSP(*(uint32_t*)BANK_A_START_ADDR);
        SCB->VTOR = BANK_A_START_ADDR;
        
        void (*app_entry)(void) = (void(*)(void))(*(uint32_t*)(BANK_A_START_ADDR + 4));
        app_entry();
    }
}
在应用程序(Bootloadable)侧,需实现固件接收逻辑以响应来自主机的升级命令。当应用程序收到DFU启动指令后,设置DFU标志并执行系统复位,使系统进入Bootloader模式。

双Bank DFU方案依赖有效的固件校验机制。ModusToolbox的Bootloader组件默认支持CRC校验,在配置界面中勾选“Enable application verification”即可启用该功能。Bootloader在每次启动时对备用Bank的固件进行CRC32校验,校验失败则自动回退至原有Bank,确保系统在任何情况下都能正常启动。

通过合理配置ModusToolbox中的Bootloader和Bootloadable组件,开发者可以在不依赖外部存储芯片的前提下实现可靠的固件升级功能,降低系统成本的同时提升了维护便利性。该方案适用于工业控制、物联网边缘设备等需要远程固件更新的应用场景。
喂什么玩意 发表于 2026-8-24 20:59 | 显示全部楼层
双Bank DFU确实稳,但Flash空间利用率只有一半,做项目前得先评估下代码量。PSoC C3如果跑复杂算法,App本身可能就占几十K,再分一半给备份区,很容易不够用。如果成本敏感,其实单Bank加外部EEPROM存校验数据也是个折中方案
突然下起雨 发表于 2026-8-25 08:59 | 显示全部楼层
Bootloader和App之间的跳转逻辑是坑最多的地方。特别是中断向量表的重定向,很多人忘了在App启动代码里修改VTOR寄存器,导致进App后一开中断就HardFault。建议在Bootloader里做个简单的内存清零动作,避免残留状态干扰新固件运行
怎么总是重复啊 发表于 2026-8-26 09:12 | 显示全部楼层
CRC32校验虽然经典,但在安全要求高的场景下可能不够。现在黑客工具那么多,伪造个合法CRC太容易了。建议结合PSoC C3的安全模块,用HMAC或者RSA签名来做完整性校验,虽然慢点,但能防止恶意固件注入
lxs0026 发表于 2026-8-28 10:00 | 显示全部楼层
升级过程中的掉电保护不仅要靠双Bank,还得考虑标志位的写入可靠性。Flash写操作本身就有失败概率,建议把“升级完成”这个标志位多写几个副本在不同地址,启动时做多数表决。不然万一标志位写坏了,好固件也起不来
烟雨蒙蒙520 发表于 2026-8-28 11:01 | 显示全部楼层
ModusToolbox里的DFU库封装得挺好,但灵活性稍差。如果想自定义通信协议,比如走私有TCP通道而不是标准的USB HID,就得改不少底层代码。这时候不如直接参考英飞凌的AN21xxxx应用笔记,手写个轻量级Bootloader更可控
大鹏2365 发表于 2026-8-29 13:59 | 显示全部楼层
关于升级速度,UART确实太慢了。如果是批量生产或者现场维护,强烈建议用USB或者SPI接口传固件。PSoC C3的USB FS控制器跑DFU绰绰有余,几兆的固件几十秒就能传完,比UART几分钟的体验好太多
有何不可0365 发表于 2026-8-29 21:02 | 显示全部楼层
有个细节容易被忽视:App版本回滚机制。万一新固件有Bug,用户想退回去怎么办?双Bank天然支持A/B切换,但需要在Bootloader里记录版本号。建议在Flash里留个专门区域存历史版本信息,方便实现一键回退功能
漫天星yl 发表于 2026-8-30 08:03 | 显示全部楼层
调试双Bank程序时,JTAG连接可能会干扰Bootloader判断。有些Bootloader检测到JTAG存在就不进升级模式,这逻辑没问题,但有时候调试器复位时序不对会导致误判。建议在开发阶段留个强制进入DFU模式的GPIO按键,省得反复插拔调试器
t61000 发表于 2026-8-30 16:11 | 显示全部楼层
PSoC C3的Flash寿命虽然标称10万次,但频繁DFU测试还是会心疼。建议在RAM里跑个模拟层验证逻辑,确认无误后再真正写入Flash。特别是校验算法,先在内存里跑通,别拿Flash当RAM刷
kqh11a 发表于 2026-8-31 08:07 | 显示全部楼层
Bootloader本身的更新是个死循环问题。如果Bootloader有Bug怎么修?PSoC C3通常支持Bootloader自更新,但这部分逻辑要格外小心,最好有硬件看门狗兜底。不然一旦自更新失败,芯片就真砖了,只能上编程器救
OKAKAKO 发表于 2026-8-27 22:41 | 显示全部楼层
Bootloader判断启动分区并跳转这个很实用的操作
您需要登录后才可以回帖 登录 | 注册

本版积分规则

53

主题

614

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部