F29H85x MCU基于Flash与UART的二级引导程序(SBL)FOTA实现详解

发布时间:2026/7/23 21:04:42
F29H85x MCU基于Flash与UART的二级引导程序(SBL)FOTA实现详解 1. 项目概述与核心价值在嵌入式产品尤其是工业控制、汽车电子和物联网设备的开发生命周期中固件更新是一个绕不开的课题。想象一下你的设备已经部署到全国各地的工厂车间或者成千上万的智能终端上这时发现了一个需要修复的软件缺陷或者需要增加一个新功能。如果每次都需要技术人员跑到现场通过物理接口如JTAG连接电脑进行烧录其成本和时间开销将是灾难性的。这正是固件空中升级Firmware Over-The-Air, FOTA技术要解决的核心痛点实现远程、安全、可靠的固件更新。FOTA并非一个单一的功能而是一套完整的系统工程其核心在于一个常驻在设备非易失性存储器中的特殊程序——引导加载程序Bootloader。这个程序在设备上电后先于主应用程序运行负责检查是否有新的固件需要更新并管理固件的下载、验证、存储和切换。今天我们以德州仪器TI的F29H85x系列高性能实时微控制器MCU为平台深入探讨如何实现一个基于Flash的、通过UART通信的二级引导加载程序Secondary Bootloader, SBL并完成完整的FOTA流程。这个方案特别适合那些没有复杂网络栈但具备串口通信能力的设备是许多工业场景下的经典选择。为什么选择F29H85x和UART SBL这个组合首先F29H85x系列MCU内置了灵活的Flash存储体Bank架构和硬件安全模块HSM为安全、可靠的双备份固件升级提供了硬件基础。其次UART作为最基础、最稳定、资源占用最少的通信接口之一几乎在所有嵌入式设备上都有预留是实现“最后一道防线”式更新的可靠手段。基于Flash的SBL意味着引导程序本身也存储在Flash中无需每次更新都通过复杂的BootROM流程加载简化了操作并提升了可靠性。本文将带你从原理到实践手把手拆解整个流程分享我在实际项目中趟过的坑和积累的经验目标是让你看完后能独立在自己的F29H85x项目上实现这一关键功能。2. F29H85x FOTA方案的整体架构与设计思路在动手写代码和配置工具之前我们必须先理解整个FOTA方案是如何在F29H85x的硬件和软件框架下协同工作的。这就像盖房子前先看蓝图理解了整体结构后面的每一块砖该怎么放就清晰了。2.1 硬件基石Flash存储体Bank架构F29H85x的Flash内存这里主要指程序Flash如FLC1并非一整块连续区域而是被划分成了多个“存储体”。对于FOTA而言最关键的是理解“Bank Mode”和“Active/Inactive Region”的概念。Bank Mode存储体模式这决定了CPU如CPU1 CPU3可以访问的Flash地址空间如何划分。常见的模式有Bank Mode 0传统模式CPU1独占所有程序Flash。这种模式下无法实现“运行中更新”因为擦写当前运行代码所在的Flash区域会导致程序崩溃。Bank Mode 1这是实现CPU1 FOTA的典型模式。它将CPU1的程序Flash划分为两个大小相等的“区域对”Region Pair例如FLC1.B0/B1作为活动区域Active RegionFLC1.B2/B3作为非活动区域Inactive Region。CPU1始终从活动区域执行代码。当需要更新时新的固件被下载并编程到非活动区域更新完成后通过一个“Bank Swap”操作交换两个区域的角色新的固件就变成了活动区域设备复位后即运行新版本。这个过程就像双BIOS切换确保了总有一个可用的版本。Bank Mode 3在多核如CPU1CPU3场景下使用。它将Flash划分为三部分一部分给CPU1一部分给CPU3还可能有一部分共享或作为数据区。在这种模式下CPU1和CPU3各自都有自己对应的活动/非活动区域对可以独立进行FOTA升级。核心设计考量选择哪种Bank Mode直接决定了你的固件内存布局和升级策略。对于单CPU应用Bank Mode 1是标准选择。如果你的应用使用了CPU3例如专门处理通信或安全任务就必须使用Bank Mode 3并确保SBL和主机工具都支持该模式。2.2 软件核心基于Flash的UART SBLSBL在这里扮演着“更新管理器”的角色。它需要实现以下核心职责通信通过UART与主机如PC上的升级工具建立连接接收命令和固件数据包。命令解析解析主机发送的指令例如“DFU CPU1”设备固件升级CPU1或“CPU1_CP_FLASH_IMAGE”带安全认证的CPU1固件升级。Flash操作根据命令安全地擦除目标非活动区域并将接收到的固件数据编程到Flash中。这里必须严格遵循Flash的擦写时序和等待状态要求。固件验证编程完成后进行校验如CRC校验以确保数据完整性。在安全启动HS-SE状态下还需与HSM协作使用X.509证书验证固件的合法性和完整性。元数据管理在指定位置如Data Flash的第一个字节写入当前的Bank Mode信息。更重要的是在非活动区域的“Bank Management Region”写入交换标志以便在下次复位时BootROM或SBL能执行Bank Swap操作。状态同步向主机报告操作成功或失败的状态。“基于Flash”意味着这个SBL本身是作为一个应用程序被预先烧录到Flash的活动区域中。设备正常启动时运行的就是这个SBL或者SBL应用程序的组合体。当它检测到升级事件如收到特定UART命令便切换到“升级模式”执行上述流程。这与需要每次从UART加载到RAM中运行的“UART Flash Kernel”有本质区别后者更像一个临时工而前者是常驻管家。2.3 安全链条HSM与X.509证书对于需要防止固件被篡改或恶意替换的高安全性应用F29H85x的硬件安全模块HSM是关键。安全升级流程对应CPU1_CP_FLASH_IMAGE等命令大致如下证书传递主机先将一个X.509证书发送给SBLSBL将其传递给HSM。固件传输与鉴权主机分块发送已签名的固件。SBL将每个数据块传递给HSM。HSM处理HSM在内部使用证书中的公钥验证固件签名的有效性确保固件来自可信源且未被篡改。验证通过后HSM亲自将固件数据编程到目标Flash区域。这是一个关键点在安全状态下对受保护Flash区域的编程操作由HSM直接完成CPU1无法直接干预这构成了硬件级的信任根。最终验证与切换全部固件编程完成后HSM进行最终验证。验证成功SBL再写入Bank管理信息准备切换。这个流程确保了从固件来源、传输到写入的整个链条都处于安全保护之下。在实际项目中是否启用安全升级取决于产品的安全等级要求。启用后工具链和镜像生成流程都需要相应调整必须集成签名和证书生成步骤。2.4 主机侧工具链整个FOTA是设备端SBL和主机端升级工具的二人转。TI SDK提供了uart_flash_programmer这个主机命令行工具。你需要重点关注两个可执行文件uart_flash_programmer.exe: 用于与UART Flash Kernel配合进行初始烧录或恢复。它会先发送Kernel镜像到设备RAM。uart_flash_programmer_appIn.exe: 用于与基于Flash的SBL配合。它假定SBL已经在设备Flash中运行因此直接开始发送命令和数据。一个常见的混淆点很多开发者第一次尝试用uart_flash_programmer.exe去连接已经运行Flash SBL的设备结果通信失败就是因为工具开头会尝试发送Kernel而设备端SBL并不期待这个数据导致协议错乱。记住这个区别能节省大量调试时间。3. 开发环境搭建与工程配置详解理论清晰后我们进入实战环节。第一步是把TI官方提供的示例工程跑起来理解其结构并适配到自己的硬件平台。3.1 获取与定位示例工程首先确保你安装了对应版本的F29H85x SDK。示例工程路径通常为你的SDK安装路径\mcu_sdk_f29h85x\examples\driverlib\single_core\flash\flash_based_UART_SBL_with_FOTA在这个目录下你会找到CCSCode Composer Studio工程文件。用CCS打开它。工程里通常包含以下几个关键部分SBL主体代码实现UART驱动、命令解析、Flash驱动调用Fapi接口、升级状态机等。链接命令文件.cmd这是重中之重。它定义了代码、数据在内存中的布局。对于FOTA必须确保所有需要烧录到Flash的段section特别是.text代码段其起始地址是512位64字节0x40对齐的。这是因为Flash编程操作有对齐要求。在.cmd文件中你会看到类似 FLASH_RP0, palign(32)的语句palign(32)就是确保32字32*16bit512bit对齐。示例应用程序FOTA_Example_Application这是一个简单的演示程序被链接到SBL的后面一起生成一个完整的.out和.bin文件。在实际项目中你需要替换成自己的应用程序。3.2 理解并选择构建配置Build Configuration在CCS的“Project Explorer”视图中右键点击工程选择“Build Configurations” - “Set Active”你会看到几个关键的配置BANKMODE_1用于CPU1 FOTA的非安全HS-FS状态场景。BANKMODE_3用于CPU3 FOTA的非安全场景。BANKMODE_1_CP用于CPU1 FOTA的安全HS-SE状态场景。BANKMODE_3_CP用于CPU3 FOTA的安全场景。选择逻辑你的设备最终运行在什么安全状态HS-FS还是HS-SE你需要升级哪个CPUCPU1 或CPU1和CPU3 根据答案选择对应的配置。例如一个在HS-SE状态下需要升级CPU1和CPU3的产品就需要分别编译BANKMODE_1_CP和BANKMODE_3_CP的SBL镜像注意它们可能是同一个工程的不同配置输出。3.3 硬件连接与引脚配置SBL需要通过UART与主机通信。你需要确认使用哪个UART模块示例工程默认可能使用某个UART如SCIA。你需要根据自己硬件原理图上UART转USB芯片的连接修改代码中的UART初始化部分包括GPIO复用配置PINMUX、波特率、停止位等。Boot Mode配置引脚为了让设备上电后进入Flash Boot模式从而执行Flash中的SBL需要正确配置GPIO72和GPIO84的上拉/下拉状态。具体配置请查阅TRM技术参考手册的Boot章节。通常在SBL运行后你可以通过代码重新配置这些引脚作为普通UART引脚使用。连接稳定性确保USB转串口线连接可靠地线共地。工业环境下建议使用带隔离的USB转串口模块避免地环路干扰导致数据错误。3.4 生成含X.509证书的二进制文件.bin这是安全升级和非安全升级都需要的步骤因为SBL期望固件镜像的前0x1000字节4KB是证书区域。对于非安全升级这个区域可以是一个“空”的证书或填充特定格式的无效数据但结构必须存在。TI提供了脚本或工具来生成这种“Combined Image”。通常流程是编译你的应用程序生成.out文件。使用hex2000或ofd2000等工具将.out转换为纯二进制.bin文件。使用signing tool如TI的secure_boot_sign_ofd工具链将一个X.509证书.pem或.der格式合并到.bin文件的开头。对于非安全镜像你可能需要生成一个“自签名”证书或使用工具生成一个格式正确的占位证书。关键检查点生成的最终.bin文件其大小应该是0x1000 应用程序实际大小并且应用程序的入口地址在.bin文件中的偏移量是0x1000。你可以用二进制查看工具如HxD打开生成的.bin文件确认前4KB是有数据的即使是安全证书的二进制数据并且你的应用程序代码从0x1000开始。4. 实操流程从零开始完成一次完整的FOTA升级假设我们有一个全新的F29H85x设备需要部署支持FOTA的系统并进行第一次远程更新模拟。以下是详细步骤。4.1 阶段一初始SBL与V1.0应用烧录此阶段目标是将Flash SBL和第一个版本的应用程序V1.0烧录到设备的Flash活动区域。方法A通过CCS和JTAG烧录开发阶段最常用连接与配置使用JTAG仿真器连接设备在CCS中创建或导入F29H850TU9.ccxml目标配置文件以“Project-less Debug”模式启动。检查Bank Mode连接CPU1在CCS的“Registers”视图中查看SSU_GEN_REGS.BANKMODE寄存器。如果是新芯片可能为0。我们需要将其设置为Bank Mode 1值0x6。可以通过CCS的“Flash Settings”配置工具完成右键CPU1 - Properties - Flash Settings选择Bank Mode 1并勾选“Program BANKMGMT”然后执行烧录并复位设备。加载SBL镜像在CCS菜单选择 Run - Load - Load Program 选择编译生成的flash_based_uart_sbl_with_fota.out文件。在加载前务必勾选Flash插件中的“FOTA Enable”复选框。这个操作会确保程序被烧录到当前Bank Mode下的活动区域例如Bank Mode 1下的FLC1.B0/B1。验证运行加载完成后复位设备让PC指针运行到SBL的入口。你可以单步或全速运行并通过串口工具如Tera Term连接到对应的COM口发送一个SYNC_STATUS命令具体格式参考主机工具说明如果收到SBL的响应说明SBL已成功运行。方法B通过UART Boot和Flash Kernel烧录适用于无JTAG口的生产或现场准备环境确保设备处于Bank Mode 0并将GPIO72拉低、GPIO84拉高使其进入UART Boot模式。触发复位。使用主机工具发送Kernel打开命令行进入UART Flash Programmer工具目录执行uart_flash_programmer.exe -d f29h85x -p COM34 -k .\ex3_uart_flash_kernel.cert.bin -a1 .\flash_based_uart_sbl_with_fota.bin这个命令会先通过UART将Flash Kernel加载到设备RAM并运行然后Kernel会接收-a1参数指定的SBL镜像并将其烧录到Flash此时在Bank Mode 0下会烧录到CPU1的默认地址空间。切换至Bank Mode 1烧录完成后通过CCS或如果SBL已包含模式切换功能将设备Bank Mode改为1并配置为Flash Boot模式GPIO721 GPIO841。复位并验证复位设备现在它应该从FlashBank Mode 1的活动区域启动运行我们刚烧录的SBL。同样用串口工具发送SYNC_STATUS验证。至此设备已经具备了通过UART接收升级命令的能力。4.2 阶段二准备V2.0应用并执行FOTA升级现在我们开发了应用程序的V2.0版本需要远程更新到设备上。生成V2.0镜像按照3.4节的步骤将你的V2.0应用程序编译链接生成带有X.509证书头的app_v2.bin文件。连接设备确保设备上电并运行着V1.0系统内含SBL。通过串口线连接设备与PC。执行FOTA升级命令使用uart_flash_programmer_appIn.exe工具注意是appIn版本因为SBL已在运行。执行以下命令uart_flash_programmer_appIn.exe -d f29h85x -p COM34 -a1 .\app_v2.bin这里没有-k参数因为不需要发送Kernel。工具会直接与Flash SBL通信。观察升级过程工具会依次执行以下操作并打印日志发送DFU CPU1命令包。SBL擦除非活动区域FLC1.B2/B3。工具开始发送app_v2.bin文件数据。SBL将数据编程到非活动区域并进行验证。SBL在非活动区域的Bank管理区写入交换标志。SBL在Data Flash的首字节写入当前Bank Mode。向主机返回成功状态。触发固件切换重要上述流程完成后V2.0固件已被写入非活动区域但设备仍在运行V1.0的代码。你需要手动触发一次设备复位。设备复位后BootROM或SBL的初始化代码会检查Bank管理区的标志发现有待交换的请求于是执行Bank Swap操作。交换完成后原来的非活动区域B2/B3存有V2.0变成活动区域而原来的活动区域B0/B1存有V1.0变成非活动区域。设备随后从新的活动区域启动V2.0应用程序开始运行。4.3 多核CPU3升级的特殊处理如果你的应用使用了CPU3流程会复杂一些核心在于CPU1需要负责CPU3的启动管理。工程配置编译SBL时必须使用BANKMODE_3或BANKMODE_3_CP配置。修改应用程序在你的CPU1应用程序即与SBL结合的那个应用的初始化阶段需要添加代码来配置并启动CPU3。主要步骤包括配置CPU3的引导地址指向CPU3固件在Flash中的起始位置。配置CPU3的非屏蔽中断NMI向量地址。将CPU3从复位状态中释放Bring CPU3 out of reset。 这段代码通常放在设备初始化完成之后中断初始化之前。可以参考TI SDK中多核示例的写法。升级流程升级CPU3固件时使用DFU CPU3命令。主机工具命令类似uart_flash_programmer_appIn.exe -d f29h85x -p COM34 -a3 .\cpu3_app_v2.bin。SBL会处理CPU3对应非活动区域的擦写和Bank管理信息设置。复位后CPU1的SBL/应用会加载新的CPU3固件并启动它。5. 深度排查常见问题与实战技巧在实际部署中你几乎一定会遇到各种问题。下面是我总结的常见“坑”及其解决方案。5.1 链接与镜像生成相关问题主机工具报错提示编程失败或设备端SBL报告Flash编程错误。排查首要检查链接文件确认所有分配到Flash的段如.text.cinit.switch等都使用了palign(32)进行512位对齐。未对齐是导致Flash API操作失败的最常见原因。检查.bin文件头用二进制编辑器打开生成的.bin文件查看前0x1000字节。如果是安全升级这里应是有效的X.509证书数据如果是非安全升级这里也不能全是0xFF或0x00需要有正确的结构例如一个填充的证书头。一个快速的验证方法是使用TI提供的示例证书和签名工具流程先确保能生成一个可工作的镜像再对比自己生成的镜像结构。检查镜像大小确认你的应用程序编译后没有超出为它分配的Flash区域大小。在Bank Mode 1下每个区域活动/非活动的大小是总Flash的一半要留出足够的空间给SBL和应用程序。5.2 通信与命令相关问题主机工具连接超时收不到SBL的响应。排查确认COM口和波特率这是最基础也最易错的。确保主机工具指定的COM口号与设备连接的串口一致。确保SBL代码中配置的UART波特率与主机工具设置的波特率完全匹配如115200。区分工具再次强调连接已运行Flash SBL的设备请使用uart_flash_programmer_appIn.exe而不是uart_flash_programmer.exe。检查硬件流控有些串口芯片或驱动默认启用了硬件流控RTS/CTS。如果电路板上没有连接这些流控线会导致通信卡死。尝试在主机串口工具或代码中禁用硬件流控。监听通信数据使用一个USB转串口监听器或软件虚拟串口对串联在主机和设备之间抓取原始的通信数据包。对比分析主机发送的命令格式和设备实际的响应可以快速定位是命令解析错误还是数据包格式问题。5.3 Bank Mode与状态相关问题执行CPU3升级或安全升级时主机工具报错提示设备状态不正确。排查确认Bank Mode对于CPU3升级设备必须处于Bank Mode 3。通过CCS读取SSU_GEN_REGS.BANKMODE寄存器确认。同时SBL也必须是用BANKMODE_3配置编译的。确认安全状态对于安全升级命令包含_CP_设备必须处于HS-SE状态。这通常需要通过特定的密钥和流程将设备从HS-FS状态转换到HS-SE状态。如果设备不在HS-SE状态HSM会拒绝相关操作。请查阅TIFS SDK中关于安全状态转换的文档。检查复位源Bank Swap操作通常在设备复位Reset时生效而不是软件复位Soft Reset。确保你触发的是完整的硬件复位如重启电源或拉低复位引脚。5.4 Flash操作与中断冲突问题在FOTA升级过程中正在擦写非活动区域如果触发了中断并且在中断服务程序ISR中尝试读写Data FlashFLC1.B4可能导致系统挂起或数据错误。解决方案这是一个需要谨慎处理的并发问题。如果必须在FOTA过程中操作Data Flash请在ISR中首先调用Fapi_checkFsmForReady()函数检查Flash状态机是否空闲。如果繁忙正在执行擦写则必须等待其完成。更稳健的设计是在开始FOTA关键操作前暂时禁用可能触发Data Flash操作的中断或者在应用层设计一个任务队列将Data Flash操作请求缓存起来等FOTA完成后再执行。5.5 版本回滚与可靠性设计官方示例主要演示了升级流程。但在产品化中必须考虑升级失败后的回滚机制。设计思路可以在Bank管理区域不仅存储“交换请求”还存储新固件的版本号和校验值。SBL在触发交换前先验证非活动区域固件的完整性如CRC32。只有验证通过才设置交换标志。此外可以设计一个“安全计数器”或“启动尝试计数器”。如果新固件启动后连续若干次无法成功运行到某个健康状态点则SBL在下次启动时自动回滚到旧版本。这需要在应用程序中与SBL约定一个“心跳”或“状态确认”机制。6. 进阶话题生产部署与持续集成考量当FOTA功能在实验室验证通过后如何将其集成到产品生产和后续的软件发布流程中是另一个维度的挑战。生产线烧录在生产线上你需要一种高效、可靠的方式为每一片空白的F29H85x芯片烧录初始的SBLV1.0应用程序。这时基于UART Kernel的方案4.1节方法B可能不够快。可以考虑使用专业的量产编程器通过JTAG接口并行烧录速度最快。编写一键烧录脚本将CCS的加载操作、Bank Mode设置等步骤通过CCS的脚本功能如使用DSLite命令行工具自动化减少人工操作错误。固件版本管理你需要建立一套规则来管理固件版号并将其嵌入到应用程序镜像中例如放在一个固定的Flash地址或某个数据结构里。SBL在升级前和升级后都能读取并报告版本号。主机升级工具也可以根据版本号决定是否需要升级。集成到CI/CD管道在敏捷开发中你可以搭建这样的自动化流程开发者提交代码到Git。CI服务器如Jenkins触发构建编译生成新的.bin文件。自动调用签名脚本如果需安全升级生成带证书的最终镜像。将镜像文件归档到版本仓库并自动生成一个包含升级命令的脚本。测试人员或现场设备可以通过调用这个脚本一键完成对新版本固件的验证升级。现场升级的健壮性考虑到现场网络环境不稳定升级包传输可能中断。你的SBL需要支持断点续传吗至少它应该能检测到不完整的镜像并拒绝激活它保持旧版本运行。同时升级协议中应有超时和重试机制主机工具端也应具备发送失败后重传整个包或部分包的能力。实现基于F29H85x的Flash SBL与FOTA是一个融合了硬件特性理解、底层驱动编写、通信协议设计和系统架构思考的综合性工程。它没有太多“黑科技”但每一个环节都需要扎实、细致的工作。从理解Bank Mode的硬件划分到调试UART通信的每一个字节从确保链接文件的对齐到处理安全升级的证书链从实验室的功能验证到设计面向千万台设备的可靠升级策略——每一步都考验着开发者的工程能力。希望这篇指南能为你扫清障碍祝你一次点亮升级顺利。如果在实践中遇到新的问题不妨回头再仔细看看数据手册和参考手册很多时候答案就在那些寄存器描述的细节里。