本文描述 power_mgmt 中与 PMBus、CANBus 相关的软件结构:协议注册、PsuSlot / OnePower 与 Monitor 的职责,以及两套协议在实现上的事务布局与扩展方式。
1. 总体架构
1.1 三类构件
| 构件 | 作用 |
|---|---|
| 协议实现模块 | 继承或封装具体命令,实现 get_<属性名>、set_<操作> 等,供槽位对象按属性名反射调用。 |
| 协议注册(init) | 将 physical_interface 映射到 { 对外协议名字符串, require(协议模块), monitor 路径或缺省 };亦可配置可选的 protocol[制造商][型号] 同名三元素表。 |
| Monitor | 在通用 PsuSlot 之上封装周期巡检、DBus 订阅、健康位解析、黑匣子等上层逻辑;不同协议可选用不同 read_interval 与初始化流程。 |
电源槽位对象通过 get_dynamic_data(prop) 调用 self.protocol['get_' .. prop](self.protocol);新增对外属性时,协议类需实现同名 get_<prop>,并与 DAL / 设备树属性名一致。
1.2 核心入口文件
- 协议注册:
include/device_tree/adapters/power_mgmt/protocol/init.lua - 通用槽位逻辑:
include/device_tree/adapters/PsuSlot.lua(get_protocol、fetch_power_supply_info、get_dynamic_data、get_black_box_data等) - 通用 OnePower:
include/device_tree/adapters/OnePower.lua - 单板覆写:
include/device_tree/adapters/<与 CSR 同名目录>/PsuSlot.lua(及可选OnePower.lua;可能替换 Monitor 加载方式或增加去抖)
1.3 协议解析规则
include/device_tree/adapters/power_mgmt/protocol/init.lua 导出 function(physical_interface, manufacturer, model)。解析顺序与源码一致:
- 当
manufacturer、model均非空,且protocol[manufacturer]存在、protocol[manufacturer][model]存在时,使用该嵌套表项(三元素:protocol_name、require得到的模块、monitor模块路径字符串)。 - 否则使用
protocol[physical_interface]。若该键不存在,table.unpack会得到nil,随后req_protocol.new会失败,因此PhysicalInterface必须在protocol表中注册。
PsuSlot:fetch_power_supply_info(PsuSlot.lua)先执行 get_protocol(physical_interface);在 monitor:fetch_power_supply_info 刷新出 manufacturer / model 后,若二者齐全则再次 get_protocol(physical_interface, manufacturer, model),以便在已配置嵌套表时切换实现。
1.4 协议标准与物理层
1.4.1 PMBus
规范关系
- PMBus(Power Management Bus)面向电源与配电器件的 管理、配置与遥测,电气与帧规则基于 SMBus(常用 SMBus 2.0 子集),并定义电源域 Command、数据格式、典型行为。
- SMBus 建立在 I²C(Inter-Integrated Circuit)电气约定之上:SCL / SDA 双线、多为主从结构,按 从机地址与读写方向 完成寄存器风格访问。
术语
| 术语 | 含义 |
|---|---|
| Command Code | 事务中的 命令字节,对应实现中 pmbus.cmd.*,表达读写字的语义(如输入电压、厂商标识)。 |
| PAGE | 通过 PAGE 寄存器 切换逻辑页后再读 Command,多见于多路输出电源。 |
| Byte / Word / Block | SMBus 读写字节 / 字 / 块(块首字节常为长度)。实现中对应 chip_byteread、chip_wordread、chip_blkread、get_dynamic_block。 |
| PEC(Packet Error Code) | SMBus 包错误码(CRC-8),覆盖地址与数据域。实现使用 mc.crc8,嵌入 chip_read / chip_write。 |
| Linear11 / Linear16 | PMBus 线性数据格式(尾数与指数)。实现中 get_linear_11、get_linear_16。 |
| Direct | 依赖 Coefficients(m、b、R 等) 换算工程量。实现中 get_direct 与 twos_complement_to_original。 |
| STATUS_* | 状态类寄存器,如 INPUT、TEMPERATURE、VOUT、IOUT、CML,用于告警与健康位。 |
1.4.2 CANBus
规范关系
- ISO 11898 规定 CANBus 物理与数据链路特性:介质上 广播 帧,靠 仲裁域(Identifier) 区分优先级与过滤;物理层常用 CAN_H / CAN_L 差分对,以差分电压表示显性/隐性位;MAC 子层为 帧格式、15 位 CRC、ACK;规范帧 payload 至多 8 字节(CAN 2.0 A/B)。
- 标识符长度:标准帧 11 bit、扩展帧 29 bit(实现中扩展帧常量见
CAN_EXTENDED_FRAME,驱动侧常称 EFF)。 - 应用层:在 CANBus 帧数据域(≤8 B) 之上定义 私有命令布局(命令字、节点地址、
protocol、sigid_and_error、Sigid 等),实现见canbus.lua中can_data_info与各CMD_*;字段语义以 项目规格书 为准。
术语
| 术语 | 含义 |
|---|---|
| Frame / Data Field | MAC 帧及其 数据段(0–8 B)。实现中常以 8 B 为步长(FRAME_DATA_LEN、CANBUS_FRAME_DATA_SIZE)。 |
| Arbitration ID | 仲裁与接收过滤依据;扩展帧下为 29 位。语义字段通过 bitstring 写入 cmd、addr、protocol、frame_type、sigid_and_error 等;与 Identifier 比特级映射由 驱动 / BMC 插件 完成。 |
| Bit rate | 同一条 CAN 链路上各节点须用相同比特率(常见 250 kbps / 500 kbps)。波特率在 内核 CAN 驱动 / 设备配置侧设定,不在 power_mgmt 的 Lua 中修改。Lua 仅将应用字段 can_data_info:pack 成缓冲区,经 PsuChip:WriteRead 下发。 |
| Sigid | 信号编号;与 sigid_and_error 低 12 位 对应,用于 CMD_QUERY(0x82) 等定点读。 |
| 批量命令(如 0x40 / 0x50) | 周期 多帧 payload 拼接;解析顺序由 get_batch_query_data、canbus_get_property_info 与规格书一致锁定。 |
1.4.3 PMBus 与 CANBus 实现对照
| 维度 | PMBus 实现路径 | CANBus 实现路径 |
|---|---|---|
| 介质 | I²C / SMBus(SCL/SDA) | 差分对 CAN_H / CAN_L(ISO 11898) |
| 差错 | PEC(CRC-8) 与逻辑内校验 | 控制器 CRC-15、ACK、错误帧;应用侧 sigid_and_error |
| 寻址 | 7-bit 从机地址 + Command | 节点地址、protocol、命令字 等与仲裁 / 数据布局协同 |
| 大块数据 | Block 与多块读 | 多帧 8 B 拼接(电子标签、升级、黑匣子等) |
| 源码入口 | pmbus.lua:chip_*、get_linear_* | canbus.lua:chip_write_read、get_signal_data、get_batch_query_data |
规格书维护上,PMBus 以 SMBus 事务与 Command 语义 为主;CANBus 以 波特率、扩展帧约定、命令表、Sigid、批量字段顺序 为主,分别落表到 pmbus.cmd / canbus.cmd。
2. 设备树适配(power_mgmt 侧:选协议 + 读硬件)
本章说明 protocol/init.lua 注册、OnePower.PhysicalInterface 与 PsuSlot / OnePower 适配之间的关系,以及协议对象与 Monitor 的典型分工。
2.1 Protocol 与 Monitor 注册
编辑 include/device_tree/adapters/power_mgmt/protocol/init.lua,在 protocol 表中增加一项:键名 = OnePower 的 PhysicalInterface 字符串(与 CSR/设备树约定一致);值 为三元素表:
{ 对外 Protocol 名字符串, require(协议模块), monitor 模块路径字符串 }第三项 monitor 可省略(部分条目仅有协议模块);若省略,通用 PsuSlot:get_protocol 会在无 monitor 时打告警日志,需确认机型是否允许。
映射关系示意:
表中已有示例(节选):
-- Lines 18-21: include/device_tree/adapters/power_mgmt/protocol/init.lua
-- 通用电源pmbus协议
pmbus = { 'pmbus', require (base_content .. 'pmbus'), base_content .. 'monitor.pmbus' },
-- 通用电源canbus协议
canbus = { 'canbus', require (base_content .. 'canbus'), base_content .. 'monitor.canbus' },厂商 + 型号映射(可选):按 init.lua 注释增加与顶表同形的三元组 protocol[制造商][型号] = { 协议名字符串, require(…), '…monitor…' }。当前仓库中 protocol 仅含 physical_interface 顶键;嵌套表需按机型手工添加。fetch_power_supply_info 第二轮 get_protocol 仅当首轮已用 physical_interface 拉取到 manufacturer、model 且嵌套表存在时才会切换实现。
2.2 PsuSlot / OnePower Adapter
| 类别 | 路径 |
|---|---|
| 默认槽位逻辑 | include/device_tree/adapters/PsuSlot.lua |
| 默认 OnePower 适配 | include/device_tree/adapters/OnePower.lua |
| 单板差异 | include/device_tree/adapters/<与 CSR 同名目录>/ 下放置 PsuSlot.lua(必要时 OnePower.lua);框架 优先 使用该目录下的实现 |
单板解析优先级示意:
PsuSlot 适配中常需关注的方法(通用实现已部分串联 monitor,覆写时需保持行为一致或明确替代策略):
| 函数 | 作用 |
|---|---|
fetch_power_supply_info | 注册协议并刷新 FRU / 动态信息(通用实现中会调用 monitor:fetch_power_supply_info) |
power_monitor_start | 启动周期轮询(经 monitor:power_monitor_start) |
psm_monitor_stop / stop_monitor_tasks | 停止监控(升级、黑匣子等场景需停轮询) |
2.3 Protocol 模块职责
协议类(如 protocol/pmbus.lua、protocol/canbus.lua 及其变体)与 Monitor 分工可概括为:
| 能力 | 典型实现位置 |
|---|---|
| 功率 / 状态 / FRU 查询 | protocol/pmbus.lua 等协议模块中的 get_* |
| 黑匣子 | monitor:get_event_log 或协议 get_event_log(PsuSlot:get_black_box_data 会优先 monitor) |
| 主备、深度休眠 | set_power_mode、set_sleep_mode 等(依机型在协议或槽位中暴露) |
| 风扇转速 | set_psu_fan_speed_rpm 等 |
| 固件升级 | protocol/upgrade/pmbus_upgrade.lua / canbus_upgrade.lua 与协议对象上的 upgrade 相关入口 |
3. PMBus 相关代码结构
3.1 模块位置与变体
| 文件 | 说明 |
|---|---|
protocol/pmbus.lua | 基类:mc.class(),PMBus 命令字表 pmbus.cmd、CRC8、按字/块读写、Linear11/16、Direct、状态与健康、固件版本与升级入口等。 |
protocol/pmbus_qb900.lua | 电源砖等变体(如天工 AI 节点),常配合 monitor/pmbus_qb900.lua,功率是否计入总量等策略不同。 |
protocol/pmbus_eb1000_1.lua | EB1000 等刀片/砖块差异(巡检等可能与通用不同)。 |
protocol/pmbus_PDC3KD5412_LC.lua、pmbus_PDC4000D12_LC.lua、pmbus_FP1420.lua | 特定型号:轮询间隔、命令支持、监控模块等。 |
protocol/powerconverter_pmbus.lua | 电源砖通用变体 + monitor/powerconverter_pmbus.lua。 |
protocol/smc.lua | 经 SMC 取电信息,对外仍挂名 pmbus 类协议名。 |
protocol/upgrade/pmbus_upgrade.lua | PMBus 在线升级状态机(DCDC/PFC/QB 等软体、与 FRU/软体信息结构配合)。 |
3.2 协议事务与字节布局
PMBus 在链路上按 SMBus / I²C 字节事务 组织,并无与 CAN 类似的固定 MAC 帧;一条事务由 Start / 从机地址与方向 / Command(PMBus 命令码)/ 数据字节 / PEC(CRC-8)/ Stop 等构成,具体比特时序由 PsuChip BlockIO 与控制器完成。实现侧关注的是 命令码 cmd、SlotI2cAddr、载荷以及 PEC 参与校验的字节序列。
3.2.1 写路径与 PEC(chip_write)
写操作将 cmd 与 data 经由 Write 下发;PEC 按 SMBus 规则对 [写地址][Command][数据…] 计算 CRC-8,附加在待发数据末尾:
-- Lines 211-216: include/device_tree/adapters/power_mgmt/protocol/pmbus.lua
function pmbus:chip_write(cmd, data)
local check_buf = string.format('%s%s%s', string.char(self.slot_i2c_addr), string.char(cmd), data)
local crc = crc8(check_buf)
self.psu_chip:Write(ctx.new(), cmd, data .. string.pack('B', crc))
endchip_bytewrite / chip_wordwrite / chip_blkwrite 仅改变 data 的字宽或 Block 首字节长度域,PEC 生成规则不变。
3.2.2 读路径与 PEC(chip_read)
读操作请求长度为 len 的 Read;返回缓冲区 最后一字节为 PEC,其校验范围为 [写地址][Command][读地址][数据…(不含 PEC)]:
-- Lines 233-251: include/device_tree/adapters/power_mgmt/protocol/pmbus.lua
-- chip_read 读取指定长的数据
function pmbus:chip_read(cmd, len)
local err_str = ''
local value
local check_buf
for _ = 1, RETRY_TIMES, 1 do
value = self.psu_chip:Read(ctx.get_context_or_default(), cmd, len)
check_buf = string.format('%s%s%s%s',
string.char(self.slot_i2c_addr),
string.char(cmd),
string.char(self.slot_i2c_addr | 0x01),
value:sub(1, #value - 1))
if value and check_data(value:sub(#value, #value):byte(), check_buf) == E_OK then
return value
end
err_str = string.format('[power_mgmt][pmbus]read command(0x%02x) failed', cmd)
end
error(err_str)
end读地址参与 check_buf 时为 slot_i2c_addr | 1。失败重试 RETRY_TIMES 次后 error。
3.2.3 Word / Byte / Block 映射
| API | 典型 len / 载荷 | 有效数据 |
|---|---|---|
chip_wordread | Read(cmd, 3),返回 2 数据字节 + PEC | 低字节在前解析为 16 位字 |
chip_byteread | Read(cmd, 2),返回 1 数据字节 + PEC | 单字节 |
chip_blkread | Read(cmd, len + 2) | 去掉 首字节与末尾 PEC,返回中间 len 字节(见源码 sub(2, #value - 1)) |
block_read / get_dynamic_block | 先读 BYTE_CNT,再按 计数 + BYTE_CNT + CS 读满缓冲 | Block 首字节为 长度,末尾 PEC;get_dynamic_block 在校验通过后去掉 长度字节与 PEC,仅返回 数据块 |
3.2.4 Block Read 动态长度(get_dynamic_block)
-- Lines 287-299: include/device_tree/adapters/power_mgmt/protocol/pmbus.lua
function pmbus:get_dynamic_block(cmd)
local value = self:block_read(cmd)
local check_buf = string.format('%s%s%s%s', string.char(get_addr_wr(self.slot_i2c_addr)),
string.char(cmd),
string.char(get_addr_rd(self.slot_i2c_addr)),
value:sub(1, #value - 1))
-- value 返回布局由 pmbus.block_read 保证
if check_data(value:sub(-1, -1):byte(), check_buf) == E_OK then
return value:sub(2, #value - 1)
end
error(string.format('[power_mgmt][pmbus]read command(0x%02x) failed, data:[%s]', cmd, utils.to_hex(value)))
endPEC 覆盖 写地址、命令、读地址及除 PEC 外的全部返回字节;成功时返回 value 的中间段(厂商字符串、序列号等 Block 应用场景)。
3.2.5 寄存器语义与数值解码
- 命令集合:
pmbus.cmd与各电源规格书中的 Command Code 一一对应;扩展时同步维护pmbus.read_cmd(若用于巡检列表)。 - Linear11 / Linear16 / Direct:见
get_linear_11、get_linear_16、get_direct;与 PEC 布局无关,属于 寄存器返回值语义层。Linear-11、VOUT / LINEAR-16 的位布局与换算见下文 §3.2.6、§3.2.7(写法与 §4.2 CANBus 数据帧格式 类似:先说明层级与字段,再给出布局与实现入口)。
3.2.6 Linear-11 数据格式
与 §4.2 将 CAN 帧分为 链路层 MAC 与 应用层 PDU 类似,PMBus 在 字节事务(§3.2.1~3.2.4) 之上,还有 数据字(Data Word) 的语义编码:Linear-11 用 一个 16 位字 表示带数量级的模拟量,典型由 chip_wordread 读回(低字节在前,与 PMBus Word 事务一致)。
位域布局(16 位无符号机器字 raw_word 中的划分;解码时按有符号补码解释 Y、N):
| 位域 | 宽度 | 含义 |
|---|---|---|
| 高 5 位(bit15–11) | 5 bit | 指数 N:二进制 有符号整数,补码表示 |
| 低 11 位(bit10–0) | 11 bit | 尾数 Y:二进制 有符号整数,补码表示 |
与真实物理量之间的关系(规格书常用写法):
X = Y · 2^N
- X:换算后的物理量真值(量纲依 Command Code 而定,如电压、电流)。
- Y:低 11 位按补码解释的整数尾数。
- N:高 5 位按补码解释的整数指数。
本仓库在 pmbus:get_linear_11 中对 raw_word 拆出尾数与指数并完成移位运算;对部分 读电流 命令另有 10 mA 量级精度处理,详见 pmbus.lua 实现与注释。
-- Lines 301-312: include/device_tree/adapters/power_mgmt/protocol/pmbus.lua
function pmbus:get_linear_11(cmd)
local raw_word = self:chip_wordread(cmd)
local value = raw_word & 0x7FF
local bit = ((raw_word >> 11) & 0x1f)
if raw_word & 0x8000 > 0 then
bit = (255 - (bit | 0xE0)) + 1
-- 电流较小(0~1 A)时,以 A 为单位传值会导致精度丢失;
-- 计算电流时,将读数先放大,以 10 mA 为单位传值以保留精度;
return self:is_pmbus_cmd_read_i(cmd) and ((value * PS_I_SCALING_FACTOR) >> bit) or (value >> bit)
end
return value << bit
end3.2.7 VOUT(LINEAR-16)数据格式
输出电压相关命令(如 READ_VOUT 等)在规格书中常采用 LINEAR-16:由 16 位无符号整数 V 与 指数 N 共同决定电压,与 Linear-11 的「Y+N 同字」布局不同,V 为无符号、N 通常由 VOUT_MODE 等寄存器给出。
前提:电源需支持 VOUT_MODE 命令(本仓库命令常量见 pmbus.cmd.VOUT_MODE),输出电压数据格式须与 VOUT_MODE 所配置的编码方式一致。
换算关系(输出电压,单位:伏特 V):
Voltage = V · 2^N
- Voltage:输出电压数值。
- V:16 位无符号整数(对
READ_VOUT返回的 Data Word 按无符号解析)。 - N:5 位二进制有符号整数(补码);具体取值由
VOUT_MODE的 Mode、VID 等字段解码得到。文档或机型说明中常见N = -12作为某一 VID 模式下的典型指数;若与具体电源数据手册或寄存器定义不一致,以手册及现场VOUT_MODE读值为准。
解码入口:pmbus:get_linear_16(cmd, vout_mode),其中 vout_mode 一般为读 VOUT_MODE 得到的字节经解析后的模式量(见 pmbus.lua 中与 VOUT_EXPONENT 相关的指数计算)。
-- Lines 314-322: include/device_tree/adapters/power_mgmt/protocol/pmbus.lua
function pmbus:get_linear_16(cmd, vout_mode)
local exponent = (1 << VOUT_EXPONENT) - vout_mode
-- bit0-4 为 exponent,需要判断正负数
if (vout_mode & 0x10) ~= 0 then
return self:chip_wordread(cmd) / (2 ^ exponent)
end
return self:chip_wordread(cmd) << exponent
end3.3 Monitor(monitor/pmbus.lua 等)
- 对
PsuSlot做 class 包装,增加fetch_power_supply_info、power_monitor_start、远程功率上报(PluginRequest/ DBus)、时间同步、健康事件合并等。 - 读周期 等参数可与通用 CANBus Monitor 不同;定制机型使用独立 monitor 模块并在
init.lua第三元指定路径。
3.4 升级
- 业务侧
src/lualib/power_upgrade.lua中COMPONENT_IDEX将Protocol字段pmbus→ 0、canbus→ 2,与component_idex、UpgradeSupported共同用于升级对象筛选(参见该文件中的升级入口逻辑)。 - 具体打包、擦写、重启时序在
upgrade/pmbus_upgrade.lua,并与upgrade/fw_def.lua、FRU 中软体描述结构配合。
4. CANBus 相关代码结构
4.1 模块位置与变体
| 文件 | 说明 |
|---|---|
protocol/canbus.lua | 基类:CANBus 协议栈;canbus.cmd、canbus.protocol(帧长、批量长度、黑匣子参数);chip_write_read;get_signal_data(按 sigid);get_batch_query_data(0x40);电子标签与升级帧等。 |
protocol/canbus_tpsu.lua | 继承 canbus:双路 CANBus 物理接口(PsuChip + PsuBackupChip)、主备通道切换、canbus.tpsu_cmd、黑匣子/批量长度等对 protocol 表的覆盖。 |
protocol/canbus_pah.lua | 继承 canbus:PAH 机型差异(通道、命令选择等)。 |
protocol/upgrade/canbus_upgrade.lua | CANBus 在线升级:读 bin、CRC16、start_canbus_download、分帧与滑窗确认(与 canbus.cmd 中 D3–D6 类命令配合)。 |
4.2 数据帧格式
4.2.1 CAN 2.0 MAC 帧(链路层)
电源侧 CANBus 物理与 MAC 遵循 ISO 11898、CAN 2.0 A/B。主机与电源之间交换的是标准 数据帧(不含远程帧场景时):含 仲裁域(Identifier)、控制域、数据长度码 DLC、数据域 Data Field(0~8 B)、CRC(15 bit)、ACK、帧结束 等。有效载荷至多 8 字节;波特率、采样点、扩展帧 29 bit Identifier 等在驱动与收发器配置,Lua 栈不解析比特时序。
4.2.2 应用层 PDU:can_data_info
与电源通信的 语义字段 由 mc.bitstring 打包为二进制缓冲区,经 PsuChip:WriteRead 下发;驱动将该缓冲区映射到 CAN 帧 Identifier / Data Field 的具体拆分方式以实现为准。定义见 canbus.lua:
-- Lines 122-132: include/device_tree/adapters/power_mgmt/protocol/canbus.lua
local can_data_info = bs.new([[<<
cnt:1,
reserve:6,
ms:1,
cmd:8,
addr:7,
protocol:6,
frame_type:3,
sigid_and_error:16/big,
data/string
>>]])字段按 bitstring 声明顺序 串行打包;sigid_and_error 为 16 bit、大端(/big)。get_signal_data 中取 (sigid_and_error & 0xf000) >> 12 为应答错误码,sigid_and_error & 0x0fff 为 Sigid。
| 字段 | 宽度 | 说明 |
|---|---|---|
cnt | 1 bit | 计数位 |
reserve | 6 bit | 单播时常为槽位相关保留(如 slot_addr);canbus_broadcast_cmd 中为 0 |
ms | 1 bit | BIT_M_CNT = 1(主发)、BIT_S_CNT = 0(从侧) |
cmd | 8 bit | 命令字节,对应 canbus.cmd(如 0x40、0x50、0x82) |
addr | 7 bit | 节点地址;广播时为 0 |
protocol | 6 bit | CAN_POWER_PROTOCOL = 0x3f |
frame_type | 3 bit | CAN_EXTENDED_FRAME = 4(扩展帧路径) |
sigid_and_error | 16 bit | 应答错误码(bit12–15)与 Sigid(bit0–11) |
data | 变长 | can_data_info 尾部字节串;如 CMD_QUERY 路径使用 6 B 填充(见 can_send_get_data_info)。FRAME_DATA_LEN = 8 在同文件用于 升级分包、批量切片步长 等,与单次 pack 总长无固定相等关系 |
同源常量:CAN_POWER_PROTOCOL、CAN_EXTENDED_FRAME、FRAME_DATA_LEN。
4.2.3 批量应答拆解:can_frame_info / can_frame_data
0x40 等批量命令返回的是 较长的 canbus_data;外层用 can_frame_info 解出 canbus_data,再按 CANBUS_FRAME_DATA_SIZE(8) 切成多段,每段用 can_frame_data 解析:
-- Lines 134-148: include/device_tree/adapters/power_mgmt/protocol/canbus.lua
local can_frame_info = bs.new([[<<
cnt:1,
reserve:6,
ms:1,
cmd:8,
addr:7,
protocol:6,
frame_type:3,
canbus_data/string
>>]])
local can_frame_data = bs.new([[<<
sigid_and_error:16/big,
data/string
>>]])即:批量路径下,每 8 B 对应一段 sigid_and_error + data 的电源侧约定布局,与 4.2.2 中 单帧 Sigid 语义 一致。
4.2.4 典型用法(与入口函数对应)
- 单点查询:
CMD_QUERY(0x82),get_signal_data中校验(sigid_and_error & 0xf000) >> 12 == 0后使用data。 - 周期批量:
CMD_BATCH_QUERY_PERIOD_DATA(0x40),get_batch_query_data使用can_frame_info/can_frame_data按 8 B 切片。 - 广播:
canbus_broadcast_cmd,addr = 0、reserve = 0,其余字段按广播命令约定填充。
4.3 数值与属性映射
- 功率/电流等常通过 uint32 + 系数 1024(
CANBUS_POWER_COFFICIENT)或canbus:get_batch_query_data解析链路映射到 DAL 属性;扩展 0x40 批量顺序 时,应修改canbus:canbus_get_property_info中 sigid → 属性名、类型、缩放 的表,并保持与电源规格书中顺序一致(注释中已说明追加建议)。
4.4 Monitor(monitor/canbus.lua、monitor/canbus_tpsu.lua、monitor/canbus_pah.lua)
- 初始化时往往先
update_elabel_info/refresh_basic_info(CANBus 侧电子标签与版本路径与 PMBus 不同)。 - 健康与告警:例如将 AlarmStatus 位域映射到统一 health_event(见
update_health_event)。 - TPSU:
read_interval、通道切换与升级通道逻辑与基类不同,开发时勿混用PsuChip句柄。
5. 开发指导:新增或修改协议时怎么做
5.1 通用步骤(PMBus / CANBus 共用)
- 在
protocol/init.lua中为OnePower.PhysicalInterface增加表项,保证protocol[physical_interface]存在(否则首轮get_protocol即失败)。 - 确定键名与模块映射:
{ 'pmbus' 或 'canbus', require('…协议模块'), 'device_tree.adapters.power_mgmt.monitor.xxx' }- Monitor 路径可省略;省略时
PsuSlot:get_protocol仍会建立protocol对象,但log:warn提示无 monitor。
- 实现协议模块:
- 使用
mc.class();构造函数签名与基类一致:function ctor(self, psu_slot, protocol_name),并从psu_slot取PsuChip、SlotI2cAddr/SlotNumber等。 - 为每个对外属性实现
get_<属性名>,命名与 DAL/上游一致。
- 使用
- 必要时新增 Monitor:
return function(obj) local psu_slot = class(obj) … end,在ctor(self, protocol)中保存self.protocol。 - 单元测试:
test/unit/下test_pmbus.lua、protocol/test_canbus_*、*_monitor.lua等;新增命令或属性时补充 Chip mock 与断言。
5.2 仅 PMBus
- 优先 继承或复制
pmbus.lua的结构,避免重复实现 CRC 与 Linear 解码。 - 新增命令字:在子模块或基类
pmbus.cmd中增加常量,并在read_cmd或业务路径中引用。 - Block 读长度:注意
BUFFER_MAX_LEN、block_read长度校验,避免 OOB。 - 电流极小场景:基类已对部分 READ_I 命令做 10 mA 精度 相关处理,修改时勿破坏该分支。
5.3 仅 CANBus
- 优先
class(canbus_base)继承canbus.lua,在子类ctor中覆盖canbus.protocol各长度常量与黑匣子参数(参考canbus_tpsu.lua)。 - 新增 sigid:在
canbus.cmd或子模块tpsu_cmd增加常量;实现get_xxx时复用get_signal_data(sigid)。 - 扩展 0x40 批量:同时更新
canbus_get_property_info与解析循环,避免属性错位。 - 双路 CANBus 机型:处理 主备芯片 与
chip_write_read使用的psu_chip(TPSU 经canbus_chip切换)。
5.4 升级与制造
- PMBus:
upgrade/pmbus_upgrade.lua、power_upgrade.lua、制造侧manufacture/manufacture_app.lua可能对协议名敏感,新增变体时需确认 组件 ID / 协议名字符串 与既有流程兼容。 - CANBus:
canbus_upgrade.lua中帧长 8 字节、crc16与文件读取路径需与固件打包约定一致。
5.5 调试建议
- 日志:调高
mc.logging级别;PMBuschip_read在重试耗尽后error;CANBuschip_write_read失败返回nil并写日志。 - 集成:
test/integration/test_power_mgmt.lua、test_power_mgmt_rpc.lua。 - 行为变更以
CHANGELOG.md为准(延时、防抖、版本读取时机等)。
6. 关键路径索引
| 类别 | 路径 |
|---|---|
| 协议注册 | include/device_tree/adapters/power_mgmt/protocol/init.lua |
| PMBus 基类 | include/device_tree/adapters/power_mgmt/protocol/pmbus.lua |
| CANBus 基类 | include/device_tree/adapters/power_mgmt/protocol/canbus.lua |
| CAN TPSU | include/device_tree/adapters/power_mgmt/protocol/canbus_tpsu.lua |
| CAN PAH | include/device_tree/adapters/power_mgmt/protocol/canbus_pah.lua |
| Monitor 目录 | include/device_tree/adapters/power_mgmt/protocol/monitor/ |
| PMBus 升级 | include/device_tree/adapters/power_mgmt/protocol/upgrade/pmbus_upgrade.lua |
| CANBus 升级 | include/device_tree/adapters/power_mgmt/protocol/upgrade/canbus_upgrade.lua |
| 槽位(默认) | include/device_tree/adapters/PsuSlot.lua |
| OnePower(默认) | include/device_tree/adapters/OnePower.lua |
| 升级回调 | src/lualib/power_upgrade.lua |
7. 补充
- 新机型在
init.lua注册后,优先通过 子类 扩展pmbus_*/canbus_*,减少重复实现。 - 设备树Adapter类成员变量应在ctor中初始化,否则运行期可能为nil。