第五章:如何对 HAL 库本身进行单元测试?

这一章我们将深入嵌入式开发最"底层"的阵地。很多开发者会问:"逻辑层可以隔离,但我直接配置 STM32 寄存器或调用 HAL 库的代码,怎么测?"

这一章,我们要处理那些无法回避的底层调用,并引入 TDD 的进阶手段:Fake(伪函数)

5.1 为什么 Mock 有时不够用?

对于 HAL_GPIO_WritePin 这种简单的一对一调用,Expect 很好用。但如果你在写一个 I2C 扫描逻辑,代码里涉及大量的循环和连续调用,写几十个 Expect 会让测试脚本极其冗长且难以维护。

此时,我们需要 Fake(伪造实现):我们写一个功能简单的函数,替换掉真正的 HAL 函数,并让它记录下所有的动作。

5.2 实战:测试一个 I2C 设备探测器

需求: 扫描 I2C 总线上地址从 1127 的设备,并返回第一个响应的地址。

底层接口 (stm32g0xx_hal.h)HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout);

5.3 编写测试:使用 Stub(存根/钩子)

Ceedling 的 CMock 支持 StubWithCallback。我们可以定义一个自定义函数,让 CMock 在被调用时运行我们的代码。

#include "unity.h"

#include "mock_stm32g0xx_hal_i2c.h" // 模拟 HAL 库

#include "I2C_Scanner.h"

// 这是一个伪造的 I2C 响应函数

// 我们模拟只有地址 0x50 的设备有响应

HAL_StatusTypeDef my_I2C_Stub(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout, int num_calls) {

if (DevAddress == (0x50 << 1)) {

return HAL_OK;

}

return HAL_ERROR;

}

void test_Scanner_Should_Return0x50_WhenDeviceFound(void) {

// 告诉 CMock:当 HAL_I2C_IsDeviceReady 被调用时,别管 Expect 了,去运行 my_I2C_Stub

HAL_I2C_IsDeviceReady_StubWithCallback(my_I2C_Stub);

uint8_t found_addr = I2C_Scanner_ScanFirst();

TEST_ASSERT_EQUAL_HEX8(0x50, found_addr);

}

5.4 进阶技巧:针对 STM32 寄存器的"影子内存"

如果你在写非常底层的代码(如手写寄存器驱动),可以利用一种叫 Shadow Register 的技术:

  1. 在测试环境中,定义一组全局变量(如 uint32_t V_GPIOA_ODR)。

  2. 在头文件中通过宏定义将 GPIOA->ODR 指向这个变量。

  3. 测试方法 :调用你的驱动函数,然后断言 TEST_ASSERT_EQUAL_HEX32(0x01, V_GPIOA_ODR)

这让你可以验证驱动程序是否真的改写了对应的寄存器位。

5.5 本章核心心法:什么时候该停止测试?

请注意:

  • 不要去测试 ST 官方的 HAL 库 :我们默认 HAL_GPIO_WritePin 是工作的。

  • 测试的是"调用行为":我们要测的是"当传感器数据溢出时,驱动是否正确调用了复位寄存器"。

  • 避免过度 Mock:如果你的测试代码比业务代码长 5 倍,说明你的函数拆分得还不够细。

本章小结

我们掌握了 StubCallback,这让我们能够处理复杂的循环调用和底层库交互。至此,你已经完成了从业务逻辑到硬件驱动的全路径 TDD 覆盖。

相关推荐
无损检测小白白4 小时前
【嵌入式面试题一】
c语言·单片机
蒸蒸yyyyzwd4 小时前
cpp选手秋招学习笔记day24-cs144项目总结
运维·服务器·网络
Messy create4 小时前
【BMS-Pack检测-短路检测】
单片机·嵌入式硬件·能源
yutian06064 小时前
TI 280049 GPIO 相关笔记
嵌入式硬件·c2000
数据知道5 小时前
静态分析入门——PE 结构、字符串、导入表快速定性
网络·安全·web安全·网络安全
CCYe、5 小时前
新模型上线、旧模型下线:企业AI网关如何管住模型版本
java·网络·数据库·人工智能
葡萄城技术团队5 小时前
从设备协议数据到完整OEE:机加工车间设备效率分析的技术实现路径
网络
星一工作室5 小时前
【STM32模块教程】-TT马达(直流电机)
单片机·嵌入式硬件
码农小麦6 小时前
LangChain 1.3.18 + DeepSeek-v4-flash 工具调用踩坑实录
网络·数据库·langchain
吴声子夜歌6 小时前
Guava——事件总线
java·网络·guava