bsp学习—串口调试助手
1. 学习内容
- QT 图形化
- QT 和底层交互
- IMX6ULL(正点原子) 显示驱动移植
- IMX6ULL(正点原子) 触摸驱动移植
2. 学习到的知识库
2.1 QT 插件
2.1.1 Qt 在嵌入式 Linux 中的作用
Qt 应用不直接操作 LCD 或 GT911. Qt 通过 QPA 平台插件负责显示, 通过 generic input plugin 负责输入:
1 | QApplication / QWidget |
本项目是 Qt Widgets 应用. 正点原子 i.MX6ULL 无桌面环境时通常使用 linuxfb. 如果 BSP 使用 DRM/KMS 和 EGL, 应改用 eglfs.
2.1.2 Qt 插件和依赖部署
目标板至少需要 QtCore, QtGui, QtWidgets, 平台插件, 输入插件, 字体:
1 | /usr/lib/libQt5Core.so.5 # QT 核心动态链接库 |
检查动态库和插件:
1 | ldd /usr/bin/serial_assistant |
QT_DEBUG_PLUGINS 开启插件调试功能
2.1.3 Qt 启动环境
1 | export XDG_RUNTIME_DIR=/tmp/runtime-root # 指定为当前应用分配运行级的临时目录 |
eventN 只是示例编号, 必须从 /proc/bus/input/devices 中找到 Goodix 对应的实际编号.
2.1.4 Qt 和底层交互
serial_assistant 不使用 Qt SerialPort. SerialPortBackend 通过 POSIX open, read, write 和 termios 访问串口, 并用 QSocketNotifier 把文件描述符事件接入 Qt 事件循环:
1 | QSocketNotifier activated |
2.1.5 三篇内容中的 Qt 控件
本项目的三个 Qt/BSP 主题分别对应界面构建, 底层事件接入以及显示和触摸部署. 实际创建的界面控件集中在 MainWindow, 显示和触摸篇不新增专用控件, 而是通过 Qt QPA 把 framebuffer 和 Linux input 事件交给已有控件.
| 主题 | Qt 控件或类 | 在本项目中的用途 |
|---|---|---|
| Qt 图形化 | QMainWindow, QWidget |
创建主窗口和中央部件, 承载全部界面内容 |
| Qt 图形化 | QGroupBox |
分组显示串口设置, 接收区和发送区 |
| Qt 图形化 | QLabel |
显示字段名称, 连接状态和收发字节计数 |
| Qt 图形化 | QComboBox |
选择端口, 波特率, 数据位, 校验, 停止位和行尾 |
| Qt 图形化 | QPushButton |
刷新, 打开, 关闭, 清空, 发送和软键盘按键 |
| Qt 图形化 | QCheckBox |
切换 HEX 显示, HEX 发送和自动滚动 |
| Qt 图形化 | QPlainTextEdit |
显示接收数据和编辑待发送数据 |
| Qt 图形化 | QMessageBox |
弹出打开串口和发送失败提示 |
| Qt 图形化 | QVBoxLayout, QHBoxLayout, QGridLayout |
管理主窗口, 选项栏和触摸软键盘的布局 |
| Qt 与底层交互 | QObject, QSocketNotifier |
以对象信号槽和文件描述符可读事件接入 Qt 事件循环, 这些不是可见控件 |
| 显示和触摸部署 | QApplication, QWidget 及上述输入控件 |
linuxfb 或 eglfs 负责显示, evdevtouch 或 tslib 负责输入, GT911 不直接由控件访问 |
控件层级可以概括为:
1 | QApplication |
2.2 显示驱动移植
这里可以具体查看之前写过的显示屏移植篇
2.2.2 查找已有驱动
1 | rg -n "panel|lcdif|mxcfb|backlight" \\ |
通用决策:
- 已有完全匹配的 panel 驱动, 只修改设备树.
- 已有通用 panel 驱动, 增加 compatible 和 display-timings.
- 没有匹配驱动或初始化时序不兼容, 才编写 panel 驱动.
panel: 屏幕面板驱动
2.2.3 配置内核
配置名称随 BSP 版本变化, 以当前 defconfig 和 make menuconfig 为准. i.MX6ULL 旧版 framebuffer BSP 常见选项:
1 | CONFIG_FB=y |
新版 DRM/KMS BSP 应配置对应的 DRM, LCDIF, panel 和 backlight 选项.
2.2.4 编写设备树
设备树要连接 LCDIF, pinctrl, reset, backlight, 电源和 display-timings. 示例:
1 | &lcdif { |
时序数值必须替换为屏幕手册中的值. 引脚复用示例:
1 | pinctrl_lcdif_dat: lcdifdatgrp { |
pad 宏和电气参数必须查询当前 SoC 的 pinfunc 头文件. 同一个 GPIO 不能同时被 regulator, LED, reset 或触摸节点占用.
2.2.5 编译, 烧录和验证
1 | cd /path/to/linux |
启动目标板后先不要运行 Qt:
1 | ls -l /dev/fb0 |
问题定位:
- 没有 /dev/fb0, 查设备树 status, 内核配置, pinctrl 和 driver probe.
- 有 /dev/fb0 但黑屏, 查背光, reset.
- 有画面但偏色, 查 RGB 位宽.
- 有画面但抖动, 查 pixel clock 极性, 时钟频率.
- 分辨率不对, 查 U-Boot 参数.
确认 framebuffer 正常后再验证 Qt:
1 | export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0 |
2.3 触摸驱动移植
2.3.1 确认 GT911 硬件
从触摸模组手册和原理图确认控制器型号, I2C 总线, 7-bit 地址, INT GPIO, RST GPIO, 中断触发方式, 触摸范围和坐标方向. GT911 常见地址为 0x5d 或 0x14, 地址由复位期间 INT 电平决定.
本项目链路:
1 | GT911 -> I2C2 -> Goodix 内核驱动 -> Linux input -> /dev/input/eventN -> Qt |
2.3.2 验证 I2C
1 | i2cdetect -l |
I2C communication failure: -5通常发生在内核 probe 阶段.
2.3.3 设备树和内核驱动
优先启用内核已有的 goodix 驱动. GT911 DTS 示例:
goodix 驱动: 一个触摸屏驱动, 加载之后会在系统下生成 /dev/input/eventX 节点.
其底部汇总了 GT911, GT9271, GT9147 等芯片
1 | &i2c2 { |
逐句解析:
1 | &i2c2 { /* 引用板级设备树中已经定义的 I2C2 控制器 */ |
注意事项:
touchscreen@5d中的@5d应与reg的 I2C 地址一致, 节点名称本身不是驱动匹配条件.interrupts的触发标志不能脱离当前内核的 GPIO binding 猜测,IRQ_TYPE_NONE表示交由系统或驱动确定, 如果中断不工作应根据硬件电平改为上升沿, 下降沿或电平触发.pinctrl-0中的pinctrl_ts_int和pinctrl_ts_reset必须在同一份设备树中定义, 并且对应引脚不能同时被 regulator, LED 或其他外设占用.reg的地址必须根据 GT911 复位时序和硬件连接确认, 常见地址为0x5d或0x14.
属性名必须以当前内核 Documentation/devicetree/bindings/input/touchscreen binding 为准. 本板 GPIO1_IO09 曾被 3.3 V regulator 使用, 必须删除冲突的 GPIO 属性.
2.3.4 验证 Linux input
1 | cat /proc/bus/input/devices |
确认 Goodix 对应的 eventN 后, 按下和移动触摸时 od 应出现新数据, 中断计数也应增加. 没有 event 节点说明 probe 或 input 注册失败. event 存在但无数据, 重点检查 INT, 排线和中断配置.
2.3.5 接入 Qt
Qt 不直接访问 GT911, 而是读取 Linux input event. 先使用 evdevtouch:
1 | export QT_QPA_GENERIC_PLUGINS=evdevtouch:/dev/input/eventN # Qt 框架中用于显式指定通用输入设备插件 |
需要滤波和校准时使用 tslib:
tslib 是一个开源的嵌入式 linux 触摸屏数据校准框架
1 | export TSLIB_TSDEVICE=/dev/input/eventN # TSlib 库绑定的触摸屏设备节点 |
坐标偏移或方向错误时, 先确认内核上报的 X/Y 范围, 再检查屏幕旋转和 /etc/pointercal. 不要先修改应用按钮坐标.