这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【FRDMRW612系列】FRDM-RW612移植ZephyrLVGL踩坑:GT

共1条 1/1 1 跳转至

【FRDMRW612系列】FRDM-RW612移植ZephyrLVGL踩坑:GT911触摸导致系统启动死机的排查与修复

高工
2026-08-08 20:00:43     打赏

一、背景与现象

硬件平台:NXP FRDM-RW612 + LCD-PAR-S035 显示屏扩展板(ST7796S,480x320,通过 RW612 的 LCDIC 外设以 4 线 SPI + DMA 驱动;触摸芯片 GT911,挂在 flexcomm2 I2C 总线上,地址 0x5D)。

软件平台:Zephyr 4.4.0,应用为官方 LVGL 示例(samples/subsys/display/lvgl)的移植。

现象:启用 LVGL 后烧录固件,屏幕满屏彩色噪点,串口一条日志都没有,系统看似彻底死亡。

而同一套硬件:

跑 Zephyr 裸 display 示例(不用 LVGL)→ 正常

跑 NXP 官方 MCUXpresso SDK 的 LVGL 工程 → 显示和触摸都正常


二、排查过程

2.1 排除 LVGL 本身

最初怀疑 LVGL 渲染缓冲、flush 线程栈(默认仅 1024 字节)、像素格式转换等。通过加大栈、启动时用 display_write 直接刷屏(绕过 LVGL)等手段,确认显示链路正常——问题不在 LVGL。

2.2 关键分叉点:CONFIG_INPUT

二分配置发现:只要 CONFIG_INPUT=n,系统完全正常;INPUT=y 就死机。

原因藏在 shield 的 Kconfig.defconfig 里:

if SHIELD_LCD_PAR_S035
if LVGL
config INPUT
    default y        # LVGL=y 时 INPUT 默认打开
endif
endif

也就是说只有 LVGL 构建才会启用 GT911 触摸驱动的初始化——裸 display 示例从不碰触摸,所以一直正常。这解释了"加 LVGL 就坏"的表象。

2.3 为什么连日志都没有?

这是本问题最阴险的地方。GT911 初始化发生在 shield 的 SYS_INIT(POST_KERNEL 阶段,优先级 85),早于 main():

挂死在 SYS_INIT → main() 永远不执行

Zephyr 默认 deferred 日志:日志由专门的后台线程输出,系统卡在启动阶段时日志线程还没调度起来 → 缓冲区里的日志一条都打不出来

ST7796S 初始化没跑完 → 屏幕显示的是显存上电随机值 = 满屏噪点

39fd91aa58dcf3d83fd5d25376967640.jpg

对策:CONFIG_LOG_MODE_IMMEDIATE=y(同步日志)+ 在 shield.c 和 GT911 驱动里埋 LOG_INF 标记。同步日志下,挂死前打印的最后一行就是案发地点。

2.4 调试器的陷阱

用 Ozone/J-Link 单步时发现停在各种奇怪位置,故障转储显示 MSP=0xFFFFFFE0、PC 是垃圾值。但这些转储里都有一个共同标记:Debug event——Cortex-M33 在 DebugMonitor 异常未使能时,调试器的 halt/单步动作会被升级成 HardFault。这些"崩溃"全是调试器制造的假象,真实挂死点只能靠自由运行 + 同步日志埋点确定。

经验:调中断密集的驱动初始化代码时,用"运行到断点"(F5),不要单步(F10/F11)。

2.5 埋点定位

自由运行 + 埋点日志,最后一行输出:

[00:00:00.254,956] <inf> lcd_par_s035: shield: gt911 init...
[00:00:00.261,126] <inf> gt911: gt911: init entry
[00:00:00.266,337] <inf> gt911: gt911: INT pin low, entering sleeps
[00:00:00.343,232] <inf> gt911: gt911: GPIO done, reading ID via I2C addr 0x5d

← 死在这里:第一笔 I2C 传输

挂死在 GT911 读取芯片 ID 的第一笔 I2C 传输,且 CONFIG_I2C_NXP_TRANSFER_TIMEOUT=1000 的 1 秒超时也没有生效。

2.6 I2C 扫描实验:问题比 GT911 更底层

暂时禁用 GT911 节点让系统能启动到 main(),在应用里加 I2C 地址扫描(探测 0x48 板载温度传感器、0x5D、0x14 两个 GT911 候选地址):

[00:03:28.449] i2c probe 0x48 ...
[00:03:29.455] i2c probe 0x48 -> ret 0     ← 耗时整整 1005ms!
[00:03:29.460] i2c probe 0x5d ...
← 永久卡死


解读

板载传感器 0x48 必然在线,正常应答只需几百微秒,却等满 1000ms 超时——而且驱动忽略了 k_sem_take 的超时返回值,把陈旧状态(初始值 0 = 成功)当成结果返回。说明 I2C 完成中断从未触发,ret 0 是假象

第二笔传输直接把系统拖死(硬件状态机留在中途,中断风暴,主线程冻结)

结论:这块板子上 flexcomm I2C 的传输链路压根就没工作过,GT911 只是第一个实际发起传输的受害者。

三、根因

3.1 上游已知的 RW612 回归

搜索发现上游 issue zephyrproject-rtos/zephyr#107017,报告者同样在 RW612 + Zephyr 4.4 上遇到 I2C 卡死,并指出是 commit 8f24beb 引入的回归——它在 PM_DEVICE_ACTION_RESUME 路径上新增了一次 pinctrl_apply_state()。

3.2 触发路径

Zephyr 的设备 PM 初始化函数 pm_device_driver_init()(subsys/pm/device.c)在启动时会连续执行两个 PM 动作:

/* Run power-up logic */
rc = action_cb(dev, PM_DEVICE_ACTION_TURN_ON);   // → mcux_flexcomm_init_common()
...
/* If device has no PM structure */
if (pm == NULL) {
    /* Device should always be active */
    return action_cb(dev, PM_DEVICE_ACTION_RESUME);  // → 又一次 pinctrl_apply_state()
}

于是每次启动,flexcomm I2C 的初始化时序变成:

TURN_ON: pinctrl_apply_state() → I2C_MasterInit() → 注册中断 → 使能中断
RESUME:  pinctrl_apply_state()  ← 又来了第二次!(此时 MasterInit 已经做完了)

3.3 为什么第二次 pinctrl 是致命的

RW61x 的引脚复用由 MCI_IO_MUX 控制,pinctrl_apply_state() 对 flexcomm 功能引脚的操作是"先清零功能选择位、再重新置位"。在 I2C_MasterInit() 完成后再来这么一次,flexcomm 的功能选择被中途打断重建,I2C 外设状态机进入损坏状态:

传输发起后永远等不到完成中断(第一笔传输死等超时)

外设残留状态导致后续传输触发中断风暴,CPU 冻结(第二笔传输系统死机)

issue 报告者验证:删掉 RESUME 里的 pinctrl_apply_state(),或者在它之后重新执行 I2C_MasterInit(),I2C 即恢复正常。

四、修复

修改 Zephyr 树 drivers/i2c/i2c_mcux_flexcomm.c,让 RESUME 走完整初始化(保证 pinctrl 永远发生在 I2C_MasterInit 之前):

 static int i2c_mcux_flexcomm_pm_action(const struct device *dev, enum pm_device_action action)
 {
    const struct mcux_flexcomm_config *config = dev->config;
    int error;
 
    switch (action) {
    case PM_DEVICE_ACTION_RESUME:
-       error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
-       if (error < 0 && error != -ENOENT) {
-           return error;
-       }
-       break;
+       /* Workaround for zephyrproject-rtos/zephyr#107017: on RW61x,
+        * re-applying pinctrl after I2C_MasterInit() leaves the flexcomm
+        * I2C peripheral in a bad state (transfers never complete, device
+        * can get stuck in its ISR). Run the full init instead so that
+        * pinctrl is always applied before I2C_MasterInit().
+        */
+       return mcux_flexcomm_init_common(dev);
    case PM_DEVICE_ACTION_SUSPEND:
        error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_SLEEP);
        if (error < 0 && error != -ENOENT) {


mcux_flexcomm_init_common() 内部顺序为:pinctrl → I2C_MasterInit() → 创建传输句柄 → 配置波特率 → 连接并使能中断。重复执行是幂等的(IRQ_CONNECT/irq_enable 重复调用无副作用),因此这个修复同时兼容带 PM 的运行时挂起/恢复路径。


五、验证

修复后同样的 I2C 扫描:


[00:40:47.039] i2c probe 0x48 ...
[00:40:47.044] i2c probe 0x48 -> ret 0     ← 5ms 完成(修复前 1005ms)
[00:40:47.050] i2c probe 0x5d ...
[00:40:47.055] i2c probe 0x5d -> ret 0     ← GT911 在 0x5D 正常应答!
[00:40:47.060] i2c probe 0x14 ...
[00:40:47.066] i2c probe 0x14 -> ret -5    ← 干净利落的 NAK,不再死锁


地址 修复前 修复后 说明

0x48 1005ms 超时,假成功 5ms,ret 0 板载 p3t1755 温度传感器

0x5D 系统死锁 5ms,ret 0 GT911 真实地址

0x14 (未执行到) 5ms,ret -5 无应答,正常返回错误

恢复 GT911 节点后:启动正常、显示正常、GT911 初始化成功,触摸事件经 Zephyr input 子系统进入 LVGL(shield 的 zephyr,touch chosen 节点使 CONFIG_LV_Z_POINTER_INPUT 自动生效),点击屏幕上的按钮可正常响应。


六、经验总结

"无任何日志"本身就是高价值线索:说明系统挂在 main() 之前的 SYS_INIT 阶段,且默认的 deferred 日志在这种场景下必然沉默。CONFIG_LOG_MODE_IMMEDIATE=y 是排查启动期问题的第一步。

调试器会撒谎:Cortex-M 下单步/halt 可能触发 Debug event 型 HardFault,表现出栈损坏、PC 乱飞等骇人假象。自由运行 + 埋点日志才是启动类问题的金标准。

分层二分:LVGL → INPUT 子系统 → GT911 驱动 → I2C 驱动,逐层排除,每一层都用"能跑通的最小配置"验证。

用已知良好的参照物:板载传感器(0x48)验证了"I2C 传输整体坏掉"而非 GT911 单体问题,避免了在触摸驱动里空耗。

先搜上游 issue:RW612 是相对新的平台,Zephyr 4.4 的回归 issue #107017 几乎描述了完全相同的现象,直接锁定了根因方向。

附:相关配置

应用 prj.conf 关键项:


CONFIG_INPUT=y                        # 启用 GT911 触摸
CONFIG_I2C_NXP_TRANSFER_TIMEOUT=1000  # I2C 传输超时兜底(驱动默认 K_FOREVER 死等)
CONFIG_LVGL=y
CONFIG_LV_Z_FLUSH_THREAD_STACK_SIZE=4096  # 默认 1024 对 LCDIC DMA 写链偏紧

注意:该修复在 Zephyr 树内(drivers/i2c/i2c_mcux_flexcomm.c),不在应用仓库中。更新 Zephyr 树时需检查上游是否已修复 #107017,未修复则需重新打上此补丁。





关键词: FRDMRW612     Zephyr     LVGL     GT9    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]