部件驱动接口模型设计
1. 概述
部件驱动接口模型是Component Drivers项目的核心架构设计,采用"配置驱动+代码生成"的设计理念,通过DDS(Device Description Standard)配置文件自动生成接口层代码和DBus设备树接口,实现了接口定义与实现的彻底分离,极大提升了开发效率和系统可扩展性。
1.1 核心特性
- DDS配置驱动: 通过标准化的JSON配置文件定义设备接口和对象模型
- 自动代码生成: 从DDS配置自动生成C++接口头文件和反射代码
- 接口与实现分离: 生成的接口代码与厂商实现完全解耦
- 多层抽象: 支持接口层、设备对象层、驱动实现层的清晰分层
- 反射机制: 通过MC_REFLECT实现运行时属性访问和序列化
1.2 技术优势
| 优势 | 说明 | 价值 |
|---|---|---|
| 开发效率提升 | 接口代码自动生成,无需手写 | 减少70%以上的接口代码编写工作 |
| 标准化接口 | 统一的接口定义规范 | 确保多厂商设备接口一致性 |
| 易于扩展 | 新增接口只需修改DDS配置 | 快速支持新设备类型 |
| 跨进程访问 | 自动生成DBus接口 | 支持进程间设备管理 |
| 类型安全 | 编译期类型检查 | 减少运行时错误 |
| 维护性强 | 接口定义集中管理 | 接口变更影响可控 |
2. 设计目标
- 提供统一的设备接口定义和管理机制
- 实现接口定义与实现的完全分离
- 支持从配置文件自动生成接口代码
- 支持多厂商、多型号设备的统一管理
- 提供基于反射的动态属性访问能力
- 实现设备对象的层次化组织和管理
3. 整体架构
3.1 三层架构模型
3.2 数据流向
4. DDS配置机制
4.1 DDS配置文件结构
DDS (Device Description Standard) 配置文件采用JSON格式,定义了设备的完整接口模型:
{
"Schema": "dds-v1",
"Type": "Component",
"DeviceCategory": "PCIeNicCard",
"ID": "N/A",
"Objects": {
"PCIeNicCard": {
"Path": "/bmc/dev/Systems/:SystemId/PCIeNicCard/:Id",
"Interfaces": [
"bmc.dev.PCIeDevice",
"bmc.dev.PCIeDevice.PCIeFunction",
"bmc.dev.PCIeDevice.Status",
"bmc.dev.PCIeDevice.Oem",
"bmc.dev.PCIeCard",
"bmc.dev.PCIeCard.Oem",
"bmc.dev.PCIeCard.Metrics",
"bmc.dev.Board",
"bmc.dev.NetworkAdapter",
"bmc.dev.PCIeDevice.Bandwidth",
"bmc.dev.Cooling",
"bmc.dev.NetworkAdapter.FaultStatus",
"bmc.dev.NetworkAdapter.LogCollection",
"bmc.dev.NetworkAdapter.Oem"
]
},
"NicPort": {
"Path": ":Parent/NicPort/:Id",
"Interfaces": [
"bmc.dev.NetworkPort",
"bmc.dev.NetworkPort.LinkInfo",
"bmc.dev.NetworkPort.DataCenterBridging",
"bmc.dev.NetworkPort.LLDPReceive",
"bmc.dev.NetworkPort.Metrics"
]
},
"OpticalTransceiver": {
"Path": ":Parent/OpticalTransceiver",
"Interfaces": [
"bmc.dev.OpticalModule",
"bmc.dev.OpticalModule.Status",
"bmc.dev.OpticalModule.TemperatureCelsius",
"bmc.dev.OpticalModule.Voltage",
"bmc.dev.OpticalModule.Power",
"bmc.dev.OpticalModule.Current",
"bmc.dev.OpticalModule.Diagnose"
]
}
}
}4.2 DDS配置元素说明
| 字段 | 说明 | 示例 | 作用 |
|---|---|---|---|
| Schema | DDS版本标识 | "dds-v1" | 定义配置文件格式版本 |
| Type | 设备类型 | "Component" | 标识设备大类 |
| DeviceCategory | 设备类别 | "PCIeNicCard" | 具体设备类别名称 |
| Objects | 设备对象集合 | {...} | 定义所有设备对象及其接口 |
| Path | 对象路径模式 | "/bmc/dev/..." | 设备在系统中的路径规则 |
| Interfaces | 接口列表 | [...] | 对象支持的所有接口 |
4.3 接口定义配置
每个接口通过独立的JSON文件定义其属性和方法:
{
"name": "PCIeDevice",
"namespace": "bmc.dev",
"description": "PCIe设备基础接口",
"properties": [
{
"name": "DeviceName",
"type": "string",
"description": "设备资源名称",
"writable": true
},
{
"name": "Location",
"type": "string",
"description": "当前PCIe的物理位置",
"writable": true
},
{
"name": "Slot",
"type": "uint8_t",
"description": "PCIe设备的物理槽位号",
"writable": true
},
{
"name": "SocketId",
"type": "uint8_t",
"description": "PCIe设备所属CPU ID",
"writable": true
},
{
"name": "Bus",
"type": "uint8_t",
"description": "PCIe Root Port的总线号",
"writable": true
},
{
"name": "Device",
"type": "uint8_t",
"description": "PCIe Root Port的设备号",
"writable": true
},
{
"name": "Function",
"type": "uint8_t",
"description": "PCIe Root Port的功能号",
"writable": true
}
],
"methods": [
{
"name": "SetRootBDF",
"description": "设置根设备BDF",
"returnType": "bool",
"parameters": [
{"name": "bus", "type": "uint8_t"},
{"name": "device", "type": "uint8_t"},
{"name": "function", "type": "uint8_t"}
]
}
]
}4.4 路径模式规则
路径模式支持以下特殊语法:
| 语法 | 说明 | 示例 |
|---|---|---|
:参数名 | 路径参数占位符 | /Systems/:SystemId/PCIeNicCard/:Id |
${参数名} | 属性引用 | ${DeviceName} |
:Parent | 父对象路径引用 | :Parent/NicPort/:Id |
5. 接口代码自动生成
5.1 代码生成流程
5.2 生成的C++接口类
自动生成的C++接口类位于dev::gen命名空间:
// 自动生成文件: gen/include/device_tree/interface/PCIeDevice.h
#ifndef GEN_PCIe_DEVICE_INTERFACE_H
#define GEN_PCIe_DEVICE_INTERFACE_H
#include <device_tree/base.h>
namespace dev::gen {
/**
* @brief PCIe设备基础接口
*
* 此接口由DDS配置自动生成,定义了PCIe设备的标准属性和方法。
* 厂商实现应继承此接口并实现具体逻辑。
*/
class MC_API PCIeDevice : public mc::engine::interface<PCIeDevice> {
public:
MC_INTERFACE("bmc.dev.PCIeDevice")
property<std::string> DeviceName; ///< 设备资源名称
property<std::string> Location; ///< 当前PCIe的物理位置
property<uint8_t> Slot; ///< PCIe设备的物理槽位号
property<uint8_t> SocketId; ///< PCIe设备所属CPU ID
property<uint8_t> SystemId; ///< PCIe设备所属系统ID
property<uint8_t> Bus; ///< PCIe Root Port的总线号
property<uint8_t> Device; ///< PCIe Root Port的设备号
property<uint8_t> Function; ///< PCIe Root Port的功能号
property<std::string> SlotType; ///< PCIe设备所在槽位的类型
property<std::string> DeviceType; ///< PCIe设备类型
property<std::string> Model; ///< PCIe标卡产品型号
property<std::string> Manufacturer; ///< 厂商
property<std::string> PartNumber; ///< 部件编码
property<std::string> SerialNumber; ///< 序列号
property<std::string> FirmwareVersion; ///< PCIe标卡的固件版本号
property<uint8_t> MaxPCIeType; ///< 最大支持的PCIe接口规格
property<uint8_t> PCIeType; ///< 实际的PCIe接口规格
property<uint8_t> MaxLanes; ///< 支持的最大通道数
property<uint8_t> LaneInUse; ///< 实际使用的通道数
virtual bool SetRootBDF(uint8_t bus, uint8_t device, uint8_t function) = 0;
};
} // namespace dev::gen
#endif // GEN_PCIe_DEVICE_INTERFACE_H说明:以上内容与
gen/include/device_tree/interface/PCIeDevice.h完全一致。接口基类为mc::engine::interface<PCIeDevice>(单模板参数),命名空间为dev::gen,头文件包含device_tree/base.h。
5.3 接口反射注册
运行时属性访问通过反射机制实现。与生成的接口头文件不同,反射注册是在厂商接口实现(.cpp)中通过 MC_REFLECT(dev::Xxx) 宏完成,并不单独生成 _reflect.h 文件。示例(与库中 drivers/pcie_nic_card/hisi/interface/pcie_device.cpp 一致):
// 厂商接口实现文件: drivers/pcie_nic_card/hisi/interface/pcie_device.cpp (节选)
namespace dev {
// 反射注册:将实现类的属性与 D-Bus 接口关联
MC_REFLECT(dev::PCIeDevice)
} // namespace dev反射注册在接口实现源文件中定义,其他厂商接口(PCIeCard、NetworkAdapter、Cooling、Board、Fru 等)均在各自的 .cpp 中以相同方式调用 MC_REFLECT(dev::Xxx) 完成注册。
5.4 生成文件组织结构
gen/
└── include/
└── device_tree/
└── interface/ # 生成的接口类(全部为 dev::gen 命名空间)
├── PCIeDevice.h # PCIe设备接口
├── NetworkAdapter.h # 网络适配器接口
├── NetworkPort.h # 网络端口接口
└── ... # 其他接口6. 接口实现机制
6.1 厂商接口实现
厂商通过继承生成的接口基类实现具体逻辑:
// 厂商实现文件: drivers/pcie_nic_card/hisi/interface/pcie_device.h
#ifndef PCIE_DEVICE_INTERFACE_H
#define PCIE_DEVICE_INTERFACE_H
#include <mc/engine/service.h>
#include <mc/timer.h>
#include <device_tree/interface/PCIeDevice.h>
#include <ncsi_over_mctp/ncsi_over_mctp_huawei.h>
#include <smbus/smbus.h>
namespace dev {
using smbus_obj_ptr = mc::shared_ptr<smbus>;
/**
* @brief PCIe设备接口的海思厂商实现
*
* 继承 auto-generated 的 dev::gen::PCIeDevice 基类。
* 厂商实现类需以 mc::engine::interface<实现类, 基类> 双模板参数形式继承,
* 使接口同时具备厂商实现与生成基类的双重类型信息。
*/
class MC_API PCIeDevice : public mc::engine::interface<PCIeDevice, gen::PCIeDevice> {
public:
PCIeDevice() = default;
~PCIeDevice() = default;
public:
// 实现基类虚方法
bool SetRootBDF(uint8_t bus, uint8_t device, uint8_t function) override;
public:
void set_smbus_obj(smbus_obj_ptr smbus_obj);
bool set_slot_by_smbus(uint8_t slot);
private:
smbus_obj_ptr m_smbus_obj;
public:
void replace_dynamic_property(mc::mutable_dict& object, const mc::dict& connector);
};
} // namespace dev
#endif // PCIE_DEVICE_INTERFACE_H实现文件(节选):
// 厂商实现文件: drivers/pcie_nic_card/hisi/interface/pcie_device.cpp (节选)
namespace dev {
bool PCIeDevice::SetRootBDF(uint8_t bus, uint8_t device, uint8_t function)
{
if (bus == 0 && device == 0 && function == 0) {
std::cerr << "Error: Invalid BDF values" << std::endl;
return false;
}
Bus = bus;
Device = device;
Function = function;
return true;
}
void PCIeDevice::set_smbus_obj(smbus_obj_ptr smbus_obj)
{
m_smbus_obj = smbus_obj;
}
// 反射注册:单参数形式,在 .cpp 中完成
MC_REFLECT(dev::PCIeDevice)
} // namespace dev说明:
- 厂商实现类用 双模板参数
mc::engine::interface<PCIeDevice, gen::PCIeDevice>继承,而非直接: public gen::PCIeDevice。- 反射注册为 单参数
MC_REFLECT(dev::PCIeDevice),在.cpp中完成,无 3 参数形式。- 当前
dev::PCIeDevice不包含 NCSI 定时任务成员,也不声明pcie_device_bdf_changed信号;该信号声明于dev::PCIeDevice_PCIeFunction(见interface/pcie_device/pcie_function.h)。NCSI 更新任务由具体网卡设备对象(如hi182x_card)及各业务接口发起。
6.2 设备对象组合接口
设备对象通过组合多个接口实现复杂功能:
// 设备对象文件: drivers/pcie_nic_card/hisi/hi182x/hi182x_card.h
#ifndef HI182X_CARD_H
#define HI182X_CARD_H
#include <imu/imu.h>
#include <mc/engine.h>
#include <mc/timer.h>
#include <mctp/mctp.h>
#include <ncsi_over_mctp/ncsi_over_mctp_huawei.h>
#include <smbus/smbus.h>
#include "hi182x_port.h"
#include "interface/board.h"
#include "interface/cooling.h"
#include "interface/fru.h"
#include "interface/network_adapter.h"
// ... 其余接口头文件
namespace dev {
using ncsi_over_mctp_hw_ptr = std::shared_ptr<ncsi_over_mctp_huawei>;
using smbus_obj_ptr = mc::shared_ptr<smbus>;
using imu_ptr = std::shared_ptr<imu>;
class hi182x_card : public mc::engine::object<hi182x_card> {
public:
// MC_OBJECT宏定义:类名 / 设备类型名 / 路径模式 / 支持的接口列表
MC_OBJECT(
hi182x_card, "PCIeNicCard", "/bmc/dev/Systems/1/PCIeNicCard/${object_name}",
(PCIeDevice)(PCIeDevice_PCIeFunction)(PCIeDevice_Oem)(PCIeDevice_Status)(PCIeCard)(PCIeCard_Oem)(PCIeCard_Metrics)(NetworkAdapter)(NetworkAdapter_FaultStatus)(Cooling)(NetworkAdapter_Oem)(Board)(PCIeDevice_Bandwidth)(NetworkAdapter_LogCollection)(Fru))
hi182x_card();
~hi182x_card();
// 生命周期方法(非虚,不带 override)
bool start();
bool stop();
bool init(mc::mutable_dict& csr_object, const mc::dict& connector);
void init_network_ports();
void replace_dynamic_property(mc::mutable_dict& object, const mc::dict& connector);
// === 接口实例(组合模式) ===
NetworkAdapter_Oem m_network_adapter_oem;
PCIeDevice m_pcie_device;
PCIeDevice_PCIeFunction m_pcie_device_pcie_function;
PCIeDevice_Oem m_pcie_device_oem;
PCIeDevice_Status m_pcie_device_status;
PCIeCard m_pcie_card;
PCIeCard_Oem m_pcie_card_oem;
PCIeCard_Metrics m_pcie_card_metrics;
Cooling m_cooling;
NetworkAdapter m_network_adapter;
NetworkAdapter_FaultStatus m_network_adapter_fault_status;
Board m_board;
PCIeDevice_Bandwidth m_pcie_device_bandwidth;
NetworkAdapter_LogCollection m_network_adapter_log_collection;
Fru m_fru;
uint8_t m_system_id;
private:
std::vector<hi182x_port*> m_network_ports;
// === 协议管理 ===
bool start_ncsi_protocol();
void stop_ncsi_update_task();
bool start_smbus_protocol();
bool init_smbus_protocol();
bool init_imu_protocol();
bool start_protocol();
ref_chip_ptr m_ref_chip;
smbus_obj_ptr m_smbus_obj;
imu_ptr m_imu_obj;
ncsi_over_mctp_hw_ptr m_ncsi_over_mctp_huawei;
mc::milliseconds m_interval = mc::milliseconds(5000);
mc::milliseconds m_smbus_interval = mc::milliseconds(5000);
mc::shared_ptr<mctp> m_mctp_object;
};
} // namespace dev
// MC_REFLECT定义:建立接口成员与 D-Bus 接口名的映射
MC_REFLECT(dev::hi182x_card,
((m_system_id, "SystemId"))((m_pcie_device, "bmc.dev.PCIeDevice"))
((m_pcie_device_pcie_function, "bmc.dev.PCIeDevice.PCIeFunction"))
((m_pcie_device_oem, "bmc.dev.PCIeDevice.Oem"))
((m_pcie_device_status, "bmc.dev.PCIeDevice.Status"))
((m_pcie_card, "bmc.dev.PCIeCard"))((m_pcie_card_oem, "bmc.dev.PCIeCard.Oem"))
((m_pcie_card_metrics, "bmc.dev.PCIeCard.Metrics"))
((m_network_adapter, "bmc.dev.NetworkAdapter"))
((m_network_adapter_fault_status, "bmc.dev.NetworkAdapter.FaultStatus"))
((m_cooling, "bmc.dev.Cooling"))((m_network_adapter_oem, "bmc.dev.NetworkAdapter.Oem"))
((m_board, "bmc.dev.Board"))((m_pcie_device_bandwidth, "bmc.dev.PCIeDevice.Bandwidth"))
((m_fru, "bmc.dev.Fru"))
((m_network_adapter_log_collection, "bmc.dev.NetworkAdapter.LogCollection")))
#endif // HI182X_CARD_H子设备识别(节选自 init_network_ports(),与库中一致):
// 通过对象名前缀识别设备类型,使用 dynamic_cast 并校验空指针
for (auto& object : objects) {
std::string sub_name = object->get_name();
if (sub_name.substr(0, sub_name.find_first_of("_")) == "NicPort") {
auto* port = dynamic_cast<hi182x_port*>(object.get());
if (port == nullptr) {
elog("hi182x_card child ${name} is not hi182x_port, skip", ("name", sub_name));
continue;
}
ilog("hi182x_card init network port ${name}", ("name", sub_name));
m_network_ports.push_back(port);
}
}6.3 接口层次关系
7. 完整开发流程示例
7.1 步骤1: 编写DDS配置文件
// dds/PCIeGpuCard.dds.json
{
"Schema": "dds-v1",
"Type": "Component",
"DeviceCategory": "PCIeGpuCard",
"ID": "N/A",
"Objects": {
"PCIeGpuCard": {
"Path": "/bmc/dev/Systems/:SystemId/PCIeGpuCard/:Id",
"Interfaces": [
"bmc.dev.PCIeDevice",
"bmc.dev.PCIeCard",
"bmc.dev.Gpu",
"bmc.dev.Board"
]
},
"GpuMemory": {
"Path": ":Parent/Memory/:Id",
"Interfaces": [
"bmc.dev.Memory",
"bmc.dev.Memory.Metrics"
]
}
}
}7.2 步骤2: 运行代码生成器
# 生成接口代码
./tools/dds_codegen.py \
--input dds/PCIeGpuCard.dds.json \
--output-cpp gen/include/device_tree/
# 生成输出(仅接口头文件,无 _reflect.h;反射在接口 .cpp 中注册):
# gen/include/device_tree/interface/Gpu.h
# gen/include/device_tree/interface/Memory.h7.3 步骤3: 实现厂商接口
// drivers/pcie_gpu_card/nvidia/interface/gpu.h
#ifndef NVIDIA_INTERFACE_GPU_H
#define NVIDIA_INTERFACE_GPU_H
#include <device_tree/interface/Gpu.h>
namespace dev {
/**
* @brief GPU接口的NVIDIA厂商实现
*/
class Gpu : public mc::engine::interface<Gpu, gen::Gpu> {
public:
// 实现基类虚方法
bool Initialize() override {
// NVIDIA特定的初始化逻辑
return init_nvidia_gpu();
}
bool GetStatus() override {
// 通过NVIDIA驱动获取GPU状态
return query_nvidia_status();
}
private:
bool init_nvidia_gpu();
bool query_nvidia_status();
};
} // namespace dev
#endif // NVIDIA_INTERFACE_GPU_H7.4 步骤4: 实现设备对象
// drivers/pcie_gpu_card/nvidia/tesla_t4/tesla_t4_card.h
#ifndef NVIDIA_TESLA_T4_CARD_H
#define NVIDIA_TESLA_T4_CARD_H
#include <mc/engine/object.h>
#include "drivers/pcie_gpu_card/nvidia/interface/gpu.h"
#include "drivers/pcie_gpu_card/nvidia/interface/pcie_device.h"
namespace dev {
class tesla_t4_card : public mc::engine::object<tesla_t4_card> {
public:
MC_OBJECT(
tesla_t4_card,
"PCIeGpuCard",
"/bmc/dev/Systems/1/PCIeGpuCard/${object_name}",
(PCIeDevice)(PCIeCard)(Board))
bool init(mc::mutable_dict& csr_object, const mc::dict& connector);
bool start();
bool stop();
// 接口实例
dev::PCIeDevice m_pcie_device;
dev::PCIeCard m_pcie_card;
dev::Gpu m_gpu;
dev::Board m_board;
};
} // namespace dev
MC_REFLECT(dev::tesla_t4_card,
((m_pcie_device, "bmc.dev.PCIeDevice"))
((m_pcie_card, "bmc.dev.PCIeCard"))
((m_gpu, "bmc.dev.Gpu"))
((m_board, "bmc.dev.Board"))
)
#endif // NVIDIA_TESLA_T4_CARD_H7.5 步骤5: 实现ABI导出
// drivers/pcie_gpu_card/nvidia/tesla_t4/tesla_t4_abi.cpp
#include <devmon/driver_abi.h>
#include "tesla_t4_card.h"
extern "C" {
driver_handle_t create_tesla_t4_card(void* service, const char* name) {
try {
if (service == nullptr || name == nullptr) {
return nullptr;
}
auto* device = new dev::tesla_t4_card();
device->set_service(static_cast<mc::engine::service*>(service));
device->set_object_name(name);
return (void*)device;
} catch (const std::exception& e) {
elog("Error creating tesla_t4_card: ${error}", ("error", e.what()));
return nullptr;
}
}
status_t init_tesla_t4_card(driver_handle_t device, void* csr_object, void* connector) {
if (device == nullptr || csr_object == nullptr || connector == nullptr) {
return STATUS_ERROR;
}
auto* device_object = static_cast<dev::tesla_t4_card*>(device);
auto* csr_object_ptr = static_cast<mc::mutable_dict*>(csr_object);
auto* connector_ptr = static_cast<mc::dict*>(connector);
bool ret = device_object->init(*csr_object_ptr, *connector_ptr);
return ret ? STATUS_OK : STATUS_ERROR;
}
status_t start_tesla_t4_card(driver_handle_t device) {
if (device == nullptr) {
return STATUS_ERROR;
}
auto* device_object = static_cast<dev::tesla_t4_card*>(device);
bool ret = device_object->start();
return ret ? STATUS_OK : STATUS_ERROR;
}
status_t stop_tesla_t4_card(driver_handle_t device) {
if (device == nullptr) {
return STATUS_ERROR;
}
auto* device_object = static_cast<dev::tesla_t4_card*>(device);
bool ret = device_object->stop();
return ret ? STATUS_OK : STATUS_ERROR;
}
device_driver_t tesla_t4_card_driver = {
.device_name = "PCIeGpuCard",
.ctor = create_tesla_t4_card,
.init = init_tesla_t4_card,
.start = start_tesla_t4_card,
.stop = stop_tesla_t4_card
};
status_t register_device_driver(device_driver_t** device_driver, uint8_t* count) {
*device_driver = &tesla_t4_card_driver;
*count = 1;
return STATUS_OK;
}
} // extern "C"7.6 步骤6: 编译和测试
# 配置构建
meson setup builddir
# 编译驱动库
meson compile -C builddir
# 运行测试
meson test -C builddir
# 安装驱动
meson install -C builddir8. 最佳实践
8.1 DDS配置设计原则
| 原则 | 说明 | 示例 |
|---|---|---|
| 单一职责 | 每个接口专注单一功能域 | NetworkPort.LinkInfo只负责链路信息 |
| 接口组合 | 通过组合而非继承扩展功能 | PCIeNicCard组合PCIeDevice+NetworkAdapter |
| 路径规范 | 使用层次化路径表示设备关系 | /Systems/:SystemId/PCIeNicCard/:Id |
| 属性命名 | 使用大驼峰命名法保持一致 | DeviceName, VendorId, NetworkPortCount |
| 只读/可写 | 明确标识属性的访问权限 | VendorId只读, DeviceName可写 |
8.2 接口实现规范
// ✅ 推荐:清晰的接口实现
class PCIeDevice : public mc::engine::interface<PCIeDevice, gen::PCIeDevice> {
public:
// 1. 实现所有虚方法
bool SetRootBDF(uint8_t bus, uint8_t device, uint8_t function) override {
// 参数验证
if (!validate_bdf(bus, device, function)) {
return false;
}
// 更新生成基类中的属性
Bus = bus;
Device = device;
Function = function;
return true;
}
private:
// 2. 使用私有方法封装复杂逻辑
bool validate_bdf(uint8_t bus, uint8_t device, uint8_t function) {
return !(bus == 0 && device == 0 && function == 0);
}
};
// ❌ 不推荐:不完整的实现
class PCIeDevice : public mc::engine::interface<PCIeDevice, gen::PCIeDevice> {
public:
// 缺少虚方法实现,导致编译错误
// 缺少日志记录
// 缺少错误处理
};8.3 设备对象设计模式
// ✅ 推荐:标准的设备对象模式
class hi182x_card : public mc::engine::object<hi182x_card> {
public:
// 1. 使用MC_OBJECT定义对象元数据
MC_OBJECT(hi182x_card, "PCIeNicCard",
"/bmc/dev/Systems/1/PCIeNicCard/${object_name}",
(PCIeDevice)(NetworkAdapter)(Board))
// 2. 实现标准生命周期方法
bool init(mc::mutable_dict& csr_object, const mc::dict& connector) {
// 初始化逻辑
return true;
}
bool start() {
// 启动逻辑
return true;
}
bool stop() {
// 停止逻辑
return true;
}
// 3. 声明接口实例
dev::PCIeDevice m_pcie_device;
dev::NetworkAdapter m_network_adapter;
dev::Board m_board;
private:
// 4. 私有成员和辅助方法
void init_ports();
bool start_protocol();
};
// 5. 定义反射映射
MC_REFLECT(dev::hi182x_card,
((m_pcie_device, "bmc.dev.PCIeDevice"))
((m_network_adapter, "bmc.dev.NetworkAdapter"))
((m_board, "bmc.dev.Board"))
)8.4 性能优化建议
// 1. 优先使用属性提供的批量/只读访问接口
// 属性值通过 .get_value() 一次读取,避免重复反序列化
std::string model = m_pcie_device.Model.get_value().as<std::string>();
// 2. 缓存频繁访问的属性(按实际存在的属性为准,此处以 DeviceType 为例)
class PCIeDevice {
private:
std::string m_cached_device_type;
bool m_device_type_cached = false;
public:
const std::string& get_device_type() {
if (!m_device_type_cached) {
m_cached_device_type = DeviceType.get_value().as<std::string>();
m_device_type_cached = true;
}
return m_cached_device_type;
}
};9. 总结
部件驱动接口模型通过DDS配置驱动的设计理念,实现了设备驱动开发的标准化和自动化:
9.1 核心优势
- 配置驱动开发: DDS配置文件定义设备接口和对象模型
- 自动代码生成: 从配置自动生成C++接口和反射代码
- 接口实现分离: 生成的接口代码与厂商实现完全解耦
- 类型安全: 编译期类型检查,减少运行时错误
- 易于扩展: 新增接口只需修改DDS配置
9.2 开发流程
DDS配置 → 代码生成 → 接口实现 → 设备对象 → ABI导出 → 编译测试9.3 适用场景
- 需要统一管理多种设备类型的系统
- 需要支持多厂商设备的平台
- 需要快速开发新设备驱动的项目
- 需要接口标准化的设备管理系统
通过遵循本文档的设计原则和最佳实践,开发者可以高效地开发出高质量、可维护的设备驱动程序,构建强大的设备管理系统。