RK3288W Android8.1开发日志(三):HDMI EDID读取异常时用I2C抓包定位

发布时间:2026/9/27 21:28:39
RK3288W Android8.1开发日志(三):HDMI EDID读取异常时用I2C抓包定位 1. 从一次黑屏说起RK3288W 上 EDID 读取失败到底卡在哪RK3288W 跑 Android 8.1 的板子HDMI 输出这块最容易踩的坑不是分辨率不对而是根本没读到 EDID。现象很典型接上显示器内核 log 里dw-hdmi报failed to read edid block或者干脆edid NULL然后系统回退到默认分辨率运气不好直接黑屏。很多人第一反应是去改dw-hdmi.c把 EDID 屏蔽掉强制输出这招能救急但根因没定位换块屏又翻车。EDID 走的是 HDMI 的 DDC 通道本质就是一条 I2C 总线RK3288W 上通常挂在i2cff160000这类控制器下从机地址固定0x50。读不到 EDID无非三种可能I2C 物理层没通上拉、电平、走线、地址冲突总线上有别的设备抢0x50、时序不满足时钟拉伸、SCL 频率过高。这篇就按这个顺序用 i2c-tools 抓包把根因钉死全程不动硬件。适合谁看正在调 RK3288W Android 8.1 HDMI 显示链路的驱动/系统工程师尤其是手上板子接不同显示器表现不一致、怀疑 DDC 通道有问题的场景。下面所有命令和 dts 片段都是可复制直接用的。2. 前置准备TaoToken 统一 Key 与调试日志通道排查这种跨内核态和用户态的 I2C 问题日志会散落在 dmesg、i2c-tools 输出、还有你自己写的解析脚本里。我习惯把调试过程中的关键结论和命令输出通过一个统一的 API 通道记录下来方便回溯也方便团队里其他人复现。TaoToken 在这里的角色就是提供一套统一的 Key 和 API 入口不用为每个小工具单独配鉴权。先去控制台拿 Key地址是https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite创建完在 API Keys 页面复制页面在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite。接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite接口基址统一用https://taotoken.net/api注意这个不带 UTM 参数。拿 Key 只是第一步真正有用的是把 I2C 抓包结果结构化记下来。比如你抓完一次i2cdetect把输出贴进日志后面比对不同板子、不同显示器时就有基线了。如果你后面要长期跑编码或 Agent 类的自动化调试脚本可以考虑 Coding Plan入口在https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。想先验证模型对 log 的理解能力用模型对话页面https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite直接贴 dmesg 片段问也行。3. 可复制配置dts 里 HDMI I2C 节点与 i2c-tools 抓包3.1 dts 中 HDMI DDC 节点骨架RK3288W 的 HDMI 控制器 dts 节点里DDC 总线是单独引用的。先确认你的hdmi节点有没有正确指向 i2c 控制器很多板子 EDID 读不到就是因为这里ddc-i2c-bus指错了或者压根没写。hdmi { status okay; ddc-i2c-bus i2c4; /* 部分 SDK 用 hdmi_ddc 单独节点按你的 dtsi 实际命名 */ }; i2c4 { status okay; clock-frequency 100000; /* EDID 阶段建议先降到 100k别一上来 400k */ pinctrl-names default; pinctrl-0 i2c4_xfer; /* 确认没有其他设备占用 0x50 */ };关键点clock-frequency先给 100kHz。DDC 通道对时序敏感400kHz 在走线稍长的板子上就容易读失败降速能排除一大类时序问题。另外确认i2c4下没有别的从机节点避免地址冲突。3.2 编译进 i2c-tools 并抓包Android 8.1 默认不带 i2c-tools需要自己编一个塞进 system/bin。源码用i2c-tools-4.1即可交叉编译后 push 进去adb root adb remount adb push i2cdetect /system/bin/ adb push i2cget /system/bin/ adb push i2cset /system/bin/ adb shell chmod 755 /system/bin/i2cdetect先扫总线确认0x50在不在adb shell i2cdetect -y 4正常应该看到50这一格被标记UU 表示已被驱动占用数字表示可访问。如果整行全是--说明 I2C 物理层没通直接跳到第 5 节排查。如果0x50位置是UU说明内核 HDMI 驱动已经占用了这个地址这是正常的但你要抓包就得先让驱动释放或者用i2cget直接读。读 EDID 前 8 字节头正常应该是00 ff ff ff ff ff ff 00adb shell i2cget -y 4 0x50 0x00 adb shell i2cget -y 4 0x50 0x01更完整的做法是写个循环把 128 字节全读出来for i in $(seq 0 127); do addr$(printf 0x%02x $i) val$(adb shell i2cget -y 4 0x50 $addr 2/dev/null) echo -n $val done把输出拼起来就是完整 EDID block头 8 字节对不上基本可以判定是读时序或地址问题而不是显示器本身。4. 验证请求与成功结果EDID 解析与 dmesg 对照4.1 解析 EDID 确认分辨率把上面读到的 128 字节存成edid.bin用edid-decode解析edid-decode edid.bin成功的话你会看到EDID version: 1.3、Detailed mode里列出显示器支持的分辨率比如1920x108060。这一步能确认两件事I2C 读出来的数据是完整且校验和正确的最后字节 checksum 要对以及显示器实际支持哪些模式。4.2 dmesg 里对照 dw-hdmi 的读取结果adb shell dmesg | grep -i -E edid|ddc|hdmi正常读取成功的 log 类似dw-hdmi ff980000.hdmi: HDMI cable connected dw-hdmi ff980000.hdmi: read edid block 0 ok dw-hdmi ff980000.hdmi: EDID block 0 checksum ok如果看到read edid block failed或者ddc transfer failed但你的i2cget手动读又能读到正确头那问题就在驱动侧的时序配置而不是硬件。这时候回去检查clock-frequency和ddc-i2c-bus指向。4.3 用 TaoToken 记录这次抓包基线把i2cdetect输出、edid-decode结果、dmesg 关键行整理成一段文本通过 API 存下来。用 curl 示例curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_KEY \ -H Content-Type: application/json \ -d { model: your-model, messages: [ {role: user, content: 帮我归纳这段 RK3288W EDID 抓包日志的异常点粘贴日志} ] }这样每次换板子、换显示器你都有一个可对比的基线记录不用靠记忆。5. 本篇常见错排查i2cdetect 扫不到 0x50整行全空。先量 DDC 的 SCL/SDA 上拉电压正常应该是 3.3V 或 5V。如果电压为 0检查 HDMI 连接器的 DDC 引脚有没有虚焊或者 dts 里 pinctrl 配错导致引脚没复用成 I2C 功能。这一步不改硬件先用万用表确认。0x50 能扫到但读出来全是 0xff。典型的时序问题。把clock-frequency从 400k 降到 100k 再试还不行降到 50k。RK3288W 的 I2C 控制器在某些走线布局下对时钟拉伸支持不好降速是最有效的软解法。地址冲突总线上有别的设备也响应 0x50。用i2cdetect -y 4看有没有多个格子被标记。如果有检查 dts 里i2c4下是不是挂了 EEPROM 之类的设备它们的地址可能和 DDC 撞了。把冲突设备挪到别的 I2C 控制器。dmesg 报 edid checksum error。说明读到了数据但校验不过通常是读的过程中丢字节。检查是不是有别的进程在同时访问这条 I2C 总线或者驱动里 EDID 读取的重试次数太少。可以在dw-hdmi.c里把重试次数调大观察。改了 dts 但没生效。确认你改的是实际编译进 dtb 的那个 dtsiRK3288W 的 SDK 里经常有多份 hdmi 相关 dtsi用grep -r ddc-i2c-bus全工程搜一遍确认最终生效的那份。6. 后续接入与工具入口定位完 EDID 读取异常如果你要把这套抓包和日志记录流程固化到日常调试里建议直接用 API Keys 配好统一通道入口在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite接入细节看文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。想先拿一段 dmesg 让模型帮你圈异常点用模型对话https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite最快。长期要跑自动化调试脚本或 Agent 的Coding Plan 在https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。最后补一句实操经验RK3288W 这块板子我调的时候三块板子只有一块 EDID 读取稳定另外两块都是把 I2C 降到 50kHz 才勉强读全。所以别急着怀疑显示器先把总线速度降下来试一轮能省掉大量换硬件的功夫。