当前位置: 首页 > news >正文

从零开始:手把手教你为嵌入式设备编写一个简单的Power Supply驱动(基于Linux 4.19.111)

从零开始:手把手教你为嵌入式设备编写一个简单的Power Supply驱动(基于Linux 4.19.111)

在嵌入式Linux开发中,电源管理是一个至关重要的环节。无论是智能家居设备、工业控制器还是便携式医疗设备,稳定可靠的电源供应都是系统正常运行的基础。本文将带你深入Linux内核的Power Supply子系统,从零开始构建一个完整的电池驱动。

1. 理解Linux Power Supply子系统

Linux内核中的Power Supply子系统为各类电源设备提供了统一的抽象框架。这个框架的核心思想是将电源状态信息抽象为属性(properties),并通过sysfs接口向用户空间暴露这些信息。

1.1 子系统架构

Power Supply子系统主要由三个部分组成:

  • Core:位于drivers/power/power_supply_core.c,提供核心数据结构和公共逻辑
  • Sysfs:位于drivers/power/power_supply_sysfs.c,实现sysfs接口和uevent功能
  • LEDs:位于drivers/power/power_supply_leds.c,提供电源状态LED指示功能

典型的电源管理硬件通常包含两个主要组件:

  1. Fuel Gauge(电量计):监测电池电量、健康状态等信息
  2. Charger(充电管理):处理电源插拔检测和充放电过程

1.2 关键数据结构

开发Power Supply驱动需要理解三个核心数据结构:

struct power_supply_config { struct device_node *of_node; struct fwnode_handle *fwnode; void *drv_data; char **supplied_to; size_t num_supplicants; }; struct power_supply_desc { const char *name; enum power_supply_type type; enum power_supply_property *properties; size_t num_properties; int (*get_property)(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); int (*set_property)(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *val); /* 其他成员省略 */ }; struct power_supply { const struct power_supply_desc *desc; struct device dev; /* 其他成员省略 */ };

2. 硬件准备与数据手册分析

假设我们基于i.MX6UL平台开发,使用TI的BQ27425电量计芯片通过I2C接口通信。

2.1 硬件连接

典型的连接方式如下:

i.MX6UL引脚BQ27425引脚功能描述
I2C1_SCLSCLI2C时钟
I2C1_SDASDAI2C数据
GPIO1_IO02INT中断输出
VDD_3V3VCC电源(3.3V)
GNDGND地线

2.2 关键寄存器分析

从BQ27425数据手册中,我们需要关注以下寄存器:

寄存器地址名称描述访问权限
0x02Voltage电池电压(mV)只读
0x04AverageCurrent平均电流(mA)只读
0x06RelativeStateOfCharge剩余电量百分比(%)只读
0x08InternalTemperature内部温度(0.1°K)只读
0x0AFullChargeCapacity满充容量(mAh)只读

3. 驱动开发实战

3.1 初始化与注册

首先定义驱动所需的数据结构:

struct bq27425_data { struct i2c_client *client; struct power_supply *psy; struct delayed_work monitor_work; int voltage; int current; int capacity; int temp; };

然后实现驱动的probe函数:

static int bq27425_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct bq27425_data *data; struct power_supply_config psy_cfg = {}; int ret; /* 分配并初始化数据结构 */ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; >static enum power_supply_property bq27425_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TECHNOLOGY, }; static const struct power_supply_desc bq27425_psy_desc = { .name = "bq27425-battery", .type = POWER_SUPPLY_TYPE_BATTERY, .properties = bq27425_props, .num_properties = ARRAY_SIZE(bq27425_props), .get_property = bq27425_get_property, }; static int bq27425_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct bq27425_data *data = power_supply_get_drvdata(psy); switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: val->intval =>static int bq27425_read_word(struct i2c_client *client, u8 reg) { int ret; ret = i2c_smbus_read_word_data(client, reg); if (ret < 0) return ret; return le16_to_cpu(ret); } static void bq27425_update_data(struct bq27425_data *data) { >static void bq27425_monitor_work(struct work_struct *work) { struct bq27425_data *data = container_of(work, struct bq27425_data, monitor_work.work); /* 更新数据 */ bq27425_update_data(data); /* 通知子系统数据变化 */ power_supply_changed(data->psy); /* 重新调度工作队列,每5秒更新一次 */ schedule_delayed_work(&data->monitor_work, 5 * HZ); }

4. 设备树配置

在设备树中添加节点描述硬件连接:

&i2c1 { status = "okay"; bq27425: fuel-gauge@55 { compatible = "ti,bq27425"; reg = <0x55>; monitored-battery = <&battery>; }; }; battery: battery { compatible = "simple-battery"; voltage-min-design-microvolt = <3000000>; voltage-max-design-microvolt = <4200000>; energy-full-design-microwatt-hours = <10000000>; charge-full-design-microamp-hours = <2500000>; };

5. 测试与验证

驱动加载后,可以通过sysfs接口验证功能:

# 查看电源设备列表 ls /sys/class/power_supply/ # 查看电池属性 cat /sys/class/power_supply/bq27425-battery/voltage_now cat /sys/class/power_supply/bq27425-battery/capacity

也可以通过内核日志查看驱动运行状态:

dmesg | grep bq27425

6. 高级功能扩展

6.1 实现充电状态检测

扩展驱动以支持充电状态检测:

/* 在属性数组中添加 */ POWER_SUPPLY_PROP_STATUS, /* 在get_property中添加处理 */ case POWER_SUPPLY_PROP_STATUS: if (data->current > 0) /* 正电流表示充电 */ val->intval = POWER_SUPPLY_STATUS_CHARGING; else if (data->capacity >= 100) val->intval = POWER_SUPPLY_STATUS_FULL; else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break;

6.2 添加温度监控

实现温度监控和过热保护:

/* 在监控工作函数中添加检查 */ if (data->temp > 500) { /* 50°C */ dev_warn(&data->client->dev, "Battery temperature too high: %d\n", >/* 在监控工作函数中添加检查 */ if (data->capacity < 15) { power_supply_changed(data->psy); /* 触发uevent */ dev_info(&data->client->dev, "Low battery: %d%%\n",>
http://www.jsqmd.com/news/771272/

相关文章:

  • UniversalSplitScreen技术解析:多输入设备游戏分屏的终极解决方案
  • 如何用开源工具深度定制你的GameMaker游戏体验?
  • Steam经济增强工具终极指南:轻松管理你的Steam资产
  • 体验官方价折扣下模型调用成本管理的便捷性
  • 2026年学AI必看:从零到项目实战路线图,小白也能轻松掌握(收藏版)
  • AISMM模型评估可视化效能跃迁路径(工业级部署实测:准确率提升37.6%,耗时压缩至1/5)
  • 基于MCP协议连接AI与微博API:weibo-mcp项目实战指南
  • 不止于画图:用VESTA的‘Unit Cell Transformation’功能玩转超晶胞与结构转换
  • Flink 回撤流(Retract Stream)深度剖析:从底层原理到生产调优
  • 保姆级避坑指南:在VMware Workstation 17上搞定macOS Ventura虚拟机(附Intel/AMD配置差异)
  • Obsidian笔记内播放B站视频的终极指南:Media Extended插件完整教程
  • 技术揭秘:BthPS3如何破解Windows蓝牙与PS3控制器的兼容性难题
  • 2026年山西精准获客与GEO优化深度横评:手机号定向推广如何助力中小企业破局 - 优质企业观察收录
  • 避开FPGA实现SoftMax的坑:Verilog浮点运算的精度与资源权衡实战
  • AISMM不是选配模块,而是ESG披露的法定前置条件?,2026奇点大会透露欧盟AI Act 2.0过渡期仅剩138天
  • 终极指南:如何用SilentPatchBully彻底解决《恶霸鲁尼》Windows 10崩溃问题
  • 2026年天津搬家公司口碑推荐:日式搬家、单位搬家、企业搬迁、搬厂及厂房搬迁优选指南 - 海棠依旧大
  • 观察使用 Taotoken 后月度 AI 模型 API 开支的清晰度与预测性变化
  • SpeedAI写作降重助手
  • C++ 虚函数全解:从基础原理到高级特性(多重继承 / 菱形继承 / CRTP 对比)
  • 兰州高考复读学校排行 合规办学与提分实力盘点 - 奔跑123
  • 在Linux上体验完整Android:Waydroid容器技术终极指南
  • 2026年郑州铝单板选购指南:郑州方舟建材与4大品牌深度横评 - 精选优质企业推荐官
  • 对比直接使用厂商 API 与通过 Taotoken 聚合调用的接入复杂度差异
  • Sibyl:基于LLM的代码语义分析工具,提升代码理解与维护效率
  • 从家庭影院到座舱:聊聊7.1.4声道在车载音响里的那些事儿(附Dolby Atmos实战)
  • 2026年郑州铝单板与全国幕墙装饰材料深度选购指南:5大品牌横评+官方直达 - 精选优质企业推荐官
  • 屏幕实时翻译终极指南:如何用Translumo打破游戏语言障碍
  • 如何快速掌握数据流同步技术:Lab Streaming Layer完整使用指南
  • 别再混淆x86和x64了!用树莓派和旧电脑实测讲解内存与性能的真实差距