ARTICLE DETAIL

资讯详情

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

MTK6769 Type-C PD充电调试:从管脚定义到Android15协议栈实战

MTK6769 Type-C PD充电调试:从管脚定义到Android15协议栈实战 先把话说在前面这类问题十次里面有八次不是协议栈写得不明白而是硬件链路或者驱动状态机没对齐。我最近手里一块 MTK6769 平台的板子在调 Type-C PD 充电现象特典型——插上支持 PD 的充电器系统栏也弹了“正在充电”可实际充进去的电流只有几十毫安曲线拉出来基本是一条平线。从硬件管脚量到 PD 协商日志最后定位到的问题说出来都算不上高深CC 状态上报和充电驱动预期不一致协商电压上去了充电路径却没切过去。想把这个过程讲清楚得从 Type-C 母座那几个最容易被忽略的管脚说起再到 Android15 环境里 MTK 的 TCPC 框架和 PD 协议栈的协作逻辑最后落到实战排查手法上。不管你是刚接手 BSP 的新手还是被 Type-C 兼容性问题折磨过几轮的老人这篇应该都能给你省下不少查dmesg的时间。1. 为什么 MTK6769 的 Type-C 充电调试要先抠管脚定义Type-C 之所以难调首先难在接口本身就不是一个“简单电源口”。它把电源、数据、音视频、调试串口全塞进同一个连接器里物理管脚之间的复用关系和检测机制比 Type-A 复杂了一个量级。在 MTK6769 这类平台上Type-C 不只是充电口它还是 USB 数据口有时候还得兼任 DP 投屏口。你如果不先把管脚职责理清楚后面查起问题来很容易在软件日志里绕圈子。1.1 从 14Pin 母座到完整 24Pin 公头哪些管脚跟充电有关大家在网上经常搜到“type-c 母座 7 个引脚定义 14p”这种说法这里先解释一下。完整的 Type-C 公头定义是 24 Pin两侧各 12 Pin支持正反插的关键在于 A/B 两侧对称布局。但实际很多开发板或小家电用的母座是简化版常见的有 14Pin、16Pin甚至某些纯供电用途的小板只有 6Pin。简化母座通常砍掉的是超高速差分对SSTX/SSRX和部分重复的 VBUS/GND。真正跟充电强相关的管脚我列了一张表调试时对着它看比翻规格书快。管脚名称充电链路中的作用A1/B1, A12/B12GND电流回流路径大电流充电时必须保证所有 GND 焊接可靠A4/B4, A9/B9VBUS充电输入电压由 PD/QC 协商决定水平最大能到 20VA5CC1连接检测、角色检测、供电能力广播、PD 信令复用B5CC2与 CC1 对称正反插时只有一边有信号A6/A7, B6/B7D/D-USB2.0 数据BC1.2/QC 充电协议载体A8SBU1DP Alt Mode 的 AUX 通道或 Audio Adapter 模式B8SBU2与 SBU1 对应同样可做 AUX 或模拟音频特殊 CC 上的 VCONN—给线缆内 E-Marker 芯片供电强调一下Type-C 的 CC 管脚是整条链路的灵魂。它承担了插拔检测、DFP/UFP 角色判定、供电能力广播和 PD 信令传输。在调试充电时你第一步要做的就是确认 CC1/CC2 上有没有正确的上下拉电阻以及驱动里配置的 Rp/Rd 值和实际硬件是否一致。1.2 CC 上下拉电阻决定“你是谁”DFP、UFP 还是 DRPType-C 的检测原理说穿了不复杂两根 CC 线通过不同的下拉/上拉电阻组合来判断对方是什么设备。作为电源提供方的 DFP比如充电器会在 CC 上用上拉电阻 Rp 拉到 vSafe5V作为设备方的 UFP比如手机则用 5.1kΩ 下拉电阻 Rd 到 GND。当两边物理连接CC 线电压被拉到一个特定范围双方就通过这个电平确认对方插入了。这三种角色加上正反插会有几种典型组合。调试时经常遇到“插上没反应”的情况绝大多数是 UFP 侧没有 5.1kΩ 下拉或者 DFP 侧的 Rp 阻值不对。我在几块主板上见过把 Rd 直接省略、CC 悬空的设计结果就是充电器输出一个 5V 之后就停在 SourceCaps 状态永远不会往下走。补充一个容易踩的VCONN。当一枚 CC 上检测到的是 Ra1kΩ 左右下拉而不是 Rd说明线缆里带了 E-Marker 芯片系统要在检测到 Ra 的那一侧输出 VCONN 给芯片供电。很多 5A 线缆识别失败就是驱动只在 single Ra 的场景下开了 VCONN双头 CC 都接 Ra 时处理逻辑判断错了。1.3 SBU1/SBU2 不只是投屏通路它可能干扰充电识别热搜词里有一条“type-c cable 中 sbu1 sbu2 引脚功能”还有一条“android15 无法投屏”。这两个热词放一起看很有意思。SBU 管脚在普通 USB 充电场景下完全不参与但在 DP Alt Mode 下是 AUX/AUX- 通道在 Audio Adapter Accessory Mode 下走模拟音频信号。问题在于很多四层板或低成本板把 SBU 线走得特别长、没有包地或者跟 VBUS/CC 产生了串扰。结果是主板插上支持 DP 的线缆后先是 PD 协商抖动再是音频设备识别到错误接入最后充电电流一路上不去。Android15 环境下投屏问题我后面会专门说但这里先记住一个原则凡是 Type-C 母座有 SBU 引脚的板子调试充电时必须关注 SBU 状态。只要按下耳机的“模拟音频接入模式”切换PD 充电协商会被打断这在软件里表现为 SVID 协商超时后复位电流跳回 5V/500mA。2. 充电链路的核心设计VBUS、CC 耐压、E-Marker 与 Type-A 改造管脚定义搞清楚之后第二个环节是硬件链路设计。很多人以为充电调试是纯软件活实际上 MTK6769 平台上一大半“充不进电”都源于硬件布局和器件选型问题。你必须在画板阶段就盯住几个关键器件和走线后面才不至于查日志查到崩溃。2.1 VBUS 采样电阻和“开尔文连接”的走线细节电池充电电流的闭环控制依赖充电 IC 内部的电流检测。MTK 平台通常搭配 MT6370 这类集成 PMIC 芯片外部只有一路电流采样电阻。这颗电阻一般选 10mΩ 或者 5mΩ精度要求 1%。这里有个很实际的坑采样电阻到充电 IC 的走线必须采用开尔文连接也就是从采样电阻两端单独拉一对细线到 IC 的 SENSE / SENSE- 引脚不能在采样电阻的铜皮上直接打孔分叉。铜皮上的压降在高电流下很可观之前量到一颗采样电阻两端电压 11mV换算下来电流才 1.1A但实际电池侧电流已经是 1.8A系统直接把充电电流限制在了一个假低值。VBUS 入口的过压保护(VBUS OVP)也值得注意。PD 协商完好后 VBUS 会升到 9V、12V、20V 不等OVP 管子的耐压余量至少要留 1.5 倍以上。MTK6769 参考设计里的 VBUS 通路通常有专门的 OVP IC 或 PMIC 内置 OVP但部分定制板为了省成本直接只用了 TVS结果 20V 插入时直接把后面充电 IC 打穿。2.2 VCONN、E-Marker 与 5A 线缆识别Type-C 线缆按电流等级分两类3A 及以下不需要 E-Marker 芯片5A 及以上必须在线缆两端或中间内置 E-Marker芯片由连接器上的 VCONN 供电供电电压典型 3.3V电流很小几毫安。这意味着如果你想跑 5A 大电流充电单靠 CC 的 5.1kΩ 下拉是不够的软件必须检测连接器端是否出现 Ra约 1kΩ 下拉到 GND识别到 Ra 后打开 VCONN 给 E-Marker 供电发送 Discover Identity 指令读取线缆能力确认最大电流是 5A然后才允许协商 5A PDO。很多“C-to-C 线插上只能 5V/3A”的兼容性问题就出在这个环节。线缆里的 E-Marker 需要 VCONN 上电时序正常如果 VCONN 电容过大导致上电过慢或者驱动在读取线缆信息前有一个非常短的超时整条链路就可能降级成 3A 甚至以 BC1.2 方式跑。2.3 Type-A 母座改 Type-C最容易接错的几根线热搜词里有一条“电子设备 type-a 改 type-c”很多人觉得把 Micro-USB 或 Type-A 改成 Type-C 就是换接口实际上 CC 检测才是关键。如果你改造的目标是让设备继续做 UFP被充电方CC1 和 CC2 必须各接一颗 5.1kΩ 下拉到 GND不能省略。没有这两个电阻充电器会和设备僵持在“互相不知道对方是谁”的状态大概率只输出 5V 不完成充电握手甚至完全不供电。更危险的是有人把 CC 直接接到 VCC 或 GND。如果直接接 VCCDFP 侧会认为拉高无效甚至可能造成过流如果直接接 GNDCC 上变成短路负载一些带 CC 过流保护的适配器会直接关闭输出。正确做法是VBUS 接设备 5V 输入GND 接 GNDD/D- 按需直连或加上 BC1.2 识别电阻CC1/CC2 各自通过 5.1kΩ 下拉正反插就都支持了。3. PD 协议在 Android15 环境下的软件框架与协商流程硬件链路通了之后软件层才进入真正精彩的阶段。PD 协议栈不是一个“库”它是一整套分层的状态机。MTK6769 平台的 Type-C 控制通常由 PMIC 内的 TCPCType-C Port Controller或外置 TCPC 芯片承担软件侧走的是tcpc驱动加上tcpc_manager、PD 协议栈和充电驱动的协作。Android15 在框架层没有推翻这套架构但一些具体策略配置变了导致从 Android13 升级上来的板子经常出现行为不一致。3.1 TCPC、TCPM、协议层、DPM 到底谁干什么先把名字和职责对齐之后看日志才分得清哪一层在干活。层级名称主要职责物理层TCPC读取 CC1/CC2 电压控制 Rp/Rd收发 BMC 编码的 PD 物理信号策略引擎TCPM / tcpc_manager插拔状态机、角色切换、PD 消息策略筛选、SVID 协商协议层PD Protocol保证消息可靠送达重传、超时、GoodCRC 匹配设备策略管理器DPM决定“在当前场景下应请求哪个 PDO”对接充电驱动上层框架Power Supply / Vbus 管理把协商结果暴露给 Android 的 BatteryService实际排障时报错最常见的是 TCPM 层“attach state 不对”和 Protocol 层“GoodCRC timeout”。前者说明物理检测就没完成后者说明物理链路通但 PD 物理层的时序或逻辑不满足规范。打个比方TCPC 相当于门卫负责看门外站着谁TCPM 是接待处判断来人是客户还是供应商PD Protocol 是邮局保证每封信都送到且回执DPM 是老板决定跟对方谈到什么条件Power Supply 是财务室老板谈完条件后让它拨款。你如果看到“能协商到 9V 但电池电流上不去”大概率问题出在 DPM 和财务室之间的对接上。3.2 PD 和 QC 的本质差异以及 MTK 平台上的协商优先级QCQuick Charge走的是 D/D- 上的模拟握手通过线上电压等级0.6V/3.3V 等以及短脉冲序列告诉适配器“我要 9V 还是 12V”。PD 走的是 CC 上数字信号通过 BMC 编码、双向消息协商 PDO。两者协议栈完全不同Type-C 口上又往往共用一个物理接口所以驱动里要做多层识别。对于 MTK 平台充电协商优先级大致是检测到 UFP 模式下 CC 上有 Rp说明接入了 DFP先做 USB 标准检测SDP/CDP/DCP初步拿到 500mA/1.5A 等级同时进行 PD BIST、SVID 发现如果对方支持 PD 就走 PD 协商PD 不支持再看是否 QC 握手D/D- 电压再不行退回 BC1.2 的 DCP 电流等级这个优先级顺序很容易被厂商魔改比如有些魔改充电头对 PD 的 SVID 回复不标准驱动可能超时后切到 QC又切回 PD翻来覆去导致电流抖动。遇到这类问题最好先固定用标准 PD 适配器做基线验证再逐步增加第三方充电器。3.3 Android15 的 Type-C 框架与“无法投屏”的真相Android15 里 Type-C 相关框架主要新增和加强了 Type-C 状态同步、UsbPortManager 对角色切换的描述同时对 DisplayPort Alt Mode 的策略更严格。很多人在 MTK6769 平台上把系统从 Android13 升级到 Android15 后发现插上 Type-C 转 HDMI 线投屏失效但充电正常。这里的关键在于 Android15 的typec框架会把mode状态拆得更细USB 数据角色DFP/UFP和 DisplayPort Alt ModeDP 模式是两个独立状态需要驱动同时上报正确。如果上层通过typec_port_register_altmode注册了 DP SVID但usb_role上报的时机和 DP 状态不一致系统就会认为发生了冲突宁可停用副功能只保留充电。真正排查时我会先看/sys/class/typec/port0/port0-dp/下有没有active节点再看内核日志里typec_dp_configure是否执行了。很多“Android15 无法投屏”案例的根因就是设备的 USB 控制器在 DP 模式下没有正确让出数据通路驱动要在set_orientation和dp_altmode回调里做一次电源状态与角色切换的时序配合。4. 设备树配置与 sysfs 节点在 Android15 里摸清充电路径软件协议栈层面对齐后设备树和 sysfs 才是真正落地的地方。MTK 不像高通的充电框架那样一家独大它由mtk_charger、mt6370_charger、hal和上层PowerSupply共同组成。设备树里任何一个节点的字段写错都可能造成“驱动 probe 成功了但协商结果没接上”。4.1 设备树中 TCPC 节点和 PD PDO 的写法以常见的 MT6370 TCPC 节点为例设备树里要配置 Rp 等级、PD 相关数据、以及首选的数据/电源角色。下面是一个典型的片段mt6370_pmu { tcpc { compatible mediatek,mt6370-tcpc; tcpc,rp_level 0; /* 0: 默认, 1: 1.5A, 2: 3A */ tcpc,en_pmctrl_by_pd 0; tcpc,pd_listen 1; pd-data { pd,source-pdo-size 2; pd,source-pdo 0x0001902c /* 9V3A Fixed PDO */ 0x0002d0dc /* 15V3A Fixed PDO */ ; }; }; };这段代码里pd,source-pdo的值是固定 32 bit 格式。以0x0001902c为例bit[31:28] 是固定电源类型5 表示 Fixed Supplybit[29:26] 是 10mA 为单位的最大电流0x2c换成十进制是 44也就是 440mA这里要注意计算方式实际不同平台定义略有差异最好对着内核里的enum tcpm_pdo_type和宏PDO_FIXED_VAR去解析。具体的 PDO 解析公式电压值mV在 bit[25:10]以 50mV 为步进电流值mA在 bit[29:26]Fixed 为 10mA 步进Source 可能有 250mA 步进如果设备树里的 source-pdo 和实际充电器支持的 PDO 没有交集PD 协商会停在SNK_READY状态但永远拿不到大电流。调试时可以用cat /sys/class/typec/port0/port0-source/pdos查看本端宣告的 PDO用cat /sys/class/typec/port0/port0-partner/pdos查看对端能力。4.2 mtk_charger 的充电路径与电流限制项PD 协商完成只是定义了 VBUS 能够提供多少电流真正决定“电池侧充多少”的是充电 IC 和充电路径上的各个限制。MTK 平台常见的限制有OVP / OCP / OTP 阈值输入电流限制Input Current Limit充电电流限制Fast Charging Current温度补偿曲线JEITA 与热敏电阻无线充/OTG 优先级这些限制项在中层mtk_charger里有一个struct chg_alg_device和对应的热插拔回调。很多“PD 协商 9V 成功但电流只有 500mA”的问题其实是充电驱动侧认为over_voltage标志置上把输入电流强行限制在了安全值。调试时不要只盯 PD 日志还要看每个 power supply 的current_max和online。4.3 关键 sysfs 节点与读写技巧在 Android15 上最常用的现场取证点位是这几个文件# 查看 Type-C 端口状态与角色 cat /sys/class/typec/port0/data_role cat /sys/class/typec/port0/power_role cat /sys/class/typec/port0/port0-partner/pdos cat /sys/class/typec/port0/port0-source/pdos # 查看充电路径的实时状态 cat /sys/class/power_supply/usb/online cat /sys/class/power_supply/usb/voltage_now cat /sys/class/power_supply/usb/current_max cat /sys/class/power_supply/battery/status cat /sys/class/power_supply/battery/current_now如果current_max显示的是 500000500mA而 partner PDO 里有 3A那说明问题在充电驱动或上层策略如果pdos为空那说明 PD 协商没有成功问题在物理层或协议栈。顺序先看端口状态再看 PDO最后查充电通路一般半小时内能定位到层。5. 实战走查一次“能识别不充电”的完整排查链路理论部分讲到位了下面分享一次我最近在 MTK6769 上处理的真实问题。现象特别典型插入一个支持 PD3.0 的 65W 充电器系统显示“正在快速充电”5 分钟后电流只充了 2%用电流表看只有 0.2A 左右。这个案例的整个排查思路希望能成为你日常排障的参考模板。5.1 先把现象拆成三个独立问题我习惯把这类现象拆成三层物理检测是否成功、协议协商是否达成、充电路径是否实际打开。每一步都有对应日志和 sysfs 节点不猜测。第一步插上充电器后立刻抓dmesg看 TCPC 上报的状态adb shell dmesg | grep -i tcpc正常场景下应该能看到 RPs 相关的状态切换大概长这样不同版本具体打点有差异[ 128.330911] TCPC 0: CC13 CC20, RP0, roleUFP [ 128.331012] tcpc 0: typec_attach:0, polarity0 [ 128.331120] tcpc 0: entering UFP mode...如果这里 CC 状态压根没变化说明物理检测没通过去量 CC 电压如果进入了 UFP 模式但role反复跳动可能是 Rp/Rd 配置不对称或者线缆拉载有问题。第二步确认 PD 协商过程。抓 PD 日志adb shell dmesg | grep -i pd_重点看有没有GoodCRC、Request、PS_RDY这几个关键消息。正常的协商顺序大概是Source 发送 Source_CapabilitiesSink 回复 GoodCRC再决定要不要 Request双方对 Request 确认最后 Source 发 PS_RDY如果卡在Request之后没有PS_RDY说明 Sink 请求了某个 Source 不接受的 PDO如果卡在Source_Capabilities之后没有进入SNK_READY大概率是协议层的超时参数有问题。第三步看usbpower supply 是否已经切换电压cat /sys/class/power_supply/usb/voltage_now如果显示 90000009V说明 PD 协商成功、VBUS 已升压。问题就集中到了充电 IC 输入侧为什么不肯拉电流。5.2 日志显示“协商成功”问题却在充电 IC 的限制寄存器那次排查到第三层voltage_now已经是 9Vpdos也显示了 3A PDO但current_max只有 500mA。很明显PD 协商链路是通的限制发生在充电 IC 或充电路径向。接着抓mtk_charger相关的日志adb shell dmesg | grep -i mtk_charger日志里报了一个input current limit changed: 500mA, reason: over_voltage。这个over_voltage标志让我一愣VBUS 明明已经稳定在 9V为什么还判定过压后来把万用表接到 VBUS 对地电容上充电瞬间电压毛刺冲到 11.8V超过了充电 IC 内置 OVP 的 10.5V 阈值。原因找到了板子上 VBUS 到充电 IC 之间的规划电容太小PD 协商完成后由 5V 切换到 9V 的瞬间环路响应不过来产生高压尖峰。充电 IC 为了保护自己把输入电流限制在 500mA。5.3 修复方案与验证修复不是改软件而是把 VBUS 入口的电容从 0.1uF 加到 4.7uF 陶瓷电容并且在充电 IC 前面保留一颗小阻值的磁珠做阻尼。改完后再插 65W 充电器current_max变成 3000000电池侧电流也上到了 2.8A 左右曲线终于正常了。这个例子说明PD 协议调试不能只看协议层充电 IC 自己的保护策略也会跟协议交互。遇到“协商成功但电流上不去”时除了日志别忘了用示波器抓 VBUS 切换瞬间的波形。软件再对硬件毛刺照样给你限流。6. 兼容性、热插拔和温升Type-C 充电调试里容易忽略的最后一公里前面几节已经能让大多数 PD 充电问题跑通但兼容性和稳定性问题才是项目量产前的真正门槛。很多实验室里插原装充电器没问题一上市场就被客服打爆电话原因都藏在这一节。6.1 线缆质量造成的“协商时好时坏”Type-C 线缆水很深。E-Marker 芯片、CC 线缆阻抗、屏蔽层、插头镀层都会影响 PD 握手质量。我遇到过一批第三方 C-to-C 线插上去偶发只能 5V/500mA用示波器看 CC 波形发现上升沿严重过冲导致 BMC 解码偶尔出错。这种问题没有一劳永逸的代码修复只能做两件事一是把 TCPM 的重试次数从默认 3 次调到 5 次缓解瞬时误码二是在兼容性测试用例里专门纳入“线缆库”固定选 5 款市售主流线缆做回归。量产项目里“换线就好”的说法本质上就是这里没跑透。6.2 热插拔时序和角色切换冲突Type-C 支持热插拔但热插拔瞬间的动作顺序有严格要求。断开时应该先断开 VBUS再上报typec_disconnect接入时应该先进入 attach 状态再触发 PD 协商最后打开 VBUS。如果驱动里把“打开 VBUS”和“PD 协商完成”的先后顺序写反就会出现插拔瞬间 VBUS 上有电但 CC 状态未就绪的情况轻则误判重则打坏对端。MTK 平台在tcpc_manager里对PR_SWAP电源角色切换和DR_SWAP数据角色切换有独立处理。Android15 的 OTG 场景下如果手机上插了一个 U 盘同时又想给手机充电系统要优雅地从 UFP 切到 DFP 再切回去。这类切换里最容易出问题的是充电驱动没有正确响应PR_SWAP之后的重新协商请求导致角色切换后充电电流变成 0。6.3 温升对 PD 固定的影响不是 Bug是保护最后说一个经常被误判为 Bug 的情况大电流充电持续 10 分钟后电流突然掉下来。多数时候不是协商失败而是充电 IC、电池或 PCB 板温超过了 JEITA 保护线系统主动降流。这个行为在日志里通常只表现为mtk_charger的thermal update信息不会报 error。如果你们项目因为温升降流被客户投诉不能简单关掉热保护而是要优化充电曲线把 PD 协商的大电流 PDO 设定为短时快充之后降到一个温升可控的值。MTK 平台里可以在充电配置表的cool_bat_cur、warm_bat_cur这类字段里调整而不是去改 PD 协议栈的协商结果。回到开头说的那次调试如果一开始我就按着“先隔离物理检测、再验证协议协商、最后查充电路径”的顺序走大概不到两个小时就能定位到那个电容问题不用在日志里瞎转一整天。Type-C PD 充电调试就是这样链路长、层级多但只要把每一层的职责和观察点都搞清楚它其实是最讲道理的一个模块。
返回列表