全志Fex文件配置实战:从sys_config.fex到驱动加载的深度解析
拿到一块全志开发板,第一件事往往不是写代码,而是对着原理图修改那些神秘的.fex文件。记得我第一次接触A40i开发板时,花了整整三天才让触摸屏正常工作——不是因为代码问题,而是ctp_power_ldo这个参数设错了电压值。本文将带你深入全志平台特有的配置体系,从文本文件到内核驱动的完整链路,解决"为什么配置了Fex设备还是不工作"这个经典难题。
1. 全志Fex文件体系解密
全志芯片的配置系统独树一帜,在主流Linux都采用设备树(DTS)的今天,它依然保留着从功能机时代延续下来的.fex文本配置方式。这个设计让很多从其他平台转过来的开发者感到困惑,但了解其设计逻辑后,你会发现这套系统在快速硬件适配方面有着独特的优势。
sys_config.fex是整个配置系统的核心,它采用经典的INI文件格式,被划分为多个节(section),每个节对应一类硬件或子系统配置。与设备树需要重新编译不同,修改Fex文件后只需重新打包boot0或boot_package即可生效,这在开发调试阶段非常高效。
几个关键文件的作用:
sys_config.fex:主配置文件,定义所有硬件参数script.bin:由fex2bin工具生成的二进制配置sys_config.h:内核头文件,包含配置项的宏定义
注意:全志Tina Linux的较新版本已开始支持设备树,但大量存量项目仍在使用Fex配置方式
2. 触摸屏(TP)配置实战
以最常见的Goodix GT911触摸屏为例,让我们看看如何从Fex文件一路追踪到驱动加载。假设我们的硬件连接如下:
- 电源:使用PMIC的LDO3,电压2.8V
- I2C总线:I2C2
- 中断引脚:PH9
- 复位引脚:PH10
对应的Fex配置应为:
[ctp] ctp_used = 1 ctp_name = "gt911" ctp_twi_id = 2 ctp_twi_addr = 0x5d ctp_screen_max_x = 800 ctp_screen_max_y = 480 ctp_revert_x_flag = 0 ctp_revert_y_flag = 0 ctp_exchange_x_y_flag = 0 ctp_int_port = port:PH09<6><default><default><default> ctp_wakeup_port = port:PH10<1><default><default><default> ctp_power_ldo = "vcc-ctp"常见问题排查表:
| 现象 | 可能原因 | 检查方法 |
|---|---|---|
| 触摸无反应 | 电源未正确配置 | 测量TP供电电压 |
| I2C通信失败 | 总线号或地址错误 | i2cdetect扫描设备 |
| 坐标错乱 | 屏幕参数不匹配 | 核对ctp_screen_max_x/y |
| 中断不触发 | GPIO配置错误 | 检查cat /proc/interrupts |
驱动加载的关键在于compatible匹配,全志平台通常会在sw-device.c中处理Fex配置:
static const struct of_device_id sunxi_ctp_of_match[] = { { .compatible = "allwinner,ctp_para", }, {} };当内核检测到这个匹配时,会调用ctp_init函数解析Fex配置并注册输入设备。
3. 加速度传感器(GSensor)配置详解
运动传感器配置相比触摸屏更复杂,因为涉及坐标轴映射和滤波参数。以Bosch BMI160为例,典型配置如下:
[gsensor] gsensor_used = 1 gsensor_name = "bmi160" gsensor_twi_id = 2 gsensor_twi_addr = 0x68 gsensor_int1 = port:PH11<6><default><default><default> gsensor_direction = 6 gsensor_range = <2000>其中gsensor_direction这个参数最让人困惑,它定义了传感器坐标系与设备坐标系的映射关系。全志平台使用以下编码规则:
方向值计算表:
| 轴映射 | X符号 | Y符号 | Z符号 | 计算值 |
|---|---|---|---|---|
| X→X | +1 | 0 | 0 | 1 |
| X→-X | -1 | 0 | 0 | 2 |
| X→Y | 0 | +1 | 0 | 3 |
| X→-Y | 0 | -1 | 0 | 4 |
| ... | ... | ... | ... | ... |
方向值=1+(X符号×1)+(Y符号×3)+(Z符号×9)
驱动代码中,这个值会在bmi160_parse_dt函数(实际是解析Fex)中被转换为标准的mount_matrix:
static int bmi160_set_mount_matrix(struct device *dev, int orientation) { static const int matrix_map[] = { [1] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }, // 0° [6] = { 0,-1, 0, 1, 0, 0, 0, 0, 1 }, // 90° // ...其他映射关系 }; if (orientation < 1 || orientation >= ARRAY_SIZE(matrix_map)) return -EINVAL; return iio_device_set_mount_matrix(dev, matrix_map[orientation]); }4. 驱动加载全流程剖析
理解Fex配置如何转化为驱动参数是关键。全志平台使用了一套独特的机制:
配置编译阶段:
fex2bin sys_config.fex script.bin mksunxiboot boot_package.cfg boot_package.fex内核初始化阶段:
sw-device.c中的sunxi_parse_para函数解析script.bin- 根据
[product]节的machine值选择设备配置 - 为每个外设创建platform_device并填充资源
驱动探测阶段:
static int gt911_probe(struct i2c_client *client) { struct device_node *np = client->dev.of_node; struct gt911_data *ts; // 从Fex转换来的参数存储在of_node中 ts->irq_gpio = of_get_named_gpio(np, "ctp_int_port", 0); ts->reset_gpio = of_get_named_gpio(np, "ctp_wakeup_port", 0); // 初始化输入设备 input_dev->name = "gt911_touchscreen"; __set_bit(EV_ABS, input_dev->evbit); input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, screen_max_x, 0, 0); // ... }
调试技巧:
- 检查
/sys/class/input/input*/name确认设备已注册 - 使用
evtest工具验证输入事件 - 通过
i2c-tools包中的i2cdetect和i2cget验证通信
5. 高级调试与性能优化
当基础功能正常工作后,可能需要进一步优化:
电源管理配置示例:
[ctp_power] ctp_power_vol = 2800 ctp_power_io = port:PL03<1><default><default><default> gpio_power_enable = 1 power_on_delay = 100 power_off_delay = 200I2C时序调整:
[twi2] twi2_scl = port:PH04<3><default><default><default> twi2_sda = port:PH05<3><default><default><default> twi2_sclk = 400000 twi2_rise_time_ns = 300 twi2_fall_time_ns = 100中断性能优化:
- 在
/proc/interrupts中确认中断触发次数 - 如果需要降低CPU负载,可以配置中断共享:
[ctp] ctp_irq_mode = 1 # 0=轮询 1=中断 2=低电平触发 ctp_irq_wakeup = 1
在最近的一个车载项目中,我们发现触摸屏在低温下响应迟缓,最终通过调整Fex中的滤波参数解决了问题:
[ctp_para] ctp_filter_type = 2 ctp_filter_level = 5 ctp_filter_sample = 3