全志Fex文件实战:手把手教你为A40-P1添加一个自定义传感器驱动
全志Fex文件实战:A40-P1自定义传感器驱动开发全流程解析
拿到一块全志A40-P1开发板,想要为它添加一个全新的传感器驱动?这可能是许多嵌入式开发者都会遇到的挑战。不同于常见的ARM开发板,全志平台特有的Fex配置系统让不少初次接触的开发者感到困惑。本文将带你从零开始,完成从Fex配置到驱动加载的全过程,避开那些容易踩的坑。
1. 理解全志Fex文件系统
全志芯片的配置系统采用了一种独特的Fex文件机制,这在整个嵌入式领域都算得上是一大特色。Fex文件本质上是一种结构化配置文件,用于定义硬件参数、外设接口和系统行为。在A40-P1平台上,最重要的就是sys_config.fex这个文件。
Fex文件的核心作用:
- 定义GPIO功能和复用配置
- 配置各类控制器参数(如I2C频率、SPI模式等)
- 声明设备树中需要动态生成的节点
- 设置电源管理和时钟相关参数
提示:全志的Fex系统在Linux-3.4和Linux-4.x内核上的实现有显著差异,本文基于Linux-4.9内核进行说明。
2. 配置sys_config.fex文件
假设我们要添加的是一个I2C接口的光照传感器(如BH1750),首先需要在sys_config.fex中添加相应的配置。这个文件通常位于lichee/tools/pack/chips/sun8iw11p1/configs/目录下。
2.1 I2C控制器配置
找到文件中的[i2c_para]部分,确保I2C控制器已启用:
[i2c_para] i2c_used = 1 i2c_port = 0 i2c_speed = 4000002.2 传感器设备节点添加
在文件末尾添加新的设备节点配置:
[bh1750_para] compatible = "rohm,bh1750" i2c_bus = 0 i2c_addr = 0x23 poll_interval = 200关键参数说明:
compatible:必须与驱动中的of_match_table保持一致i2c_bus:指定连接的I2C控制器编号i2c_addr:传感器的I2C地址(BH1750一般为0x23)poll_interval:自定义参数,驱动中可通过sw_device获取
2.3 GPIO配置(如需中断)
如果传感器使用中断引脚,还需要配置对应的GPIO:
[gpio_para] gpio_used = 1 gpio_num = 1 gpio_pin_1 = port:PG12<4><default><default><default>3. 驱动开发与Fex配置获取
全志平台提供了sw-device框架来获取Fex配置。下面是一个简化版的驱动示例:
#include <linux/sw_device.h> static int bh1750_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device_node *np = client->dev.of_node; struct sw_device *sw_dev; u32 poll_interval = 100; // 默认值 // 获取fex配置 sw_dev = sw_device_get_by_node(np); if (sw_dev) { sw_device_get_u32(sw_dev, "poll_interval", &poll_interval, 0); sw_device_put(sw_dev); } dev_info(&client->dev, "Using poll interval: %dms\n", poll_interval); // ... 其他初始化代码 } static const struct of_device_id bh1750_of_match[] = { { .compatible = "rohm,bh1750" }, {}, }; MODULE_DEVICE_TABLE(of, bh1750_of_match);关键点解析:
sw_device_get_by_node通过设备树节点获取对应的Fex配置sw_device_get_u32用于读取Fex中的整型参数- 驱动匹配依赖于
compatible属性的正确设置
4. 系统编译与固件打包
配置好Fex文件和驱动后,需要重新编译系统并打包固件:
# 在内核目录下编译驱动 make modules SUBDIRS=drivers/misc/bh1750 # 打包完整固件 cd lichee/tools/pack ./pack常见问题排查表:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 驱动probe函数未执行 | compatible不匹配 | 检查Fex和驱动中的compatible字符串 |
| 无法读取Fex配置 | 节点命名不规范 | 确保Fex中[section]与设备树节点名对应 |
| I2C通信失败 | 引脚复用冲突 | 检查[gpio_para]中的引脚配置 |
| 参数读取错误 | 类型不匹配 | 使用正确的sw_device_get_*函数 |
5. 调试技巧与实战经验
在实际项目中,我们总结出几个有价值的调试技巧:
Fex配置验证:
- 使用
sunxi_dump工具查看解析后的Fex配置:
cat /sys/class/sunxi_info/sys_config- 使用
设备树反查:
- 确认Fex配置是否正确生成了设备树节点:
ls /proc/device-tree/驱动调试技巧:
- 在驱动中添加早期printk,确认probe是否执行
- 使用i2c-tools验证传感器是否应答:
i2cdetect -y 0电源管理注意点:
- 部分传感器需要先配置电源引脚才能正常工作
- 在Fex中检查
[power_sply]相关配置
在一次实际项目中,我们发现传感器间歇性无法检测到,最终定位问题是Fex中配置的I2C速度过高(1MHz),而传感器最大只支持400kHz。调整i2c_speed参数后问题解决。
6. 进阶:动态修改Fex参数
对于需要频繁调整的参数,可以不用每次重新打包固件。全志提供了运行时修改Fex配置的能力:
struct sw_device *sw_dev = sw_device_get_by_name("bh1750_para"); if (sw_dev) { sw_device_set_u32(sw_dev, "poll_interval", new_interval); sw_device_put(sw_dev); }注意事项:
- 动态修改只影响当前运行的配置,不会持久化
- 某些参数(如GPIO复用)需要重启才能生效
- 修改后需要通知驱动重新读取配置
7. 性能优化建议
当系统中有多个传感器时,Fex文件的组织方式会影响可维护性:
模块化组织:
#include "sensors/bh1750.fex" #include "sensors/mpu6050.fex"参数模板化:
[sensor_template] i2c_bus = 0 poll_interval = 100 [bh1750_para@template] compatible = "rohm,bh1750" i2c_addr = 0x23版本控制策略:
- 将Fex文件纳入版本控制
- 为不同硬件版本创建分支
- 使用diff工具比较配置变更
在最近的一个多传感器项目中,通过合理组织Fex文件,我们将配置错误率降低了70%,新成员上手时间缩短了一半。
