debug.h
源文件路径:
midware/debug/debug.h所属模块:midware/debug(设备中间件 - 板级调试/产线测试) 代码行数:25
1. 文件职责
本文件是全工程最底层的两个"公共设施"的定义处:一是编译期断言宏 STATIC_ASSERT,二是把 Flash 扇区大小取个短名字 ASSERT_FLASH_SECTOR_SIZE。此外它导出 debug.c 的十六进制 dump 接口 ShowData()。
它看起来像"调试模块的头文件",但实际承担的是全工程配置表尺寸校验基础设施的角色:logic.h、inverter.h、modbus.h、system_config.h、bms.h、meter.h、evc.h、dry_node.h、ct.h、ethernet.h 等十几个头文件都在用 STATIC_ASSERT(ASSERT_FLASH_SECTOR_SIZE % sizeof(...) == 0) 断言"每张配置表都能整块存进一个 Flash 扇区、不会跨扇区截断"。它不参与任何运行时数据流,只在编译期生效。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 |
|---|---|---|
__DEBUG_H | 宏(包含卫士) | 防止重复包含(debug.h:9-10) |
STATIC_ASSERT(condition) | 宏(debug.h:16-17) | 编译期断言。展开为 typedef char static_assertion_##__COUNTER__[(condition) ? 1 : -1]:条件成立时定义一个大小为 1 的类型别名,不成立时大小为 -1,编译器直接报错 |
ASSERT_FLASH_SECTOR_SIZE | 宏(debug.h:19) | 展开为 FLASH_SECTOR_SIZE,即 (4 * 1024)(定义在 hardware/flash/flash.h:27),用于 STATIC_ASSERT 表达式中 |
FLASH_SECTOR_SIZE | 宏(来自 hardware/flash/flash.h:27,值 4 * 1024) | 一个 Flash 扇区的字节数,本文件通过 ASSERT_FLASH_SECTOR_SIZE 间接引用 |
本文件未定义任何结构体、枚举或联合体。
3. 函数清单
本文件不含函数定义,仅含 1 个函数声明:
| 函数名 | 作用域 | 说明 |
|---|---|---|
ShowData | 全局(声明,debug.h:22) | 十六进制 dump 打印,定义在 midware/debug/debug.c:57 |
4. 核心逻辑解析
4.1 STATIC_ASSERT 的展开机制
#define STATIC_ASSERT(condition) \
typedef char static_assertion_##__COUNTER__[(condition) ? 1 : -1]
逐点说明:
- 展开后是一个 typedef,不是变量声明,所以不占用存储、不产生代码,纯编译期。
##__COUNTER__是 token 拼接:__COUNTER__是预处理器内置宏,每被展开一次自增 1,因此同一次编译中每个STATIC_ASSERT都会得到不同的类型名(static_assertion_0、static_assertion_1……),避免同一编译单元内多个断言因重名冲突。这是本宏能在一个头文件里被反复使用(如logic.h里连续用了 4 次)的关键。[(condition) ? 1 : -1]是数组长度:条件为真时长度 1,合法;为假时长度 -1,ARMCC 报 "array size is negative" 或类似错误。- 局限:
__COUNTER__是编译器扩展(ARMCC/GCC/Clang 都支持,纯 ISO C 不支持);另外由于 typedef 的作用域是文件作用域,"同一断言"跨越不同编译单元不会冲突。
4.2 ASSERT_FLASH_SECTOR_SIZE 的用途
本文件把 FLASH_SECTOR_SIZE(4096)重导出为 ASSERT_FLASH_SECTOR_SIZE,是为了让各模块的断言读起来更贴近语义("断言表尺寸能整除 Flash 扇区")。典型用法(全工程共 17 处),例如:
| 使用位置 | 断言内容 |
|---|---|
data/system_config/system_config.h:744 | ASSERT_FLASH_SECTOR_SIZE % sizeof(SYSTEM_BASE_PARA_T) == 0 |
logic/logic.h:397 | ASSERT_FLASH_SECTOR_SIZE % sizeof(LOGIC_CONFIG_TAB_T) == 0 |
midware/inverter/inverter.h:507 | ASSERT_FLASH_SECTOR_SIZE % sizeof(INVERTER_CONFIG_TAB_T) == 0 |
midware/interface/modbus/modbus.h:1479 | ASSERT_FLASH_SECTOR_SIZE % sizeof(MODBUS_CONFIG_INFO_T) == 0 |
midware/bms/bms.h:1103/1114 | 电池配置表与其扩展表 |
midware/interface/dry_node/dry_node.h:201 | sizeof(STDryNodeTab) |
midware/meter/meter.h、midware/meter/ct.h:132 | 电表 / CT 配置表 |
midware/evc/evc.h:89/101、midware/evc/evc_ii.h:115 | 充电桩配置表 |
midware/ethernt/ethernet.h:265 | sizeof(IP_ADDR_TAB_T) |
midware/auxiliary/system_aux.h:52 | sizeof(ENERGY_COUNT_INFO_T) |
因此 debug.h 是全工程修改配置表结构时最先报错的地方:一旦某个结构体大小改成不能整除 4096,编译立刻失败。这是有意设计的"尺寸变更守卫",不是调试功能。
4.3 与 uCOS-II 的关系
无。本文件不涉及任务、信号量、邮箱。ShowData() 是同步阻塞函数,由调用它的任务在自己的上下文里执行。
5. 对外接口
本文件导出
| 名称 | 类型 | 供谁使用 |
|---|---|---|
STATIC_ASSERT(condition) | 宏 | logic/logic.h、midware/inverter/inverter.h、midware/interface/modbus/modbus.h、data/system_config/system_config.h、midware/bms/bms.h、midware/meter/meter.h、midware/meter/ct.h、midware/evc/evc.h、midware/evc/evc_ii.h、midware/interface/dry_node/dry_node.h、midware/ethernt/ethernet.h、midware/auxiliary/system_aux.h 等 |
ASSERT_FLASH_SECTOR_SIZE | 宏 | 同上(与 STATIC_ASSERT 配套使用) |
ShowData(u8 *buf, int len) | 函数声明 | data/system_config/system_config.c、data/resume_data/flash/flash_data_store.c、data/net_event_log/net_event_log.c、midware/interface/modbus/modbus.c、net/server.c |
本文件不导出任何全局变量。
本文件调用的外部函数/变量
不调用任何函数(ShowData 只有声明没有定义)。依赖项仅有:
chip.h(debug.h:13):u8等基础类型flash.h(debug.h:14):FLASH_SECTOR_SIZE宏
6. 依赖关系
依赖
system/sys/chip.h、hardware/flash/flash.h。
被依赖
midware/debug/debug.c、midware/debug/board_test.c、data/system_config/system_config.c、data/system_config/system_config.h、logic/logic.h、midware/auxiliary/system_aux.h、midware/bms/bms.h、midware/ethernt/ethernet.h、midware/evc/evc.h、midware/evc/evc_ii.h、midware/interface/dry_node/dry_node.h、midware/interface/modbus/modbus.h、midware/inverter/inverter.h、midware/meter/ct.h、midware/meter/meter.h 等。
由于 midware/ethernt/ethernet.h:15、midware/inverter/inverter.h、midware/interface/modbus/modbus.h、logic/logic.h 这些"高层头文件"都包含 debug.h,本文件实际上是被全工程间接包含最广的头文件之一,位于头文件依赖图的最底层。
7. 备注与风险点
- 文件被放在
midware/debug/下,但职责远不止调试:STATIC_ASSERT与ASSERT_FLASH_SECTOR_SIZE是配置表尺寸守卫,属于工程基础设施。以"debug"命名会让维护者误以为删掉它只是去掉调试功能,实际会导致大量头文件编译失败。 STATIC_ASSERT依赖__COUNTER__编译器扩展(debug.h:17):非 ARMCC/GCC/Clang 的编译器会不支持。ARMCC 5 对__COUNTER__的支持需确认(若编译器版本不支持,展开会变成static_assertion___COUNTER__的固定名,同一编译单元内多次使用将重名报错)。这是一个隐性的工具链耦合点。STATIC_ASSERT只有"断言"没有"消息":条件失败时编译器输出的是"数组大小为负",不携带任何模块信息,排查时只能靠行号定位。ASSERT_FLASH_SECTOR_SIZE与FLASH_SECTOR_SIZE是两个名字指同一常量,属冗余别名;好处是可读性,代价是搜索时容易漏掉一处。- 包含卫士与
flash.h的耦合:debug.h无条件#include "flash.h"(debug.h:14),使所有包含debug.h的头文件都拖入 Flash 驱动头,增加了头文件耦合链长度(ethernet.h→debug.h→flash.h就是一条实例)。若将来flash.h引入新的重依赖,影响面会被放大。 STATIC_ASSERT是纯编译期机制,运行时无任何开销,这一点无风险。ShowData()的声明放在这里但实现在debug.c:midware/debug/board_test.c:13也包含了debug.h,但board_test.c并未调用ShowData(),属于多余包含。