
这一章我们将切入一个非常关键且具有挑战性的场景OTAOver-the-Air固件更新。OTA 逻辑最怕的是什么是中途断电、Flash 写入失败、校验和不匹配。如果你在真机上测试这些异常可能需要反复烧录、断开电源甚至不小心把片子变“砖”。在 TDD 的世界里我们可以优雅地模拟这些灾难。9.1 OTA 测试的痛点硬件寿命频繁擦写内部 Flash 也是有寿命限制的。场景模拟你很难手动模拟“在写入第 1024 个字节时突然断电”。复杂校验CRC32、SHA256 的验证在 PC 上跑比在 MCU 上快得多。9.2 接口抽象Storage_Interface.h为了让 OTA 逻辑可测我们必须隔离 STM32 的HAL_FLASH_Program。// Storage_Interface.h#ifndef STORAGE_INTERFACE_H#define STORAGE_INTERFACE_H#include stdint.h#include stdbool.htypedef enum { FLASH_OK, FLASH_ERROR, FLASH_BUSY } FlashStatus_t;FlashStatus_t HW_Flash_ErasePage(uint32_t page_addr);FlashStatus_t HW_Flash_Write(uint32_t addr, uint8_t* data, uint32_t len);void HW_System_Reset(void);#endif9.3 实战测试“断点续传”逻辑我们要实现一个 OTA 接收器它按包接收固件记录已写入的偏移量如果写入失败要能重试。编写测试 (test_Ota_Service.c)我们要模拟一个非常极端的情况第一次写入成功第二次写入失败。#include unity.h#include mock_Storage_Interface.h#include Ota_Service.hvoid test_Ota_Should_HandleFlashWriteFailure(void) {uint8_t dummy_data[128] {0xA5};// 1. 模拟第一包数据写入返回成功HW_Flash_Write_ExpectAndReturn(0x08010000, dummy_data, 128, FLASH_OK);bool result Ota_ProcessPacket(0, dummy_data, 128);TEST_ASSERT_TRUE(result);// 2. 模拟第二包数据写入硬件突然报错比如电压不稳或页损坏HW_Flash_Write_ExpectAndReturn(0x08010080, dummy_data, 128, FLASH_ERROR);result Ota_ProcessPacket(128, dummy_data, 128);// 验证逻辑层应该识别出失败并返回 false以便触发重传机制TEST_ASSERT_FALSE(result);}9.4 进阶技巧模拟“脏数据”与校验失败在 OTA 中校验和Checksum是最后一道防线。void test_Ota_Should_RejectFirmware_WhenChecksumMismatch(void) {// 模拟 Flash 读取出的数据// 我们不需要真的读 Flash直接 Mock 掉读取函数返回“坏数据”HW_Flash_Read_StubWithCallback(my_Fake_Flash_Read_Bad_Data);// 执行校验逻辑bool is_valid Ota_VerifyChecksum();// 验证校验不通过且绝不调用系统重启去运行坏固件TEST_ASSERT_FALSE(is_valid);// 确保没有误触发系统重启这也是一种验证HW_System_Reset_Expect(); // 如果你预期它报错后重启到 Bootloader}9.5 本章核心防御式编程状态机保护OTA 过程中如果收到无关的串口命令状态机是否会崩溃原子操作模拟模拟擦除了一半突然断电Bootloader 能否识别出固件不完整边界检查Mock 掉 Flash 大小接口验证如果固件包超过 Flash 容量代码是否会越界写入。本章小结这一章证明了 TDD 不仅能测“好用”的情况更能测“坏掉”的情况。对于 OTA 这种高风险模块这种“离线异常注入”是保证产品不批量变砖的唯一手段。