外观
触摸驱动开发
2025-09-19
本章将介绍 Ruiching 平台触摸屏驱动的开发流程与技术要点。通过本章学习,将能够独立完成从设备树配置到驱动注册的完整触摸屏驱动开发流程,并深入理解触摸框架的核心数据结构和运行机制。完整的理解触摸框架和触摸驱动的配合,包含以下关键环节:
驱动开发流程掌握
- 理解并掌握 Ruiching 平台触摸屏驱动的完整开发流程:
- 从设备树匹配与驱动注册
- 设备探测 (probe) 过程实现
- 关键操作函数 (ops) 的开发
核心数据结构运用
- 深入理解触摸框架定义的关键数据结构:
- rt_touch_info(设备属性描述)
- rt_touch_config(设备配置)
- rt_touch_data(触摸数据传递)
- rt_touch_ops(驱动功能实现)
- rt_touch_device(设备抽象)
- 能够熟练运用这些数据结构进行驱动开发
驱动注册与系统集成
- 掌握使用 rt_hw_touch_register 接口
- 实现驱动在系统中的成功注册
- 确保驱动对上层应用可见可用
触摸驱动开发步骤
本示例是针对 Goodix GT9xx 系列触摸芯片对接触摸框架的实现过程,完整代码已开源(gt9xx.c),请对照代码查看,以下是开发触摸驱动流程的解析。
定义设备树匹配表
在 Ruiching 平台驱动开发时,设备树是描述硬件配置的重要机制,它通过节点属性定义硬件设备的特性、地址、中断等信息。驱动定义设备树匹配表(如gt_i2c_ofw_ids[]),以便内核在启动时能够将驱动与设备树中的对应硬件节点正确绑定。
代码实现示例
驱动中定义设备树匹配表:
static const struct rt_ofw_node_id gt_i2c_ofw_ids[] =
{
{ .compatible = "goodix,gt9xx" }, /* 匹配设备树中 compatible 属性为 "goodix,gt9xx" 的节点 */
{ /* sentinel */ } /* 结束标记 */
};设备树中对应的节点定义示例:
goodix_ts: goodix_ts@14 {
status = "okay";
compatible = "goodix,gt9xx"; /* 必须与驱动中的 compatible 字符串完全匹配 */
...
};定义 Ruiching 平台驱动结构体
在 Ruiching 平台驱动框架中,rt_platform_driver 结构体是驱动与内核交互的核心载体,主要承担以下关键作用:
驱动身份标识
通过
.name字段在系统中唯一标识该驱动,当设备树匹配失败时,内核可通过名称进行备选匹配。硬件探测入口
.probe函数指针定义了设备初始化的标准入口,系统在匹配成功后自动调用,完成驱动初始化。设备树匹配表
.ids字段关联预先定义的设备树匹配表,使驱动能自动绑定到正确的硬件节点。
代码实现示例
驱动中定义驱动结构体:
static struct rt_platform_driver gt9xx_driver =
{
.name = "gt9xx", /* 驱动名称标识符 */
.ids = gt_i2c_ofw_ids, /* 指向设备树匹配表 */
.probe = gt9xx_probe, /* 设备探测回调函数(驱动初始化入口) */
};匹配优先级:
- 首先尝试通过设备树 compatible 属性匹配
- 若无设备树匹配,则尝试通过驱动名称匹配
驱动注册
系统启动时,扫描设备树后,系统会注册设备,同时驱动也需要注册到系统中,以完成驱动与设备的匹配。驱动通过特定方式注册到系统中。
代码实现示例
static int gt9xx_register(void)
{
/* 将驱动注册到平台驱动框架 */
return rt_platform_driver_register(>9xx_driver);
}
/* 系统初始化阶段自动注册驱动 */
INIT_DEVICE_EXPORT(gt9xx_register);注册流程说明:
- 系统启动时通过
INIT_DEVICE_EXPORT宏自动调用gt9xx_register() - 注册函数将驱动结构体添加到平台总线驱动链表
- 完成注册后,系统会自动进行设备-驱动匹配并调用 probe 函数
实现 gt9xx_probe() 函数
gt9xx_probe函数是设备驱动中的关键初始化函数。它负责在设备被探测到时初始化设备的功能和属性,确保设备正确工作,probe 函数需要做到以下几点:
- 设备树解析:
- 在该函数中,读取设备树信息,帮助驱动了解硬件的配置,让驱动能够根据正确的硬件参数进行初始化和操作。
- 资源获取:
- 函数负责获取硬件所需的资源,如 I2C 总线的句柄、GPIO 引脚等,并进行相应的配置。
- 配置中断:
- 函数中设置中断引脚和模式。
- 注册设备:
- 通过
rt_hw_touch_register()函数将设备注册到 Ruiching 中,使得系统能够识别并使用该设备。
- 通过
代码实现示例
static rt_err_t gt9xx_probe(struct rt_platform_device *pdev)
{
...
/* 读取设备树节点 reg 属性获取 I2C 从设备地址 */
/* 通过设备树别名获取 I2C 总线设备,并打开 */
...
/* 解析设备树节点配置(如中断引脚、复位引脚等) */
gtp_parse_dt(np);
...
/* 本示例是以 GPIO 为中断引脚,所以框架需要知道触发中断的引脚号和模式,以便框架绑定引脚中断,所以此处填充 struct rt_touch_config 结构体 */
cfg.irq_pin.pin = gtp_int_gpio;
/* 根据设备树描述,设定响应的中断引脚模式 */
cfg.irq_pin.mode = PIN_MODE_INPUT_PULLUP; (PIN_MODE_INPUT_PULLDOWN)
/* 描述设备静态属性 填充 struct rt_touch_info 结构体*/
ts->device.info.type = RT_TOUCH_TYPE_CAPACITANCE;
ts->device.info.vendor = RT_TOUCH_VENDOR_GT;
rt_memcpy(&ts->device.config, &cfg, sizeof(struct rt_touch_config));
/* 赋值 ops */
ts->device.ops = >9xxtouch_ops;
/* 注册touch 设备 */
ret = rt_hw_touch_register(
&ts->device, "touch", RT_DEVICE_FLAG_INT_RX, RT_NULL);
}实现 gt9xxtouch_ops
框架需要驱动实现 touch_readpoint和touch_control两个函数,以便能够实时获取用户的触控信息,实现流畅的交互。这两个函数使框架能够在运行时了解设备的具体状态,从而进行适当的控制和配置。
gt9xx_read_point
负责从触摸设备读取当前的触摸点坐标和状态。
static rt_size_t gt9xx_read_point(
struct rt_touch_device *touch, void *buf, rt_size_t read_num)
{
...
/* 读取状态寄存器,查看当前是否有被触摸的点 */
/* point status register */
cmd[0] = (rt_uint8_t)((GTP_READ_COOR_ADDR >> 8) & 0xFF);
cmd[1] = (rt_uint8_t)(GTP_READ_COOR_ADDR & 0xFF);
if (gtp_i2c_read(ts, cmd, GTP_ADDR_LENGTH + 1) < 0)
...
cmd[0] = (rt_uint8_t)((GTP_REG_POINT1 >> 8) & 0xFF);
cmd[1] = (rt_uint8_t)(GTP_REG_POINT1 & 0xFF);
/* 将读取到的触摸数据填充到传入的 buf,类型为 rt_touch_data */
/* 它能够让上层应用获取触摸数据,从而进行响应,比如更新UI。 */
if (gtp_i2c_read(ts, cmd, (read_num * 8) + GTP_ADDR_LENGTH) < 0)
...
/* 函数返回读取的点数量,使得调用者能够知道成功读取了多少数据 */
return read_num;
}gt9xx_control
实现对触摸设备的控制命令,如获取设备 ID 和基本信息。其余命令请看 2.4.1 触摸控制命令支持详解
static rt_err_t gt9xx_control(struct rt_touch_device *touch, int cmd, void *arg)
{
/* 实现控制触摸设备的命令 */
switch (cmd)
{
case RT_TOUCH_CTRL_GET_ID: gtxx_get_product_id(ts, arg); break;
case RT_TOUCH_CTRL_GET_INFO: gtxx_get_info(ts, arg); break;
default: break;
}
return RT_EOK;
}流程图下图所示:
核心数据结构详解
在触摸驱动的开发步骤中,理解设备的相关结构至关重要。接下来,将深入探讨触摸驱动的核心数据结构,以便更好地掌握其实现机制和功能。这一部分将详细介绍关键数据结构及其在驱动中的应用。
设备信息结构 (rt_touch_info)
描述触摸设备的基本属性,包括设备类型、厂商、支持的触摸点数量以及坐标范围。了解这些特性可以在驱动初始化时准确配置设备。
struct rt_touch_info
{
rt_uint8_t type; /* The touch type */
#define RT_TOUCH_TYPE_NONE (0) /* touch ic none */
#define RT_TOUCH_TYPE_CAPACITANCE (1) /* capacitance ic */
#define RT_TOUCH_TYPE_RESISTANCE (2) /* resistance ic */
rt_uint8_t vendor; /* Vendor of touchs */
#define RT_TOUCH_VENDOR_UNKNOWN (0) /* unknown */
#define RT_TOUCH_VENDOR_GT (1) /* GTxx series */
#define RT_TOUCH_VENDOR_FT (2) /* FTxx series */
rt_uint8_t point_num; /* Support point num */
rt_int32_t range_x; /* X coordinate range */
rt_int32_t range_y; /* Y coordinate range */
};| 字段 | 说明 | 备注 |
|---|---|---|
| type | 设备类型 | 电容屏 RT_TOUCH_TYPE_CAPACITANCE/电阻屏 RT_TOUCH_TYPE_RESISTANCE |
| vendor | 厂商标识 | 如 Goodix GT、FocalTech FT |
| point_num | 最大支持触摸点数 | 单点/多点触摸 |
| range_x/range_y | 坐标范围 |
设备配置结构 (rt_touch_config)
设备配置结构体用于存储设备在运行的配置信息,设备驱动在初始化时可以直接填充该结构体,从而集中管理与设备相关的配置,避免在驱动代码的多个部分重复定义和配置。
struct rt_touch_config
{
#ifdef RT_TOUCH_PIN_IRQ
struct rt_device_pin_mode
irq_pin; /* Interrupt pin, The purpose of this pin is to notification read data */
#endif
char *dev_name; /* The name of the communication device */
void *user_data;
};| 字段 | 说明 | 备注 |
|---|---|---|
| irq_pin | 设置中断引脚 | 用于通知数据就绪 |
| dev_name | 底层通信设备名 | 如 "i2c1" |
| user_data | 扩展数据 |
触摸点数据结构 (rt_touch_data)
描述触摸点的实时数据,确保触摸事件的准确识别和响应。
struct rt_touch_data
{
rt_uint8_t event; /* The touch event of the data */
#define RT_TOUCH_EVENT_NONE (0) /* Touch none */
#define RT_TOUCH_EVENT_UP (1) /* Touch up event */
#define RT_TOUCH_EVENT_DOWN (2) /* Touch down event */
#define RT_TOUCH_EVENT_MOVE (3) /* Touch move event */
rt_uint8_t track_id; /* Track id of point */
rt_uint8_t width; /* Point of width */
rt_uint16_t x_coordinate; /* Point of x coordinate */
rt_uint16_t y_coordinate; /* Point of y coordinate */
rt_tick_t timestamp; /* The timestamp when the data was received */
};| 字段 | 说明 | 备注 |
|---|---|---|
| event | 事件类型 | RT_TOUCH_EVENT_DOWN(按下) RT_TOUCH_EVENT_UP(抬起) RT_TOUCH_EVENT_MOVE(移动) |
| track_id | 触点唯一标识 | 用于多点触摸追踪 |
| x_coordinate/y_coordinate | 坐标 | 单点/多点触摸 |
| timestamp | 数据采集时间戳 |
操作函数集 (rt_touch_ops)
操作函数字段为驱动程序提供了必要的接口,使其能够读取触摸数据并进行相应的控制,以确保触摸设备的正常运作和交互响应。
struct rt_touch_ops
{
rt_size_t (*touch_readpoint)(
struct rt_touch_device *touch, void *buf, rt_size_t touch_num);
rt_err_t (*touch_control)(
struct rt_touch_device *touch, int cmd, void *arg);
};| 字段 | 说明 | 备注 |
|---|---|---|
| touch_readpoint | 从硬件读取原始数据并转换为 rt_touch_data 结构 | buf:输出缓冲区(存放 rt_touch_data 数组)touch_num:请求读取的点数(需返回实际点数) |
| touch_control | 执行控制命令 | cmd:命令字(如 RT_TOUCH_CTRL_CALIBRATE)arg:命令参数 |
触摸控制命令支持详解
| 命令 | 功能 | 配合 control 的 arg 参数 |
|---|---|---|
| RT_TOUCH_CTRL_GET_ID | 获取触摸设备的 ID(芯片型号或设备标识符) | 指向存储设备 ID 的缓冲区指针(通常为 rt_uint8_t* 或 rt_uint16_t*) |
| RT_TOUCH_CTRL_GET_INFO | 获取触摸设备的基本信息 | 指向 struct rt_touch_info 结构体的指针 |
| RT_TOUCH_CTRL_SET_MODE | 设置触摸设备的工作模式 | 指向工作模式值的指针 RT_TOUCH_MODE_POLLING:轮询模式(需主动读取数据) RT_TOUCH_MODE_INT:中断模式(事件驱动) |
| RT_TOUCH_CTRL_SET_X_RANGE | 设置 X 坐标范围(分辨率) | 指向 X 轴最大坐标值的指针 |
| RT_TOUCH_CTRL_SET_Y_RANGE | 设置 Y 坐标范围(分辨率) | 指向 Y 轴最大坐标值的指针 |
| RT_TOUCH_CTRL_SET_X_TO_Y | 交换 X 和 Y 坐标 | 指向布尔值的指针(rt_bool_t*) |
| RT_TOUCH_CTRL_DISABLE_INT | 禁用触摸中断 | RT_NULL |
| RT_TOUCH_CTRL_ENABLE_INT | 启用触摸中断 | RT_NULL |
| RT_TOUCH_CTRL_POWER_ON | 开启触摸设备电源 | RT_NULL |
| RT_TOUCH_CTRL_POWER_OFF | 关闭触摸设备电源 | RT_NULL |
| RT_TOUCH_CTRL_GET_STATUS | 获取触摸设备电源状态 | 指向状态变量的指针 |
触摸设备结构体 (rt_touch_device)
触摸设备的核心控制块,负责管理设备的基本信息和操作。
struct rt_touch_device
{
struct rt_device parent; /* The standard device */
struct rt_touch_info info; /* The touch info data */
struct rt_touch_config config; /* The touch config data */
const struct rt_touch_ops *ops; /* The touch ops */
rt_err_t (*irq_handle)(rt_touch_t
touch); /* Called when an interrupt is generated, registered by the driver */
};| 字段 | 说明 | 备注 |
|---|---|---|
| parent | 继承设备模型对象 | 支持 open/read/control 等标准操作 |
| touch_control | 执行控制命令 | |
| info | 设备属性 | |
| config | 设备配置 | |
| ops | 指向底层驱动实现的操作函数 | |
| irq_handle | 中断服务函数 | 由驱动注册 |
触摸设备注册函数
在对接触摸驱动时,驱动需要将设备注册到触摸框架中,以便上层应用访问触摸设备。
rt_hw_touch_register()
int rt_hw_touch_register(
rt_touch_t touch,
const char *name,
rt_uint32_t flag,
void *data);功能描述:
此函数用于向 Ruiching 触摸框架注册一个触摸设备。它将触摸设备连接到设备管理系统,使应用程序可以通过标准设备接口访问触摸功能。
| 字段 | 说明 |
|---|---|
| touch | 指向触摸设备结构体的指针 |
| name | 设备名称(如 "touch"),用于查找设备 |
| flag | 设备标志位 |
| data | 用户自定义数据指针,会存储在设备结构体中 |
