ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

FPGA工程师学Linux:Zynq平台7寸触摸屏驱动全流程解析

FPGA工程师学Linux:Zynq平台7寸触摸屏驱动全流程解析 1. 先认清一个反直觉的事实触摸屏驱动不是FPGA的主业1.1 Zynq平台把FPGA工程师推到了Linux门口提到FPGA开发很多人的第一反应是Verilog时序、Vivado综合、引脚约束再进阶一点就是MIPI、LVDS、PCIe这类高速接口。这些确实是FPGA的舒适区。但黑金AX7Z020这类Zynq SoC出现后情况发生了很有意思的变化芯片内部一半是双核ARM Cortex-A9处理器一半是标准的7系列FPGA逻辑两者用AXI总线连起来。当你拿到配套的7寸触摸屏时这颗屏的触摸芯片往往挂在PS端的I2C控制器上而不是PL端。这就带来一个关键选择触摸屏的读取逻辑到底放在PL里用状态机实现还是放到PS端用Linux驱动实现我从一开始就强烈建议选后者不是因为我偏爱Linux而是从工程角度算完账就会发现用FPGA逻辑去做触摸解析是一件非常不划算的事情。触摸屏的数据量极小——一个触摸事件无非就是X坐标、Y坐标、压力值、触点ID一次上报几十个字节一秒钟几百次上报这点数据量对硬件吞吐来说连九牛一毛都算不上。但触摸IC的协议却比较啰嗦比如GT911上电要做时序握手要读写配置寄存器还要响应中断、做坐标滤波用状态机硬啃这些逻辑既浪费LUT资源又会拖延整个项目的验证周期。反过来看Linux内核的input子系统对触摸屏的支持已经非常成熟驱动框架现成设备树写几个节点就能把硬件信息告诉内核剩下的读寄存器、上报事件、处理多点触摸全由内核帮你搞定。FPGA侧真正应该操心的是高带宽、高并行、时序敏感的任务比如把7寸屏的RGB显示数据流处理好或者做图像采集、缩放、ISP处理这些才是PL资源的用武之地。1.2 黑金云课堂这条技术线的逻辑黑金云课堂把FPGA技术教程和Linux开发放在一起其实是把Zynq开发者的两条能力线拧成了一股绳一条线是FPGA逻辑设计能力另一条线是基于Linux的系统开发能力。单独会其中任何一条在Zynq上都做不出完整产品。你就算把PL侧的显示时序做得再完美如果PS侧没有人能把触摸屏驱动跑通这个带交互界面的设备依然是一块会亮的哑巴屏。亲眼见过很多FPGA工程师拿到Zynq板子后启动Linux没问题但一旦要新增一个外设就头疼。他们对内核编译、设备树修改、驱动模块加载这套流程不熟遇到问题宁可在PL里绕路也不愿意去碰内核。这种状态短期能撑长期做项目一定吃亏。因为Zynq的SoC优势恰恰是硬核CPU可编程逻辑协同PS侧每多接管一个外设PL侧就少一分负担系统的整体稳定性和可维护性都会好很多。所以这篇文章就是按照黑金云课堂这条主线把7寸触摸屏驱动从硬件链路到设备树配置、再到驱动编译和实际调试的完整路径过一遍。适合两类读者一类是长期写FPGA逻辑、想真正开始玩Zynq Linux的人另一类是已经写过一些Linux驱动、但没在FPGASoC工程里完整走通流程的人。整个过程中我不打算跳过任何一个看起来简单的环节因为很多坑恰恰藏在那些简单里。2. 触摸屏硬件链路拆解从手指按压到内核事件2.1 三层结构传感器面板、控制IC与主机接口一块7寸触摸屏模块从物理结构上可以拆成三个层次想清楚这三个层次再去看驱动整个逻辑会顺很多。最底层是传感器面板。电容屏的面板内部有一层氧化铟锡透明导电层蚀刻成行列交叉的电极矩阵。手指靠近时手指与电极之间形成耦合电容导致该交叉点的电容值发生变化。触摸控制IC通过不断扫描这些交叉点的电容变化就能判断出哪个区域被触碰到。电阻屏的原理更古老也更简单两层导电薄膜中间用微小的绝缘点隔开按压时上下两层短路通过分压关系计算位置。红外触摸屏则完全绕开了面板触控在屏幕边框四周排列红外发射管和接收管形成一个横竖交叉的红外线矩阵手指挡住某条红外线时对应的行列坐标就被记录下来。中间层是控制IC。这颗芯片负责把传感器面板的模拟信号转换成数字坐标同时做滤波、去抖、多点追踪这些脏活累活。对Linux驱动来说控制IC就是一个可以通过I2C或USB接口访问的外设。电容屏常用GT911、FT5x06这类芯片电阻屏常见TSC2007红外触摸框常用Touchkit这类方案。不同的控制IC对应不同的通信协议驱动代码自然也不一样。最上层是主机接口。控制IC和处理器之间的物理连接方式决定了驱动怎么写。GT911通过I2C接口输出坐标数据Touchkit红外触摸框多半是USB接口插上后内核自动枚举成一个标准USB HID触摸设备连专属驱动有时候都不需要直接用内核的usbtouchscreen或hid-multitouch驱动即可。部分工控触摸屏还会用串口输出坐标协议那就需要额外的串口驱动和协议解析层。搞清楚这三层结构后你再看内核里的触摸屏驱动就会觉得非常亲切。驱动做的事情无非是通过接口读取IC中的坐标数据做必要的格式转换然后交给内核input子系统上报给应用层。中间没有玄学。2.2 黑金7寸屏最常见的两种触摸配置黑金的Zynq开发板搭配的7寸屏我接触过的常见配置大致分两类。第一类是RGB接口的LCD面板触摸部分通过I2C与PS端连接触摸IC常见GT911或GT811系列。这类屏幕显示数据和触摸数据是分离的显示走RGB并行总线触摸走I2C。这也是7寸屏最常见的架构。第二类是USB接口的触摸配置屏幕本身可能还是RGB/LVDS显示但触摸框做成独立USB设备插到开发板的USB Host口就能用典型代表就是Touchkit红外触摸屏。这两种配置在Linux驱动上走的是完全不同的路径。GT911属于I2C触摸屏设备需要在设备树里显式声明I2C子节点让内核知道哪个I2C控制器上挂了什么设备、用哪个中断引脚。Touchkit属于USB HID设备设备树里不需要为它建节点USB总线自己会做枚举内核里的usbtouchscreen驱动根据VID/PID识别并绑定。很多第一次做触摸屏驱动的人容易在这一点上绕晕明明文档里写了要加设备树节点换了USB触摸屏后发现根本没有添加的地方。原因就在这里不同接口类型的驱动工作方式完全不同。从实践角度说我更推荐初学者先拿GT911这类I2C触摸屏练手。因为I2C的链路更透明出了问题可以用i2cdetect直接探测地址可以抓I2C波形调试手段丰富能帮助你理解设备树告知硬件拓扑这个核心机制。USB触摸方案的调试相对黑盒插上就动插上不动时排查路径反而有限。2.3 Linux input子系统驱动和应用之间的标准插座触摸屏驱动并不能直接把坐标数据随便交给应用层中间必须要经过Linux的input子系统。你可以把input子系统理解成一个标准的插座上游是各类输入设备驱动下游是各类应用。触摸屏驱动通过input子系统注册一个input_dev设备节点以后每次检测到触摸事件就用input_event函数把事件上报给内核内核经过事件分发后把数据写到对应的/dev/input/eventX设备节点。应用层只要打开这个节点用read或者poll就能拿到触摸坐标。无论驱动内部多么复杂最终上报给input子系统的都是标准化的事件三元组type、code、value。type指事件类型触摸常用EV_ABS绝对坐标事件和EV_KEY按键事件code具体到是哪个参数比如ABS_MT_POSITION_X表示多点触摸的X坐标value就是坐标值本身。多点触摸协议还有Type A和Type B之分Type A按触点索引上报完整状态Type B则用slot来跟踪触点生命周期功能更强。现在主流的电容触摸屏都支持Type B多点上报GT911驱动默认也是走Type B。理解这层标准化机制非常重要。以后你无论接什么触摸屏代码风格可能千差万别但只要最终能把坐标事件通过input子系统正确上报应用层的Qt、GTK、tslib就都能正常工作完全不关心你驱动里用的什么IC。这种解耦设计是Linux外设驱动普遍遵循的哲学也是为什么一个驱动人才能够快速上手不同硬件的原因。3. 动手前的工程骨架工具链、硬件规划与设备树基础3.1 交叉编译环境内核版本、工具链和文件系统要配套Linux内核编译是交叉编译必须在一台高性能PC上用交叉工具链生成ARM平台可以运行的镜像。我在工程里使用的组合是黑金AX7Z020开发板配套的Linux内核版本来自黑金资料包基于Xilinx官方内核4.14或5.4分支交叉编译工具链是32位ARM的arm-linux-gnueabihf-gcc。需要注意的是工具链版本和内核版本不要差太多否则可能在编译内核时遇到奇怪的报错。我遇到过GCC 12编译老内核失败的情况最后换回GCC 9就顺利通过。如果项目还没有固定工具链我建议直接用Xilinx Vitis/PetaLinux自带的工具链或者用Linaro提供的官方工具链版本选与内核年代相近的。文件系统方面建议初学者直接用黑金资料包里做好的rootfs也就是镜像文件解压出来就能用的那种。如果自己用Buildroot或Yocto从零构建调试阶段会多出很多不必要的变量比如缺库、缺模块路径容易把驱动问题掩盖掉。内核编译时先设置两个环境变量然后再执行配置和编译export ARCHarm export CROSS_COMPILEarm-linux-gnueabihf- make xilinx_zynq_defconfig make menuconfig make zImage -j8 make dtbsxilinx_zynq_defconfig是Xilinx内核提供的基础配置会打开Zynq基本的外设支持。menuconfig打开的图形界面里我们要找到触摸屏驱动相关的配置项。做完配置后编译zImage内核镜像和设备树dtb文件这两个文件就是之后启动系统要用到的核心产物。3.2 Vivado硬件工程里必须提前做对的引脚规划设备树文件写的硬件信息不是凭空编出来的它必须和Vivado硬件工程里的实际连接一致。在Zynq里I2C控制器和GPIO控制器都是PS侧的硬核外设它们的物理引脚分配是在Vivado里通过配置PS端的MIO来实现的。规划引脚时主要有两类信号要关注触摸控制IC和PS之间的I2C通信引脚以及触摸IC的中断输出引脚。GT911这类芯片一般有一个INT中断脚用来通知主机我这里有新触摸数据了。这个INT脚可以接到PS端的某个MIO GPIO上也可以接在PL的通用引脚上。如果I2C和中断都走PS端MIO整个驱动流程会最顺畅因为Linux内核可以直接使用PS端GPIO控制器来申请中断。如果INT脚接到了PL端那么GPIO控制器就是PL里的AXI GPIO IP核设备树写法会变得稍微复杂还得额外挂接PL中断控制器。我个人的建议是如果是自己设计底板或者修改引脚约束尽量把I2C和触摸中断都规划到PS MIO上。这样设备树简洁中断申请逻辑清晰板卡调试也更方便。记得在Vivado的硬件工程里使能对应的I2C控制器配置好MIO引脚综合导出XSA文件后后续生成设备树时才会包含对应的节点。3.3 设备树基础设备树到底在干什么设备树这个问题很多FPGA背景的开发者第一次接触时都会觉得抽象。可以打个比方设备树就是一份硬件说明书系统启动早期由BootROM读取并传给内核内核通过这份说明书知道这个板子上有什么设备、挂在哪个控制器下面、用了哪些资源和地址。传统ARM Linux靠一堆写死的board file来硬编码这些信息后来统一被设备树取代目的就是让同一个内核能适配不同硬件板卡。设备树文件以dts源码形式存在编译成dtb二进制后供系统使用。Zynq开发流程中设备树可以由Xilinx的device-tree-generator脚本从XSA文件生成基础版本但生成的只是默认拓扑触摸屏这种I2C子设备必须你自己往里面加节点。我写一段典型的GT911设备树节点方便对照后面的内容i2c0 { status okay; clock-frequency 100000; gt9115d { compatible goodix,gt911; reg 0x5d; interrupt-parent gpio0; interrupts 36 IRQ_TYPE_EDGE_FALLING; irq-gpios gpio0 36 GPIO_ACTIVE_HIGH; reset-gpios gpio0 37 GPIO_ACTIVE_HIGH; touchscreen-max-x 800; touchscreen-max-y 480; touchscreen-size-x 800; touchscreen-size-y 480; }; };compatible属性是驱动匹配的核心内核的goodix驱动会检查这个字符串是否在自己的of_match_table里。reg属性是I2C设备地址0x5d是GT911常见地址之一。interrupt-parent和interrupts描述中断信号接在哪个控制器、用的是哪个引脚。后两行irq-gpios和reset-gpios是驱动用来操作中断引脚和复位引脚的关键。touchscreen-max-*这些属性会把屏幕物理坐标范围告诉驱动驱动再转换成内核事件上报。关于Zynq设备树里的GPIO编号简单说明一下PS端GPIO控制器的节点名是gpio0引脚编号采用一体化方式MIO 0到MIO 53在节点里对应编号0到53后面的编号留给PL端EMIO扩展。所以例子里gpio0 36指的就是MIO36。4. 两类主流触摸屏驱动的落地实操4.1 GT911电容屏驱动从内核配置到完整编译GT911在内核里对应的源文件是drivers/input/touchscreen/goodix.c历史悠久稳定性很好。要让它生效先在menuconfig里把驱动打开。路径是Device Drivers - Input device support - Touchscreens找到Goodix touch controller按Y编入内核或者按M编成模块。如果已经通过defconfig把内核配置好也可以直接在配置文件中添加CONFIG_TOUCHSCREEN_GOODIXy。打开驱动后重新编译内核make zImage -j8 make dtbs编译完成后把新的zImage和设备树dtb拷贝到启动卡或者通过网络加载启动。系统启动后在串口终端观察日志如果一切正常会看到类似goodix-ts 0-005d: GT911 detected的内核打印这说明probe成功驱动已和硬件正常匹配。启动之后可以进一步确认设备节点是否存在cat /proc/bus/input/devices如果驱动正常工作这个文件里会出现一个名字类似的输入设备条目比如Goodix Capacitive TouchScreen后面跟着Handlers字段显示eventX节点的编号。看到这个节点说明驱动已经通过input子系统注册成功接下来就是应用层测试的事了。4.2 Touchkit红外触摸屏USB HID方案的驱动思路Touchkit红外触摸屏与GT911最大的不同在于接口类型。它通常是USB接口系统启动后USB控制器会自动枚举这个设备内核里的usbtouchscreen驱动会尝试识别并绑定。要验证设备是否被识别插上触摸屏后执行lsusb查看厂商ID和设备ID。内核drivers/input/touchscreen/usbtouchscreen.c里内置了一张已支持的设备ID表如果Touchkit的VID/PID在表中驱动会自动绑定/proc/bus/input/devices里就会出现对应设备。如果不在表中就需要修改usbtouchscreen.c把Touchkit的VID/PID添加到usbtouch_devices数组里然后重新编译内核或模块。这种情况往往出现在一些小众触摸框上逻辑并不复杂难的是你要会改内核源码数组并重新编译。注意USB设备不需要设备树节点因为USB本身就是可枚举总线设备的身份信息由USB协议自带。usbtouchscreen驱动注册后同样通过input子系统上报事件。和GT911相比它不涉及I2C地址、复位时序、中断引脚这些硬件级配置调试上相对简单插上就动插上不动就从USB枚举环节开始查。4.3 编进内核还是独立模块两种方式的取舍触摸屏驱动的编译形态有两种选择编进内核或者编译成.ko模块。内核镜像中编入驱动的好处是开机即用不需要额外加载模块适合最终产品形态缺点是每次修改驱动代码都要重新编译整个内核调试效率低。模块方式的优点是单独编译、单独加载开发阶段可以反复insmod/rmmod不需要频繁烧内核但要求驱动代码与当前运行内核版本严格匹配否则模块加载时会出现vermagic不匹配的error报Invalid module format。我自己的开发习惯是调试阶段把所有触摸驱动编成模块配合一个简单的init脚本自动加载验证没问题后再重新配置内核把这些驱动编进去。这样既保证调试效率又能保证最终产品干净。如果文件系统支持也可以把模块文件拷贝到/lib/modules/$(uname -r)/目录下用depmod生成模块依赖再通过modprobe动态加载这样做更接近发行版的管理方式。关于模块加载后的事件节点还需要提醒一点/dev/input/eventX的编号是由内核动态分配的不是固定的。应用层最好通过/dev/input/by-path或者通过event界面名字去匹配设备不要硬编码eventX编号否则系统重启或者添加新输入设备后应用可能会访问到一个完全错误的设备节点。5. 调试链路全解从完全没反应到手指流畅滑动5.1 先回答硬件有没有被认到拿到一块触摸屏无论接口是I2C还是USB调试的第一步永远是确认硬件有没有被内核认到而不是急着改驱动代码。确认方式就是看内核日志。系统启动后执行dmesg | grep -i goodix或者dmesg | grep -i touch如果有probe成功的信息很快就能进入下一环节。如果没有问题往往出在设备树配置、I2C地址或引脚连接上。对于I2C接口的GT911应该用i2cdetect工具扫描I2C总线看看目标地址上是否有ACK响应。命令格式i2cdetect -y 0这个命令会扫描i2c-0总线上的所有7位地址有设备响应的地址会显示为编号。正常情况下0x5d或者0x14这个位置会显示设备编号具体是哪个取决于GT911的上电时序决定的工作地址。如果扫描不到设备很大概率是触摸IC没有正常工作或者I2C线的引脚接错再或者是设备树里的reg地址与芯片实际配置不符。这时就要回到上电时序去查。GT911有一个非常典型的上电时序要求芯片的RST引脚先拉低INT引脚也拉低然后电源稳定等待若干毫秒后把RST拉高再等待一段时间后INT释放为高。这个时序如果出错芯片会进入从机地址切换模式导致I2C地址和预期不一致。很多我用i2cdetect找不到设备的问题最终都出在这个时序上。如果你的板卡由Linux侧驱动控制复位和中断引脚可以在驱动probe过程里仔细核对这段时序逻辑。5.2 从proc文件系统打到真实事件数据硬件被认到只是第一步驱动注册了input设备之后还要确认事件能不能正常上报。最快的验证方法是读取/proc/bus/input/devices确认event节点编号然后用hexdump直接读设备节点hexdump /dev/input/event1手指点击触摸屏时终端里会持续刷出二进制数据。这些数据按input_event结构体排列包含时间戳、type、code、value。如果hexdump有输出说明驱动已经成功上报事件整条链路已经通了。如果hexdump没有任何输出大概率问题出在中断没有触发或者驱动解析触摸IC数据失败。这一步最常见的坑是设备树里中断号或中断触发类型配置不正确导致触摸IC的中断信号没有正确上传到内核。排查时可以先用debugfs确认GPIO中断是否注册或者临时在驱动里加printk观察中断处理函数有没有被调用。另外确认触摸IC是否真的把INT引脚拉低了——如果INT引脚配置为上拉而触摸IC通过拉低来通知主机那么引脚电平状态不对中断就不会触发。5.3 tslib坐标校准解决点不准的问题触摸事件能上报但屏幕上手指位置和光标位置有偏差这是另一个高频问题。触摸坐标和设备显示分辨率之间并不是天然对齐的比如7寸屏物理分辨率是800x480但触摸IC输出的坐标范围可能不是完整的0到799、0到479加上屏幕贴合角度、安装偏移等因素直接映射就会造成偏差。内核里通过touchscreen-max-x和touchscreen-max-y属性做了一次粗映射但真正高精度的对齐需要应用层校准。在嵌入式Linux里tslib是事实标准。tslib提供了一组库和工具包括校准和滤波功能。使用前要配置环境变量指向正确的事件设备和校准文件export TSLIB_TSDEVICE/dev/input/event1 export TSLIB_CALIBFILE/etc/pointercal ts_calibratets_calibrate会显示几个十字校准点依次点击后tslib会根据触摸坐标和屏幕坐标的对应关系计算出转换参数保存到校准文件里。之后应用通过tslib读取的坐标就已经是校准后的屏幕坐标。Qt程序里如果设置了QT_QPA_FB_TSLIB环境变量就会自动使用tslib的设备配合触摸屏使用非常顺手。如果校准点非常不准并且点击顺序错乱建议检查电容触摸屏的坐标原点定义。触摸IC的坐标原点可能在左上角也可能在右下角设备树里的坐标属性能调整方向比如touchscreen-inverted-x和touchscreen-inverted-y它们的作用是翻转坐标轴向解决镜像和颠倒问题。5.4 一张表收拢七大高频故障调试过程中最怕的是问题现象千奇百怪定位时没有头绪。我根据自己的经验整理过一张速查表每次遇到类似问题先按表里的优先级顺序排查。故障现象大概率原因首选排查动作i2cdetect扫不到设备GT911上电时序不对或I2C地址错误检查复位/中断时序尝试0x14和0x5d两个地址dmesg报设备树probe失败compatible字符串与驱动不匹配比对设备树compatible和驱动of_match_table设备节点注册了但无上报数据中断配置错误或INT引脚接错检查设备树interrupts与硬件连接是否一致hexdump出现乱码/无规律数据I2C地址冲突或总线不稳定降低I2C时钟频率检查上拉电阻事件正常但Qt/应用收不到环境变量未指向正确event节点检查TSLIB_TSDEVICE及Qt相关环境变量触摸方向和屏幕相反设备树缺少坐标翻转属性添加touchscreen-inverted-x/y一段时间后触摸失灵驱动与芯片固件配置不同步检查内核版本必要时更新驱动6. 踩坑记录与写给FPGA工程师的学习路径6.1 三个让我印象深刻的坑第一个坑是MIO编号的错位。Zynq设备树里PS GPIO的编号从0开始对应MIO但很多从PL转过来的工程师习惯把PL引脚的编号也往里塞结果写成gpio0 36这种本该对应MIO36的写法实际连的是某个PL引脚导致中断完全挂不上。这个问题的排查其实更快的方法是把引脚信息重新核对一遍确认Vivado里定的引脚与设备树节点完全一致。第二个坑是GT911的I2C地址两个都试过都失败。后来发现不是地址问题而是驱动里读取配置数据时校验失败报invalid config data。这个问题通常是因为设备树里声明的坐标尺寸与芯片内已有配置不一致或者IC内部的配置区被写入了错误数据。重新上电执行一次复位时序让驱动重新发送配置参数问题就消失了。这种软件不像软件、硬件不像硬件的问题最磨人但也是成长最快的地方。第三个坑是内核模块的vermagic不匹配。自己用新工具链编译出的goodix.ko加载到开发板之后系统报Invalid module format。原因是模块编译时的内核版本、编译器版本与运行内核不一致。解决方案是使用与构建内核同一套工具链和同一份内核源码来编译模块或者直接把驱动编进内核。这个坑在初学者中几乎是必踩的但踩过一次之后对内核模块机制的理解会上一个台阶。6.2 按这个顺序学能帮你少走很多弯路很多FPGA工程师想转Linux驱动开发一上来就看内核源码结果被各种机制淹没。我个人的建议是分三步走。第一步先学会改设备树、编内核、启动系统把修改设备树-编译内核→运行→验证这条基本链路跑通不需要关心代码细节第二步挑一个简单的驱动demo比如GPIO按键驱动看懂probe、open、read这些回调函数体验一遍模块加载和调试的完整过程第三步再碰触摸屏这类带中断、带input子系统的设备驱动因为这里同时涉及异步事件上报和框架对接更有挑战性。触摸屏驱动本身并不复杂但它是一个理想的训练项目I2C通信、设备树、中断、input子系统、应用层交互整条链路全部涉及。把一个7寸触摸屏从零跑到随手滑动其实已经把一个嵌入式Linux工程师最常用的知识面全部覆盖了。做完这个项目你对从硬件到应用的整体链路会有一个完整的认识。6.3 触摸屏跑通之后这条路还能往哪里延伸触摸屏驱动只是黑金云课堂里FPGA Linux开发的一个入口。跑通触摸交互后后面的扩展路径其实非常顺同样是I2C接口可以去接各种传感器、EEPROM、RTC同样的中断input框架可以去接按键、编码器、遥控器再往高性能方向走就可以把FPGA的看家本领拿出来用PL端做MIPI或LVDS图像采集用AXI DMA把图像数据搬到内存然后在Linux应用层做显示和处理这个时候你手边的这块7寸屏就成了一个实时图像显示终端。我个人在实际操作中的体会是Zynq开发最让有成就感的地方不是某一根信号走得多顺也不是某个时序收敛得多漂亮而是你亲眼看到PL和PS两个世界在同一个系统里协同工作PL负责把海量数据流转起来PS负责把人机交互和系统调度跑起来中间由Linux设备树和驱动来牵线搭桥。把这条链路理解透之后再接任何外设、做任何项目底气都会完全不同。
返回列表