You need to enable JavaScript to run this app. Sunxi(全志)系列ARM SoC 基于ATF捕获唤醒原因的实现方法
优惠活动
大模型
产品
解决方案
定价
更多

Sunxi(全志)系列ARM SoC 基于ATF捕获唤醒原因的实现方法

Sun50i架构基于ATF的通用唤醒原因捕获实现方案

前期设计的常见踩坑点

  • 直接读取GICC寄存器识别中断源的思路有时序问题:Sunxi平台的GICC寄存器域随CPU核心电源域联动下电,系统进入深睡时GICC的所有寄存器上下文会完全丢失,唤醒初期直接读GICC地址得到的是上电后的默认值,根本无法反映触发唤醒的中断状态。
  • 寄存器选取的电源域不对:跨深睡状态保留中断状态必须选和VDD_RTC同电源域、不掉电的寄存器组,也就是GICD中断分发器的状态寄存器、RTC域通用寄存器、RTC域外设(GPIO、RTC控制器)的中断状态寄存器,只有这些资源才会在深睡期间保留有效值。

ATF代码的具体植入位置

按照唤醒流程的执行时序,对应逻辑要放在三个固定节点,避免和GIC初始化、电源域上电流程冲突:

  1. 挂起前置采样节点
    对应ATF中psci_plat_pm_ops结构体的pwr_domain_suspend回调,在CPU触发WFI、正式关闭核心电源域之前执行:这时候GIC所有寄存器还保持有效状态,是读取中断状态的唯一可靠时机。
  2. 唤醒最早入口节点
    对应BL31的AArch64低功耗异常向量入口,也就是MMU尚未使能、电源域刚完成上电、GIC重新初始化之前的最早执行路径:这一步要尽早读取VDD_RTC域保留的状态值,避免后续GIC重新初始化时把中断pending位清掉,丢失唤醒源信息。
  3. 上层接口上报节点
    对应BL31完成PSCI系统上下文初始化后的流程,把之前缓存的唤醒原因值写入平台定义的共享内存段,供上层UEFI、内核启动阶段读取,不需要上层重复扫描中断状态。

跨复位状态的标记实现方案

利用VDD_RTC域下不受普通复位、深睡断电影响的RTC通用寄存器实现状态传递,具体操作流程:

  • 寄存器选型:选用RTC域保留的GPREGx寄存器(只要VDD_RTC不掉电,数值会持续保留),划分为两个固定存储单元:一个单元存深睡进入标记,一个单元存唤醒原因编码值。
  • 写入逻辑:挂起前置采样完成后,先把采样得到的唤醒源编码写入GPREG的唤醒原因单元,再往标记单元写入预设的固定魔术值(例如0x5A5A5A5A),表示后续唤醒需要读取缓存值。
  • 读取逻辑:唤醒入口阶段先校验标记单元的魔术值,如果值匹配,就读取原因单元的编码值作为本次唤醒的依据,随即把标记单元和原因单元的值清零,避免后续冷启动、软复位场景下读到残留的旧值,造成误判。

中断检测逻辑的代码修正

原参考代码的GICC偏移访问逻辑全部需要替换为对GICD域状态寄存器的访问,对应的寄存器访问框架:

#define mmio_read_32(c)      ({unsigned int __v = (*(volatile unsigned int *)(c)); __v; })
// GICD基地址(位于VDD_RTC电源域,随具体SoC调整地址映射)
#define GICD_BASE            0x01c81000
// 遍历GICD所有ISPENDR寄存器位,捕获置位的唤醒中断
INFO("GIC SGI pending 状态:   0x%08x\n", mmio_read_32(GICD_BASE + 0x0200));
INFO("GIC PPI pending 状态:   0x%08x\n", mmio_read_32(GICD_BASE + 0x0204));
INFO("UART 中断 pending 状态: 0x%08x\n", mmio_read_32(GICD_BASE + 0x0208));
INFO("TWI 中断 pending 状态: 0x%08x\n", mmio_read_32(GICD_BASE + 0x0209));
INFO("显示控制器 pending 状态:0x%08x\n", mmio_read_32(GICD_BASE + 0x021f));
// 追加RTC域GPIO、RTC闹钟的中断状态读取,这类源不会经过核心域的GICC路径
INFO("GPIO 唤醒 pending 状态: 0x%04x\n", mmio_read_32(RTC_GPIO_BASE + 0x0000));
INFO("RTC 闹钟 pending 状态:  0x%04x\n", mmio_read_32(RTC_BASE + 0x0010));

完整唤醒原因判定闭环路径

按照执行顺序搭建判定逻辑,覆盖Sunxi平台的全量唤醒场景:

  1. 初判唤醒类型:唤醒入口首先读取RTC域的系统状态寄存器,结合GPREG的标记值判断:如果GPREG值为上电默认初始值,判定为冷启动,直接走正常初始化流程;如果GPREG值匹配深睡魔术标记,判定为深睡唤醒,进入源识别流程。
  2. 匹配唤醒源映射:把缓存的状态编码值和预先定义的唤醒源映射表比对,识别具体的触发源(UART输入唤醒、RTC定时唤醒、GPIO按键唤醒、AXI错误异常唤醒、PMU中断唤醒等),对NMI这类特殊中断也通过对应位的置位状态完成捕获。
  3. 状态清理:完成唤醒原因记录后,把RTC GPREG里的缓存值全部清空,确保下一次冷启动不会读到残留值。
  4. 上层透传:把捕获到的唤醒原因通过ATF定义的标准平台接口暴露,供后续bootloader、内核阶段读取,不需要上层重复访问底层硬件寄存器。

内容的提问来源于stack exchange,提问作者Drakes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 20:45:10