STM32L4串口Ymodem OTA升级:基于RT-Thread的可靠固件更新方案
发布时间:2026/9/5 20:49:24 作者:尧图编辑部 阅读量:1,286

简介本资源是一套基于RT-Thread操作系统的STM32L4系列单片机串口Ymodem OTA固件升级完整工程面向嵌入式开发工程师及RTOS进阶学习者解决低功耗物联网设备远程安全升级的核心需求。压缩包含2000个文件主体为2217个C源码与1887个头文件实现串口驱动、Ymodem协议栈、Flash写入逻辑及RT-Thread多任务调度辅以469份Markdown文档说明、64个Keil/IAR工程配置文件uvprojx/ewp及大量编译中间文件o、d、axf等整体达91.98MB。已有664人学习下载适合需落地OTA功能的项目开发者——不仅提供可直接编译运行的全栈代码还包含协议分块校验、固件校验回滚、中断DMA高效收发等关键设计细节以及STM32L496专属HAL驱动如stm32l4xx_hal_i2c.c、stm32l4xx_hal_tim.c与文件系统适配层ff.c、ssl_tls.c助力快速掌握嵌入式安全升级工程实践。1. 项目缘起为什么要在STM32L4上折腾Ymodem OTA最近在做一个基于STM32L496的物联网终端设备项目到了后期一个现实问题摆在了面前设备部署到现场后如何更新程序难道每次都要工程师带着J-Link和笔记本电脑跑到现场拆开外壳接上SWD线去烧录吗这显然不现实成本高、效率低而且对于部署在偏远或难以触及位置的设备来说几乎是不可能的任务。所以空中下载技术Over-The-Air OTA成了必选项。它允许我们通过无线网络如4G Cat.1、NB-IoT、Wi-Fi甚至是有线通道如串口远程更新设备固件是产品实现可持续迭代和快速修复线上问题的关键能力。在资源相对紧张的微控制器MCU领域OTA的实现方案需要格外考究既要保证可靠性又要兼顾有限的Flash和RAM资源。在众多OTA方案中我最终选择了基于串口的Ymodem协议并在RT-Thread物联网操作系统上实现。这个组合听起来有点“复古”——串口、Ymodem都是有些年头的技术了但在嵌入式领域尤其是工业控制、智能仪表等对可靠性要求极高的场景它恰恰展现出了独特的优势协议简单、可靠、易于调试且不依赖复杂的网络协议栈。对于STM32L4系列这类拥有丰富串口资源和适中Flash容量STM32L496RG有1MB Flash的MCU来说这是一个非常务实且高效的选择。本文将详细拆解如何在RT-Thread工程中为STM32L496兼容STM32L4系列实现一套完整、健壮的串口Ymodem OTA升级方案。我会从原理选型、环境搭建、代码实现、分区设计、Bootloader编写到最后的测试验证与踩坑心得进行一站式讲解。无论你是正在寻找可靠OTA方案的工程师还是对RT-Thread和STM32L4开发感兴趣的开发者相信都能从中获得可直接复用的干货。2. 技术选型深析为何是YmodemRT-Thread在动手之前我们必须理清为什么是这几个技术点的组合。这决定了整个方案的基石是否稳固。2.1 核心协议Ymodem的简单与可靠OTA的本质是一次文件传输。我们需要一个在串口这种“不可靠”的流式媒介上可靠地传输一个可能几百KB的二进制文件.bin的协议。常见的候选者有Xmodem、Ymodem、Zmodem以及自定义协议。Xmodem老祖宗128字节数据块校验和简单效率低无文件信息。YmodemXmodem的增强版是本次的主角。它支持1024字节的数据块传输效率更高最重要的是它在会话开始时会先传输文件名和文件大小这为接收方我们的设备预先判断文件是否合法、Flash空间是否足够提供了关键信息。这是选择Ymodem而非Xmodem的核心原因。Zmodem更现代支持断点续传、压缩等但协议复杂在MCU端实现开销较大。自定义协议灵活但设计一个健壮、容错的协议需要大量测试容易埋坑。Ymodem在简单性和功能性之间取得了很好的平衡。其工作流程可以概括为启动接收方设备发送字符C(0x43) 发起通信请求使用CRC-16校验。文件头帧发送方PC工具发送第一个数据块包含文件名和文件大小等信息。数据帧发送方持续发送1024字节的数据块每个块有序列号、数据和CRC校验。接收方校验通过后回复ACK(0x06)失败则回复NAK(0x15) 请求重传。结束帧文件传输完毕后发送方发送一个EOT(0x04) 标识。接收方可能要求再次发送EOT确认最终以ACK结束整个会话。这种“一问一答”的握手机制虽然比不上TCP的滑动窗口高效但在串口通信中极其可靠任何一位错误都能通过CRC校验和重传机制发现并纠正。2.2 操作系统RT-Thread的生态与便利在裸机上实现Ymodem OTA当然可以但会非常繁琐你需要自己管理串口中断、超时、状态机、Flash擦写等。而RT-Thread作为一个国产的、开源的中小型物联网操作系统提供了绝佳的支撑设备框架通过rt_device框架我们可以用统一、简单的API (rt_device_read/write) 操作串口无需深挖寄存器。文件系统虽然本次OTA直接写Flash但RT-Thread的FAL (Flash Abstraction Layer) 组件是管理Flash分区的神器。它抽象了不同Flash的操作让我们可以用“分区”的概念来管理应用程序区、下载区等代码可移植性极强。丰富的软件包RT-Thread的软件包中心有现成的ymodem软件包。它已经实现了Ymodem协议的状态机解析我们只需要实现几个回调函数如接收数据、发送响应即可大大降低了开发难度。多线程环境我们可以创建一个独立的线程来运行OTA任务它阻塞在串口读取上不会影响主业务逻辑线程的运行。RT-Thread的线程调度和同步机制信号量、邮箱可以很好地用于OTA状态通知。选择RT-Thread意味着我们站在了巨人的肩膀上避免了重复造轮子能将精力集中在OTA的业务逻辑和稳定性优化上。2.3 硬件平台STM32L4系列的恰到好处STM32L496属于STM32L4系列主打低功耗和性能平衡。对于OTA来说它的几个特性至关重要足够的Flash以L496RG为例1MB的Flash空间允许我们划分出Bootloader区、APP A区、APP B区用于备份或新固件、参数存储区等实现双备份A/B分区的OTA策略确保升级失败也能回滚。内部Flash支持擦写STM32L4的内部Flash支持以扇区Sector为单位进行擦除和编程这为我们实现Bootloader和固件存储提供了硬件基础。丰富的串口通常有多个USART/LPUART我们可以指定一个专用串口用于OTA升级与调试打印串口分离互不干扰。CRC硬件单元STM32L4内置CRC计算单元可以加速Ymodem数据块的CRC-16校验提高传输效率和降低CPU开销。这个组合——Ymodem提供可靠传输RT-Thread提供软件框架和生态STM32L4提供硬件基础——构成了一个坚实、可落地的嵌入式OTA方案三角。3. 工程准备与系统设计在写第一行代码前我们需要搭建好开发环境并完成最关键的系统分区设计。3.1 开发环境搭建硬件一块STM32L496开发板如Nucleo-L496ZGUSB转串口工具如果板载ST-Link的虚拟串口不好用建议外接一个稳定的CH340/CP2102模块。软件RT-Thread Studio或Keil MDK/ IAR。我推荐使用RT-Thread Studio它对RT-Thread工程的管理、软件包添加和配置更为直观。串口调试助手选择一款支持Ymodem协议发送文件的。SecureCRT、Xshell、MobaXterm或者开源的Tera Term、Putty需配合额外脚本都行。SecureCRT和MobaXterm的Ymodem功能比较稳定易用。STM32CubeProgrammer或J-Flash用于最初烧写Bootloader以及紧急情况下的恢复。3.2 Flash分区设计OTA的基石这是整个项目的核心设计直接关系到系统的可靠性和升级策略。我们采用经典的A/B双备份分区设计确保升级失败时能自动回滚到旧版本。假设我们使用STM32L496RG1MB Flash 起始地址0x0800 0000。一个典型的分区方案如下分区名称起始地址大小内容说明bootloader0x0800 000032KBBootloader程序负责初始化、检查并跳转到有效的APP。app_a0x0800 8000448KB应用程序A主运行分区。app_b0x0807 8000448KB应用程序B备用/下载分区。OTA时新固件暂存于此。fal_params0x080F F0004KB参数区存储当前运行分区标志、固件CRC、版本号等。设计理由与计算过程Bootloader大小32KB对于实现串口驱动、Ymodem解析、Flash擦写、跳转逻辑和基本的日志输出绰绰有余。为后续功能预留了空间。APP分区大小448KB。1MB Flash减去Bootloader的32KB和参数区的4KB剩余988KB。平分给A和B两个分区每个494KB。但为了对齐Flash扇区STM32L4的扇区大小不一例如第5扇区是128KB我们取448KB这个对齐值确保每个分区从一个扇区边界开始方便擦除管理。0x0800 8000(32KB) 和0x0807 8000(32KB 448KB 480KB 0x78000) 都是扇区边界。参数区4KB使用最后一个扇区或页独立存储关键参数防止在擦写APP分区时被意外破坏。这个分区表信息我们需要在Bootloader和APP的工程中通过FAL组件进行统一定义。3.3 在RT-Thread Studio中配置FAL在APP工程中注意Bootloader是一个独立的裸机或RT-Thread Nano工程此处先讲APP工程通过RT-Thread Settings打开软件包配置找到FAL: Flash Abstraction Layer并启用它。在board/ports目录下或根据Studio提示的位置创建或修改fal_cfg.h文件。在这个文件中我们需要做两件事定义Flash设备告诉FAL我们芯片的Flash大小和起始地址。/* fal_cfg.h */ #define FAL_PART_HAS_TABLE_CFG /* Flash device Configuration */ extern const struct fal_flash_dev stm32l4_onchip_flash; /* flash device table */ #define FAL_FLASH_DEV_TABLE \ { \ stm32l4_onchip_flash, \ }定义分区表将我们设计的分区方案用代码描述出来。/* Partition Configuration */ #ifdef FAL_PART_HAS_TABLE_CFG /* partition table */ #define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WORD, bootloader, onchip_flash, 0, 32 * 1024, 0}, \ {FAL_PART_MAGIC_WORD, app_a, onchip_flash, 32 * 1024, 448 * 1024, 0}, \ {FAL_PART_MAGIC_WORD, app_b, onchip_flash, (32448) * 1024, 448 * 1024, 0}, \ {FAL_PART_MAGIC_WORD, params, onchip_flash, (32448448) * 1024, 4 * 1024, 0}, \ } #endif /* FAL_PART_HAS_TABLE_CFG */我们还需要实现stm32l4_onchip_flash这个设备的具体操作函数read,write,erase通常可以在RT-Thread的BSP板级支持包中找到参考实现例如drivers/drv_flash_l4.c。核心是调用HAL库的HAL_FLASH_Program和HAL_FLASHEx_Erase函数。注意Bootloader工程也需要一个类似的、但可能更简化的分区定义至少它需要知道app_a,app_b和params的地址以便进行跳转判断。Bootloader中可以不使用FAL直接操作地址但使用FAL可以保持代码风格一致便于维护。4. Bootloader的实现系统的守门员Bootloader是设备上电后运行的第一段代码其职责是纯净且关键的初始化最基本的硬件时钟、串口用于调试。检查参数区判断哪个APP分区A或B是有效的、可启动的。如果有效则跳转到该APP执行。可选进入一个“升级模式”例如检测某个按键是否按下或者在一段时间内收到特定的串口指令则停留在Bootloader中等待通过Ymodem接收新固件。4.1 跳转逻辑与APP有效性校验跳转到APP前必须进行有效性校验否则可能跳转到一堆随机数据中导致硬件错误。常见的校验方法检查栈顶指针APP向量表的第一个字是初始栈顶指针MSP这个值应该位于RAM的有效地址范围内例如0x2000 0000 ~ 0x2002 0000。检查复位向量向量表的第二个字是复位中断向量的入口地址这个地址应该落在Flash的APP分区范围内。CRC校验计算整个APP分区固件的CRC值与存储在参数区的预期CRC值对比。这是最严格但耗时较长的校验。标志位APP在启动后可以在固定地址如参数区写入一个“运行成功”的标志。Bootloader检查该标志如果标志有效则认为上次启动成功该分区是稳定的。一个健壮的策略是组合使用检查栈顶指针和复位向量的有效性作为快速检查通过后再进行CRC校验。在Bootloader中代码大致如下// bootloader.c typedef void (*pFunction)(void); int jump_to_app(uint32_t app_addr) { uint32_t stack_top; pFunction app_entry; /* 1. 检查地址是否对齐到4字节Cortex-M要求 */ if (app_addr 0x3) { return -1; } /* 2. 读取APP的向量表 */ stack_top *(volatile uint32_t*)app_addr; // MSP app_entry (pFunction)*(volatile uint32_t*)(app_addr 4); // Reset_Handler /* 3. 快速检查MSP是否在合理RAM范围 */ if ((stack_top 0x20000000) || (stack_top (0x20000000 128*1024))) { // 假设128KB RAM return -2; } /* 4. 检查复位向量是否在Flash的APP分区范围内 */ if ((app_entry (FLASH_BASE APP_A_START)) || (app_entry (FLASH_BASE APP_B_END))) { return -3; } /* 5. 可选CRC校验此处省略具体计算过程 */ // if (calculate_crc(app_addr, app_size) ! stored_crc) return -4; /* 6. 关闭所有中断设置主栈指针跳转 */ __disable_irq(); // 设置向量表偏移如果APP使用了中断且VTOR已重定位 SCB-VTOR app_addr; // 设置主栈指针 __set_MSP(stack_top); // 跳转到APP的复位处理函数 app_entry(); // 正常情况下不会执行到这里 while(1); }4.2 集成Ymodem接收功能Bootloader需要集成Ymodem协议解析来接收新固件。我们可以移植一个轻量级的Ymodem解析库或者使用RT-Thread Nano并启用其软件包如果Bootloader空间充裕。更常见的做法是写一个简化的、专用于Bootloader的Ymodem状态机。其核心流程如下上电后先检查是否进入升级模式如按键或串口命令。如果进入则通过串口发送字符C循环等待PC端响应。进入接收循环解析文件头包获取文件名和文件大小。根据文件大小检查app_b分区空间是否足够。擦除app_b分区。循环接收数据包校验CRC正确则写入app_b分区的对应地址并回复ACK。收到EOT后发送ACK确认。传输完成后将app_b分区标记为“待验证”或“新版本”并更新参数区的标志位。重启系统。下次启动时Bootloader会发现app_b分区有有效固件并尝试跳转运行或根据策略决定是否立即切换。关键点在Bootloader中写Flash时一定要做好扇区管理。Ymodem是顺序传输但Flash写入前必须先擦除整个扇区。因此通常的做法是在开始接收前擦除整个目标分区app_b。在接收每个数据包时直接编程写入到对应偏移地址。STM32L4的Flash支持按字32位、半字16位或字节8位编程但地址必须对齐且只能从1写为0。在已擦除值为0xFF的区域上编程是安全的。5. 应用程序APP的设计与配合APP并非被动等待升级它需要与Bootloader协同工作共同维护系统的升级状态。5.1 工程配置的关键调整为了让APP能被Bootloader正确加载必须在编译链接阶段进行关键配置修改链接脚本APP的起始地址不再是默认的0x0800 0000而是我们分区中的app_a或app_b的起始地址例如0x0800 8000。在Keil中这是在Options for Target - Target - IROM1中修改Start地址和Size。在RT-Thread Studio或GCC链接脚本.ld文件中需要修改FLASH区域的起始地址和长度。设置中断向量表偏移因为APP的向量表不在0地址所以需要在APP启动的最早期在main函数之前通常在system_stm32l4xx.c的SystemInit函数中或RT-Thread的启动文件里通过设置SCB-VTOR寄存器将中断向量表重定位到APP的起始地址。RT-Thread的BSP通常已经处理了这部分但需要确认RT_APP_PART_ADDR宏定义是否正确。// 在APP初始化代码中如RT-Thread的启动阶段 SCB-VTOR FLASH_BASE | 0x8000; // 对于app_a偏移0x8000生成正确的固件文件编译器生成的.axf或.elf文件包含调试信息不能直接用于OTA。我们需要生成纯二进制.bin文件。在Keil中通过fromelf --bin --output配置在RT-Thread Studio中编译后会默认生成.bin文件。这个.bin文件就是我们要通过Ymodem发送的内容。5.2 实现APP内的OTA触发与管理APP需要提供一种方式让用户或服务器可以触发OTA流程。这通常通过一个命令如串口命令ota_start或者网络请求来实现。一旦触发APP需要验证新固件如果已存在检查app_b分区是否有已下载但未运行的固件并进行CRC校验。标记分区在参数区写入标志指示下一次启动时应尝试从app_b分区启动。安全重启关闭所有外设保存必要状态然后执行软重启NVIC_SystemReset()。一个重要的设计是APP不负责接收新固件。接收固件是Bootloader在“升级模式”下的工作。APP只负责“发号施令”告诉系统“下次请用B分区启动”。这样做的好处是降低复杂性APP运行时文件系统、网络栈、业务逻辑都在运行此时进行大块Flash擦写和长时间串口阻塞接收风险较高容易导致看门狗复位或任务阻塞。提高可靠性Bootloader环境纯净任务单一更适合做可靠的固件写入操作。实现回滚如果app_b启动失败比如CRC校验不过或者运行后崩溃Bootloader在下次启动时可以根据策略例如检查“运行成功”标志自动回滚到app_a。因此常见的交互流程是用户通过APP的接口串口命令发起升级请求。APP在参数区设置标志next_boot_partition APP_B和update_pending true。APP重启。Bootloader启动检查到update_pending为真且next_boot_partition指向app_b。Bootloader尝试校验并跳转到app_b。如果app_b启动成功它需要将next_boot_partition改为APP_B并将update_pending清除同时将app_a标记为旧版本可选。如果app_b启动失败比如根本跳转不过去看门狗会导致复位。Bootloader再次启动时发现update_pending仍为真但上次启动失败则执行回滚清除update_pending强制从app_a启动。6. Ymodem传输的实战细节与坑点理论设计完毕实际传输过程中会遇到各种问题。这里分享几个关键的实战细节。6.1 串口配置与流控Ymodem对串口通信的稳定性要求很高。推荐配置波特率921600 或 115200。更高的波特率缩短传输时间降低中途出错概率但要求硬件和线材质量好。115200是最稳妥通用的选择。数据位8停止位1校验位None (Ymodem自带CRC校验串口校验可关闭)流控制强烈建议使用硬件流控RTS/CTS。如果设备端处理速度跟不上比如正在擦写Flash可以通过CTS信号通知PC端暂停发送避免数据丢失。STM32L4的USART支持硬件流控务必在初始化时启用huart.Init.HwFlowCtl UART_HWCONTROL_RTS_CTS;。如果硬件连线不便至少要用软件流控XON/XOFF但可靠性不如硬件。6.2 超时与重传机制Ymodem协议本身有超时和重传但需要在设备端正确实现。接收超时在等待一个数据包时需要设置一个超时定时器例如3秒。如果超时仍未收到完整包应发送NAK或C重新发起请求。不要无限等待否则一旦数据丢失设备就会“卡死”。整包校验收到一包数据后先校验序列号是否正确防止错包再校验CRC。只有两者都正确才回复ACK否则回复NAK。连续NAK处理如果连续收到多次如10次同一包的NAK说明信道质量极差或存在根本性问题如波特率不匹配可以考虑终止会话并发送CAN(0x18) 字符取消传输。6.3 Flash编程的阻塞与看门狗在Bootloader中擦写Flash是耗时操作。以STM32L4擦除一个128KB扇区为例可能需要上百毫秒。在此期间CPU被阻塞无法响应串口中断。问题如果PC端在设备擦写Flash时发送了数据这些数据会丢失导致后续通信错乱。解决方案1硬件流控如前所述启用硬件流控。在进入擦写函数前拉高RTS请求发送表示本机未就绪擦写完成后再拉低RTS。PC端的串口工具在检测到CTS为高时会自动暂停发送。解决方案2分块处理不要一次性擦除整个分区。可以设计为每接收完一个Ymodem数据包1KB再擦写对应的Flash小块如1KB或4KB。虽然总时间可能变长但阻塞时间碎片化降低了数据丢失的风险。不过STM32L4的Flash擦除最小单位是扇区此方案实现复杂。看门狗务必在Bootloader中启用独立看门狗IWDG并设置合理的超时时间如2秒。在擦写Flash的循环中及时“喂狗”。防止因Flash操作异常或意外死循环导致设备“变砖”。6.4 文件大小与分区边界处理Ymodem文件头包中包含了文件大小。Bootloader在收到文件头后必须立即检查文件大小是否超过目标分区容量如果超过应立即发送CAN取消传输并通过串口打印错误信息。文件大小是否为Flash编程单位的整数倍虽然不强制但如果固件大小不是4字节字的倍数最后可能需要特殊处理填充确保写入操作对齐。7. 测试流程与故障排查一套完整的OTA系统必须经过严格的测试。7.1 分阶段测试单元测试Bootloader跳转测试分别编译两个不同的APP例如一个闪灯一个蜂鸣烧录到app_a和app_b。修改参数区标志测试Bootloader能否正确跳转到指定分区。Ymodem协议解析测试在Bootloader中编写一个测试模式模拟接收一个已知的小文件如一个文本文件并将接收到的数据通过串口打印出来对比是否一致。集成测试完整升级流程测试正常路径设备运行app_aV1.0。通过串口命令触发APP进入升级准备设置标志重启。设备进入Bootloader等待升级。使用串口工具通过Ymodem发送app_b的V2.0固件.bin文件。传输完成后设备自动重启应成功运行app_bV2.0。传输中断测试在Ymodem传输过程中手动拔掉串口线或关闭串口工具。设备应在超时后回到Bootloader的等待状态并且app_b分区应保持无效状态因为未完整接收。再次上电应能正常从app_a启动。固件校验失败测试手动篡改.bin文件的几个字节使其CRC校验失败。Bootloader应能检测到并拒绝该固件报告错误。压力与异常测试反复升级连续进行多次升级-回滚-再升级操作检查参数区是否被正确擦写有无累积错误。电源跌落测试在Flash擦写或编程过程中突然断电。再次上电后Bootloader应能识别到分区的不一致状态例如参数区标志是“升级中”但app_bCRC校验失败并执行回滚到app_a。这是检验系统鲁棒性的关键。7.2 常见问题与排查手段问题串口工具发送Ymodem文件后设备毫无反应。排查检查接线TX、RX、GND是否接对波特率是否一致检查Bootloader串口初始化代码确认引脚配置正确。在Bootloader最开始加一句打印如printf(Bootloader Start\r\n);看能否收到。确保Bootloader已正常运行。检查Bootloader是否在持续发送C字符。可以用串口工具的“接收”框查看或者用逻辑分析仪抓取TX引脚波形。确认串口工具选择的Ymodem协议类型是否正确通常是Ymodem 而不是Ymodem-g。问题传输到一半失败提示超时或CRC错误。排查降低波特率先从115200开始测试排除因波特率过高导致的时序问题。启用硬件流控这是解决此类问题最有效的方法。检查Flash操作耗时在擦写Flash的函数前后打时间戳计算耗时。如果单次阻塞超过串口接收缓冲区的承受时间例如115200波特率下1字节约87us一个1KB包约87ms就必须用流控或分块写入。检查看门狗是否因为Flash操作耗时过长未喂狗导致复位适当延长看门狗超时时间或在Flash操作循环内频繁喂狗。问题升级成功后新APP无法运行或运行异常。排查确认链接地址这是最常见的原因务必反复检查APP工程的IROM1起始地址是否与Bootloader中定义的分区地址完全一致。用fromelf --text -c your.axf或arm-none-eabi-objdump -h your.elf命令查看生成的elf文件的段地址。检查VTOR设置在新APP的启动代码中是否正确设置了SCB-VTOR可以在APP开始处打印这个寄存器的值进行验证。检查中断向量如果APP使用了中断但VTOR未设置或设置错误中断发生时CPU会跑到错误的地址去执行。检查跳转前的环境Bootloader在跳转前是否关闭了所有开启的外设时钟、中断最好在跳转前做一个全面的外设反初始化DeInit。问题回滚功能不生效。排查参数区读写错误检查参数区的擦写函数。STM32L4的Flash编程需要先解锁操作完成后最好再锁上。确保读写操作正确。标志位逻辑仔细梳理Bootloader中判断启动分区的逻辑。是否考虑了所有可能的状态如首次启动、升级成功、升级失败逻辑是否有歧义或漏洞可以打印出参数区的所有标志值进行调试。APP“运行成功”标志如果使用该机制APP需要在完全初始化成功后才写入标志。如果APP在初始化早期就崩溃这个标志将不会被写入Bootloader下次就会认为该分区启动失败。实现一个稳定的OTA系统三分靠设计七分靠测试和调试。耐心地模拟各种异常情况并观察系统的行为是确保方案可靠的不二法门。通过以上步骤你应该能够为STM32L496打造一个基于串口Ymodem和RT-Thread的、工业级可靠的OTA升级方案。这套方案的核心思想——清晰的分区管理、纯净的Bootloader职责、可靠的传输协议、完备的错误处理——可以扩展到其他MCU平台和不同的传输媒介如GPRS、LoRa上具有很高的参考价值。本文还有配套的精品资源点击获取