全志Fex文件实战:手把手教你为A40-P1添加一个自定义传感器驱动

📅 2026/7/13 13:09:10 👁️ 阅读次数 📝 编程学习
全志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 = 400000

2.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);

关键点解析

  1. sw_device_get_by_node通过设备树节点获取对应的Fex配置
  2. sw_device_get_u32用于读取Fex中的整型参数
  3. 驱动匹配依赖于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. 调试技巧与实战经验

在实际项目中,我们总结出几个有价值的调试技巧:

  1. Fex配置验证

    • 使用sunxi_dump工具查看解析后的Fex配置:
    cat /sys/class/sunxi_info/sys_config
  2. 设备树反查

    • 确认Fex配置是否正确生成了设备树节点:
    ls /proc/device-tree/
  3. 驱动调试技巧

    • 在驱动中添加早期printk,确认probe是否执行
    • 使用i2c-tools验证传感器是否应答:
    i2cdetect -y 0
  4. 电源管理注意点

    • 部分传感器需要先配置电源引脚才能正常工作
    • 在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文件的组织方式会影响可维护性:

  1. 模块化组织

    #include "sensors/bh1750.fex" #include "sensors/mpu6050.fex"
  2. 参数模板化

    [sensor_template] i2c_bus = 0 poll_interval = 100 [bh1750_para@template] compatible = "rohm,bh1750" i2c_addr = 0x23
  3. 版本控制策略

    • 将Fex文件纳入版本控制
    • 为不同硬件版本创建分支
    • 使用diff工具比较配置变更

在最近的一个多传感器项目中,通过合理组织Fex文件,我们将配置错误率降低了70%,新成员上手时间缩短了一半。