Type-C充电事件流:从物理连接到电量显示的代码级追踪
当我们将Type-C充电线插入手机时,屏幕上几乎瞬间出现的充电图标和跳动的电量百分比背后,隐藏着一系列精密的硬件交互和软件协作。本文将深入ADSP(音频数字信号处理器)中的充电管理子系统,揭示从插头接触到电量显示的全链路事件流。
1. 物理连接检测与TCPC状态机
Type-C接口的CC(Configuration Channel)引脚状态变化是充电流程的起点。当充电线插入时,TCPC(Type-C Port Controller)硬件检测到CC1或CC2的电压变化,触发中断信号。
// TCPC事件类型枚举定义 typedef enum _USBPD_TCPC_EVENT_TYPE { USBPD_TCPC_EVENT_CABLE, // CC/Vbus线缆事件 USBPD_TCPC_EVENT_HARDRESET, // PD硬重置信号 USBPD_TCPC_EVENT_LPD, // 液体检测事件 // ...其他事件类型 } USBPD_TCPC_EVENT_TYPE;PmicTccStateMachine_Main_Thread作为TCPC主状态机,持续轮询处理底层事件:
- 状态检测:比较当前状态(CurrStateID)和下一状态(NextStateID)
- 状态迁移:当检测到状态变化时:
- 执行新状态的初始化函数
- 更新硬件寄存器配置
- 刷新上下文状态
- 异常处理:检测VBUS过压、短路等异常情况
关键处理逻辑位于PmicTccStateMachineLevels_Offline_State_Main:
if (cc_status_changed) { // 进入待机状态处理CC变化 NextStateID = PMICTCC_STATE_ID_STANDBY; } else if (current_event == USBPD_TCPC_EVENT_CABLE) { // 检查VBUS状态判断是否进入直充模式 if (snk_vbus_sts && g_typec_connect_status) { enter_direct_charge_mode(); } }状态处理完成后,通过pmic_glink_send_oem_notification向AP侧发送检测结果通知。
2. LPM层的事件路由与协议处理
LPM(Link Power Manager)作为TCPC和上层协议的桥梁,处理来自硬件的Alert事件:
| 事件来源 | 事件类型 | 处理方式 |
|---|---|---|
| TCPC/PHY | USBPD_LPM_EVENT_ALERT | 转发至DPM或PE |
| 定时器 | USBPD_LPM_EVENT_HKTIMER_TO | 检查DPM请求队列 |
| PE协议引擎 | USBPD_LPM_EVENT_PE_REQUEST | 执行PD协议状态机 |
LPM主循环lpm_mainloop的核心逻辑:
while (1) { LpmEvent = event_handler_wait_for_events(&EvtHandler); if (LpmEvent & LPM_EVENTS_NOTIFY_DPM) { lpm_notify_dpm(pLpmCtx); // 异步事件通知DPM } while (pLpmCtx->EvtHandler.Queue.NoOfEvent) { lpm_process_event(pLpmCtx, pInputEvent); } }协议引擎(PE)的状态处理特别关注:
- 硬重置/软重置:根据
nextState标志位执行不同的重置流程 - 消息传输:处理SOP消息的发送/接收状态:
if (pState->Context.bTxPending) { if (pEvent->EvtType == USBPD_LPM_EVENT_ALERT_TRANSMIT_SOP_MESSAGE_SUCCESSFUL) { pState->Context.bTxPending = false; } } - 状态机执行:调用
usbtypec_statemachine_state_run运行当前状态的Main函数
3. DPM的决策与电源管理
DPM(Device Policy Manager)作为充电策略的核心决策层,处理来自LPM的事件通知:
void dpm_notify(DPM_LISTENER* pListener, USBPD_DPM_EVENT_TYPE Event) { switch (Event) { case USBPD_DPM_EVENT_LPM_ASYNC_EVENT: event_handler_set_event(pListener, EVENTTYPE_TO_EVENT(Event)); break; // ...其他事件处理 } }DPM主循环的关键操作:
事件队列更新:将不同来源的事件分类存入队列
- LPM异步事件 →
dpm_queue_lpm_async_event - BM电池管理请求 →
event_handler_add_new_event - OPM UCSI命令 →
ppm_state_run
- LPM异步事件 →
策略决策:在
dpm_process_event中:if (pInputEvent->EventHeader.EvtDest == USBPD_MODULE_PPM) { ppm_state_run(&pDpmCtx->ppm, pInputEvent, &bGoNextState); } else if (pInputEvent->EventHeader.EvtDest == USBPD_MODULE_DPM) { dpm_event_handler(pDpmCtx, pInputEvent); }电源管理:通过PPM(Port Policy Manager)配置充电参数:
void ppm_handle_async_event_update(PPM_CONTEXT* pPpm) { if (pPpm->Context.config.capability.bNumConnector > 0) { update_charging_parameters(); } }
4. AP通信与电量显示
AP与ADSP通过GLINK机制通信,关键交互流程:
UCSI邮箱读写:
// AP→ADSP写入命令 ppm_ucsi_mailbox_write(pMailbox, data_len); // ADSP→AP读取状态 ppm_ucsi_mailbox_read(pReadBuf, buf_size);电量信息上报:
- BM线程通过
battmngr_platform_charger_update更新电源属性 - 调用
pmic_glink_send_power_supply_notification通知AP侧 - AP最终触发
power_supply_changed更新sysfs节点
- BM线程通过
充电状态同步:
typedef struct _USBPD_UCSI_DATA { USBPD_UCSI_CCI_DATA cci; // 连接状态 USBPD_UCSI_GENERIC_CONTROL_DATA control; // 控制命令 USBPD_UCSI_GENERIC_MESSAGE_DATA message_in; // 输入消息 } USBPD_UCSI_DATA;
完整的充电事件流可总结为以下时序:
- TCPC检测CC变化 → LPM → DPM
- DPM决策充电策略 → PPM配置充电IC
- BM监控电池状态 → GLINK通知AP
- AP更新UI显示
在实际调试中,可以通过以下ADSP日志标签追踪事件流:
USBC_TCPC: Type-C连接状态变化 USBC_LPM: 协议层事件处理 USBC_DPM: 策略决策日志 BATT_MNGR: 电池管理信息理解这套事件流转机制,有助于开发者在以下场景快速定位问题:
- 充电图标不显示 → 检查TCPC事件是否上报
- 充电速度异常 → 分析DPM策略决策日志
- 电量显示不准 → 追踪BM到AP的通知链路
通过代码级的流程分析,我们可以看到现代快充系统如何将硬件事件层层传递,最终转化为用户可见的充电状态。这种事件驱动的架构设计,既保证了实时性,又保持了各模块的松耦合。