1. 项目概述:嵌入式系统的“能源心脏”PRCM
在嵌入式系统开发领域,尤其是基于德州仪器(TI)OMAP、AM系列等复杂SoC的项目中,电源、复位与时钟管理(PRCM)模块是决定系统稳定性、功耗和性能的基石。你可以把它想象成一座现代化城市的“能源与交通调度中心”:它不仅要确保城市(SoC)的各个区域(功能模块)在需要时有电、有路(时钟),还要能在空闲时精准地关闭路灯、降低电压以节省能源,甚至在发生意外时,能迅速、有序地重启特定区域(复位)。我接触过不少项目,初期因为对PRCM配置不当,导致系统莫名死机、功耗居高不下,或是外设无法正常工作的“玄学”问题,最后追根溯源,往往都是这个“调度中心”的指令没下对。
PRCM模块的核心价值,在于它提供了一套硬件级别的、精细化的电源与时钟控制机制。它远不止是简单的“开关”。通过配置一系列映射在内存地址空间的控制寄存器,开发者可以动态地管理每个硬件模块(如USB控制器、GPU、视频编解码器)的供电状态、复位释放时机以及时钟的开启与门控。这对于电池供电的物联网设备、移动终端来说至关重要,直接关系到产品的续航能力。同时,正确的上电、下电和复位序列也是系统可靠启动和抗干扰的保障。本文将以TI官方技术手册(如SPRUGZ8G)中典型的PRCM寄存器为例,深入解析其工作原理、配置方法,并分享我在实际调试中积累的配置心得与避坑指南。无论你是正在学习嵌入式底层驱动的学生,还是面临功耗优化挑战的工程师,理解PRCM都将让你对系统的掌控力提升一个维度。
2. PRCM模块核心概念与设计逻辑解析
在直接操作寄存器之前,我们必须先建立正确的认知模型。PRCM不是一个单一的功能,而是电源(Power)、复位(Reset)、时钟(Clock)三种管理的有机结合体,它们相互关联,共同构成了SoC的“生命体征”管理系统。
2.1 电源域、时钟域与复位域的三位一体
这是理解PRCM的第一个关键点。SoC内部并非铁板一块,而是被划分成多个相对独立的“域”。
-
电源域
:指共享同一套供电电源的模块集合。PRCM可以控制整个电源域的开启(ON)、关闭(OFF)或进入低功耗状态(如RETENTION)。例如,
PM_ACTIVE_PWRSTCTRL寄存器控制的ACTIVE域,可能包含DSP核心及其专用内存。关闭一个未使用的电源域是省电的最有效手段。 -
时钟域
:指共享同一时钟源的一组逻辑。即使电源域开启,也可以通过门控时钟(Clock Gating)关闭该域内部分或全部模块的时钟,使其动态功耗降至近乎为零。
CM_xxx_CLKSTCTRL这类寄存器就用于管理时钟域的状态转换(如ON-ACTIVE与ON-INACTIVE之间的切换)。 -
复位域
:指共享同一复位信号源的模块集合。PRCM可以控制对某个域进行全局复位或局部复位。
RM_xxx_RSTCTRL寄存器就用于断言或释放复位信号。
这三者之间存在严格的依赖关系,通常遵循“电源 -> 复位 -> 时钟”的使能顺序,以及相反的关闭顺序。试图给一个没电的模块提供时钟,或者在不解除复位的情况下操作模块,都是无效的。
2.2 模块级控制:STBYST, IDLEST, MODULEMODE
这是开发者最常打交道的层面。对于像USB、SATA、GPU(SGX)这样的具体硬件模块,PRCM提供了更细粒度的控制寄存器,如
CM_DEFAULT_USB_CLKCTRL
。
-
MODULEMODE (位[1:0]) :这是 软件配置 模块工作模式的 命令寄存器 。它决定了模块的“基本运行权限”。
-
0x0 (DISABLED):软件禁用模块。任何通过互联总线(INTERCONN/OCP)对模块的访问都会产生错误(除非是来自模块的唤醒事件)。这是模块的默认、最低功耗状态。 -
0x2 (ENABLE):软件显式使能模块。此时,功能时钟保证存在,接口时钟则可能根据时钟域状态被门控。只要模块处于此模式,其所在的电源域 不能 进入睡眠状态。这是模块正常工作的前提。 -
0x1和0x3:通常标记为RESERVED,禁止使用。 -
核心逻辑
:你想让一个模块干活,第一步必须是将其
MODULEMODE设置为ENABLE。这相当于给模块颁发了“上岗许可证”。
-
-
IDLEST (位[17:16]) :这是反映模块 空闲状态 的 状态寄存器 (只读)。它告诉你模块在当前配置下的实际运行情况。
-
0x0 (Func):模块全功能运行,包括其内部互联接口都正常工作。这是理想状态。 -
0x1 (Trans):模块正在过渡状态,可能是正在唤醒、进入睡眠或中止睡眠。 此时访问模块可能不稳定 。 -
0x2 (Idle):模块处于空闲模式,仅互联接口部分可能在工作。如果模块有独立的功能时钟,它可能仍能工作。 -
0x3 (Disable):模块被禁用,无法访问。 -
核心逻辑
:在配置
MODULEMODE为ENABLE后,你必须轮询或等待IDLEST变为Func,才能确认模块已准备好接受指令。这是一个典型的“命令-确认”过程。
-
-
STBYST (位[18]) :这是反映模块 待机状态 的 状态寄存器 (只读)。它指示模块是否处于软件控制的待机模式(通常比空闲模式更深度的省电状态)。
-
0x0 (Func):模块功能正常(不在待机)。 -
0x1 (Standby):模块处于待机状态。 -
核心逻辑
:
STBYST反映了更深一层的电源管理状态,通常与模块内部的特定待机控制逻辑相关,并非所有模块都支持或意义相同。
-
一个至关重要的实操心得
:
MODULEMODE
是你下的命令,而
IDLEST
是硬件给你的反馈。很多驱动代码的BUG在于,写完了
MODULEMODE
就立刻去操作模块的硬件寄存器,此时模块可能还在过渡状态(
IDLEST=0x1
),导致访问失败。正确的做法是:写入
MODULEMODE
后,加入一个延迟循环,不断读取
IDLEST
,直到其变为
0x0 (Func)
,再进行后续初始化。TI的许多SDK驱动库中,都会有类似
PRCMModuleEnable()
和
PRCMModuleDisable()
的函数,其内部就封装了这个等待过程。
2.3 时钟域状态转换:CLKTRCTRL
对于包含多个模块的时钟域(如
CM_HDVICP_CLKSTCTRL
),
CLKTRCTRL
位域(位[1:0])控制着整个域的睡眠与唤醒策略。
-
0x0 (NO_SLEEP):禁止发起睡眠转换。这是一个保持活跃的状态。 -
0x1 (SW_SLEEP): 软件强制 启动睡眠转换。当域内所有模块都空闲时,时钟硬件会尝试将域切换到低功耗的ON-INACTIVE状态。 -
0x2 (SW_WKUP): 软件强制 启动唤醒转换,将域从ON-INACTIVE状态拉回ON-ACTIVE状态。 -
0x3 (HW_AUTO): 硬件自动 管理。根据域内模块的活动情况(通常由硬件空闲检测器判断),自动决定进入睡眠或唤醒。这是最智能、最常用的模式。
配置策略
:在系统初始化时,对于需要动态功耗管理的域,通常设置为
HW_AUTO
。当需要手动确保某个域保持唤醒(例如在进行关键实时任务时),可临时切换为
NO_SLEEP
。
SW_SLEEP
和
SW_WKUP
则用于实现更精细的软件调度策略。
3. 关键寄存器详解与配置实战
理解了上述概念,我们再来剖析手册中的具体寄存器,就会清晰很多。我们选取几个有代表性的进行深度解读。
3.1 模块时钟控制寄存器:以CM_DEFAULT_USB_CLKCTRL为例
这个寄存器是控制USB控制器模块时钟的典型代表。其复位值为
0x70000
,我们拆解来看:
- 位[31:19], [15:2] :保留位。必须写入0,读取值不确定。
-
位[18] STBYST
:复位值为
1(Standby)。这意味着上电后,硬件默认报告USB模块处于待机状态。 -
位[17:16] IDLEST
:复位值为
3(Disable)。这与MODULEMODE的复位值0(DISABLED)是对应的,表明模块初始状态就是被禁用且不可访问。 -
位[1:0] MODULEMODE
:复位值为
0(DISABLED)。这是软件控制的起点。
配置使能USB模块的标准流程如下 :
-
确认基地址
:首先需要知道
CM_DEFAULT_USB_CLKCTRL寄存器在内存映射中的绝对地址。这通常在芯片的数据手册或内存映射表中定义。假设PRCM模块基地址为0x4A00_0000,该寄存器偏移为0x58,则其绝对地址为0x4A00_0058。 -
写入使能命令
:向该地址写入值,将
MODULEMODE字段设置为0x2(ENABLE)。需要注意的是,我们必须使用“读-修改-写”操作,避免影响其他保留位和状态位。通常通过设置位域(bit-field)操作或清晰的掩码操作来实现。
// 假设已定义寄存器地址宏和访问函数
#define CM_DEFAULT_USB_CLKCTRL (*(volatile uint32_t*)(PRCM_BASE + 0x58))
void enable_usb_module(void) {
uint32_t reg_val;
// 1. 读取当前寄存器值
reg_val = CM_DEFAULT_USB_CLKCTRL;
// 2. 清除MODULEMODE位域(位[1:0]),并设置为ENABLE(0x2)
reg_val &= ~(0x3); // 清除低2位
reg_val |= (0x2); // 设置为0x2
// 3. 写回寄存器
CM_DEFAULT_USB_CLKCTRL = reg_val;
}
-
等待模块就绪
:写入后,不能立即操作USB控制器。必须等待
IDLEST状态变为0x0 (Func)。
// 等待模块进入功能状态
void wait_for_usb_module_ready(void) {
uint32_t timeout = 100000; // 设置一个超时,防止死循环
while (timeout--) {
if ((CM_DEFAULT_USB_CLKCTRL & (0x3 << 16)) == 0x0) { // 检查IDLEST位[17:16]是否为00
break; // 模块已就绪
}
// 可加入微小延时
// delay_us(1);
}
if (timeout == 0) {
// 处理超时错误:模块无法就绪,可能是硬件故障或时钟未配置
handle_error();
}
}
避坑指南 :
-
顺序性
:务必先配置好模块的输入时钟源(这通常涉及PLL和时钟分频器的配置,属于另一个层面),再使能模块的
MODULEMODE。一个没有时钟信号的模块是无法完成状态转换的。 -
超时处理
:等待
IDLEST的循环必须包含超时机制。如果模块因时钟问题、电源问题或硬件故障始终无法就绪,超时机制能防止系统死锁,并给出明确的错误定位信息。 - 上下文考虑 :在操作系统环境中,这段配置代码可能需要在早期初始化阶段(如引导加载程序或内核启动早期)执行,且需要确保是原子操作或处于关中断等保护状态下,避免并发访问问题。
3.2 时钟域状态控制寄存器:以CM_HDVICP_CLKSTCTRL为例
这个寄存器管理HDVICP(高清视频图像协处理器)所在时钟域的状态。其复位值为
0x1
,即
CLKTRCTRL=0x1 (SW_SLEEP)
,这是一个比较保守的初始状态,防止域自动进入睡眠。
-
位[8] CLKACTIVITY_HDVICP_GCLK
:这是一个宝贵的
状态指示位
。它直接告诉你
HDVICP_GCLK这个时钟在域内是活跃(Act)还是被门控(Inact)。在调试功耗问题时,读取这个位比测量信号更直接。 - 位[1:0] CLKTRCTRL :控制策略选择。
典型配置场景 :
-
场景一:默认自动功耗管理
。系统启动后,希望HDVICP域在不工作时自动睡眠以省电。
// 设置为硬件自动管理 (HW_AUTO) CM_HDVICP_CLKSTCTRL = (CM_HDVICP_CLKSTCTRL & ~0x3) | 0x3; -
场景二:确保实时性
。当需要HDVICP处理一个高优先级视频流时,不希望域被自动门控引入唤醒延迟。
// 临时禁止睡眠 (NO_SLEEP) CM_HDVICP_CLKSTCTRL = (CM_HDVICP_CLKSTCTRL & ~0x3) | 0x0; // ... 执行关键视频处理任务 ... // 任务完成后恢复自动管理 CM_HDVICP_CLKSTCTRL = (CM_HDVICP_CLKSTCTRL & ~0x3) | 0x3; -
场景三:软件深度睡眠
。在系统进入待机前,由软件统一将所有可睡眠的域强制进入睡眠。
// 软件强制睡眠 (SW_SLEEP) CM_HDVICP_CLKSTCTRL = (CM_HDVICP_CLKSTCTRL & ~0x3) | 0x1;
实操要点
:
CLKACTIVITY_xx
位是只读的,但它是一个极佳的调试工具。当你怀疑某个模块不工作是因为没时钟时,先读一下这个位,如果显示
Inact
,那问题很可能就出在时钟域的状态或上游时钟源上。
3.3 电源与复位控制寄存器:以PRM_ACTIVE域为例
PRM_ACTIVE
相关寄存器展示了电源和复位管理的更底层接口。
ACTIVE
域通常包含DSP等核心计算单元。
-
PM_ACTIVE_PWRSTCTRL (偏移0h) :控制电源状态。
-
PowerState位域:写入0x3使域上电(ON),写入0x0使其掉电(OFF)。 这是一个高风险操作 !将正在运行逻辑的域直接掉电会导致数据丢失和系统崩溃。通常只在系统深度睡眠或动态电源管理框架下,由经过严格测试的、知晓所有依赖关系的统一电源管理代码来操作。 -
LowPowerStateChange位:这是一个高级功能,允许域在已睡眠的情况下,进一步进入更深的低功耗状态,而无需先唤醒它。用于极致功耗优化场景。
-
-
PM_ACTIVE_PWRSTST (偏移4h) :电源状态状态寄存器。用于查询域的当前状态(
PowerStateSt)、逻辑状态(LogicStateSt)、内存状态(Active_MEM_StateSt)以及是否有状态转换正在进行(InTransition)。在发起电源状态改变命令后,必须查询此寄存器确认转换完成。 -
RM_ACTIVE_RSTCTRL (偏移10h) :复位控制寄存器。
-
GEM_SW_RST:DSP的热复位控制。写入1断言复位,写入0释放复位。 -
GEM_LRST:DSP的本地复位控制。 -
操作顺序
:通常,释放复位的操作是在电源稳定(
PowerStateSt为ON)且时钟就绪之后进行的。断言复位则可能在关闭模块前进行,以确保模块处于确定状态。
-
一个完整的、安全的域上电序列示例 :
-
检查
PM_ACTIVE_PWRSTST,确认域当前处于OFF状态且无转换进行(InTransition=0)。 -
配置
PM_ACTIVE_PWRSTCTRL的PowerState为ON (0x3)。 -
轮询
PM_ACTIVE_PWRSTST的PowerStateSt和InTransition位,直到状态变为ON且转换结束。 - 等待电源稳定(可能需要微秒级延时,具体见芯片数据手册的电源斜坡时间)。
-
确保该域的时钟源已配置并稳定(通过相应的
CM_xxx_CLKSTCTRL或PLL配置)。 -
配置
RM_ACTIVE_RSTCTRL,释放相关复位信号(如将GEM_SW_RST和GEM_LRST写0)。 - 此时,域内的DSP内核才可能开始执行其引导代码。
4. 系统级PRCM配置策略与最佳实践
了解了单个寄存器的操作,我们还需要从系统视角来规划PRCM的配置。这通常是在Bootloader或操作系统内核早期初始化阶段完成的。
4.1 启动阶段的PRCM初始化流程
系统上电后,硬件可能有默认的时钟和电源状态,但往往不是应用所需的最优或最终状态。一个稳健的启动流程如下:
- 锁定与安全配置 :首先,可能需要对一些关键的PLL和时钟配置寄存器进行写保护解锁(如果存在锁机制)。
- 核心时钟树配置 :配置主振荡器、PLL倍频、分频器,生成系统所需的各种基础时钟频率(如ARM内核时钟、总线时钟、外设源时钟等)。 这一步必须在使能大多数模块之前完成 。
- 使能必需的外设时钟 :为Bootloader���行所必需的外设(如串口Debug UART、启动存储器接口如MMC/SD、系统定时器等)使能时钟。遵循“先配时钟源,再设MODULEMODE,后等IDLEST”的流程。
-
配置时钟域策略
:根据系统设计,将各时钟域的
CLKTRCTRL设置为HW_AUTO或NO_SLEEP。对于在Bootloader阶段就要使用的域,可先设为NO_SLEEP确保稳定。 -
内核与核心域上电
:如果Bootloader需要搬移大量数据或进行复杂解压,可能需要提前使能某些核心电源域(如
ACTIVE域)。 - 移交操作系统 :Bootloader将配置好的PRCM状态传递给操作系统内核。现代操作系统(如Linux)都有成熟的电源管理框架(如CPUFreq、CPUIDLE、Runtime PM),它们会在运行时动态调整PRCM设置。
4.2 运行时动态电源管理
在操作系统运行后,PRCM的管理变得更加动态:
-
基于Runtime PM的模块管理
:Linux的Runtime PM框架会为每个设备驱动跟踪其“使用计数”。当没有用户(进程)打开一个设备时,驱动会尝试将其挂起(suspend),其中关键一步就是通过PRCM关闭该模块的时钟(将
MODULEMODE设为DISABLED),甚至请求其所在电源域进入低功耗状态。当设备再次被打开时,驱动会将其恢复(resume)。 - CPU调频与调压 :通过PRCM或专用的DVFS(动态电压频率调整)控制器,根据CPU负载动态调整内核时钟频率和电压,在性能和功耗间取得平衡。
-
系统休眠
:在系统进入待机(Suspend-to-RAM)或休眠(Suspend-to-Disk)状态时,内核的电源管理核心会按照预定义的顺序,调用每个驱动的
suspend回调,最终通过PRCM关闭大部分电源域,仅保留唤醒源所在域的极低功耗运行。
4.3 调试技巧与常见问题排查
PRCM配置问题导致的故障现象千奇百怪,但排查思路有迹可循。
问题1:外设无法访问,读写寄存器全为0或全为F。
-
排查步骤
:
-
检查时钟
:确认该外设模块的
MODULEMODE是否已设置为ENABLE。读取IDLEST状态,确认是否为Func (0x0)。 -
检查复位
:如果模块有独立的复位控制(在
RM_xxx_RSTCTRL中),确认复位信号是否已释放。 -
检查电源域
:查询模块所在电源域的状态寄存器(如
PM_xxx_PWRSTST),确认是否为ON状态。 -
检查时钟域活动
:读取
CLKACTIVITY_xx位,确认时钟是否真的在活动状态。 - 检查内存映射 :再次核对寄存器地址是否正确,确保你访问的是正确的物理地址(在MMU启用前)或虚拟地址(在MMU启用后)。
-
检查时钟
:确认该外设模块的
问题2:系统功耗高于预期。
-
排查步骤
:
-
扫描IDLEST
:在系统空闲时,遍历所有外设模块的
CLKCTRL寄存器,读取其IDLEST和STBYST。如果某个本应空闲的模块显示为Func,说明其未被正确挂起。 -
扫描CLKACTIVITY
:检查各时钟域的
CLKACTIVITY位,找到本应门控却仍显示活跃的时钟。 -
检查时钟域模式
:确认非关键时钟域的
CLKTRCTRL是否设置为HW_AUTO,允许其自动睡眠。 - 使用功耗测量工具 :结合电流探头和芯片的功耗追踪工具,观察关闭特定模块或域时的电流变化,定位“耗电大户”。
-
扫描IDLEST
:在系统空闲时,遍历所有外设模块的
问题3:系统从低功耗状态唤醒失败。
-
排查步骤
:
-
确认唤醒源配置
:唤醒源模块(如GPIO中断控制器、RTC、USB等)的时钟和电源必须在睡眠期间保持有效。检查其
MODULEMODE和所在域的CLKTRCTRL配置。 - 检查唤醒路径 :有些SoC要求唤醒事件必须能触发整个电源域的上电序列。检查相关电源域的唤醒使能位。
- 分析唤醒流程 :单步调试唤醒早期的代码(通常在Bootloader或内核的resume入口),查看PRCM状态恢复的序列是否正确,是否有模块在恢复时钟前就被访问了。
-
确认唤醒源配置
:唤醒源模块(如GPIO中断控制器、RTC、USB等)的时钟和电源必须在睡眠期间保持有效。检查其
一个实用的调试习惯
:在系统初始化代码中,实现一个
prcm_dump()
函数,它能将关键PRCM寄存器的状态以可读格式打印出来。在遇到问题时,对比正常和异常时的dump信息,差异点往往就是问题的根源。
5. 进阶话题:PRCM配置的自动化与可移植性思考
随着项目复杂度和芯片迭代速度的提升,手动编写和维护PRCM配置代码变得越来越困难。这就需要引入一些工程化的方法。
1. 基于寄存器定义头文件与驱动库
TI通常会提供芯片支持包,其中包含完整的寄存器地址和位域定义头文件(如
hw_prcm.h
)以及封装好的驱动库函数(如
PRCMModuleEnable()
、
PRCMPowerDomainOn()
)。
强烈建议使用这些官方库
,它们经过了大量测试,隐藏了底层细节(如等待超时、操作顺序),能极大提高开发效率和代码可靠性。
2. 设备树(Device Tree)中的时钟与电源描述
在现代Linux内核中,外设的时钟和电源依赖关系是在设备树(
.dts
文件)中描述的。例如:
usb0: usb@4a0a0000 {
compatible = "ti,omap4-usb";
reg = <0x4a0a0000 0x400>;
interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&l4_per_clkctrl OMAP4_USB_CLKCTRL 0>; /* 指向时钟控制器和索引 */
clock-names = "fck";
power-domains = <&power OMAP_POWERDOMAIN_CORE>; /* 指向电源域 */
...
};
内核中的通用时钟框架(Common Clock Framework)和电源域框架会根据这些描述,在驱动探测(probe)时自动去申请并使能所需的时钟和电源资源。驱动开发者通常无需直接操作PRCM寄存器,只需确保设备树描述正确。
3. 芯片差异化的处理 即使是同一厂商的芯片,不同系列甚至不同版本的PRCM设计也可能有差异。寄存器偏移、位域定义、甚至工作流程都可能发生变化。在编写底层代码或移植系统时,必须:
- 仔细核对数据手册 :以当前项目所用芯片的官方最新手册为准。
- 使用条件编译 :在代码中通过芯片型号宏来区分不同的配置。
- 抽象接口 :设计一个统一的PRCM操作接口层,将芯片特定的实现细节隐藏在底层,上层业务逻辑调用统一的API。
6. 总结与核心经验回顾
PRCM是嵌入式系统,特别是复杂SoC开发的深水区之一。它连接着硬件物理特性和软件行为,配置得当则系统稳定高效,配置失误则疑难杂症丛生。回顾多年的项目经验,以下几点体会最为深刻:
第一,理解层次关系是根本。 一定要在脑中清晰地构建出“电源域 -> 复位域 -> 时钟域 -> 具体模块”的层级模型。操作任何一个层级,都要考虑其对上层(依赖)和下层(被依赖)的影响。比如,关闭一个电源域会同时关闭其下的所有时钟和复位;使能一个模块前,必须确保其所在的时钟域和电源域已就绪。
第二,“命令-状态”反馈循环不可或缺。
写
MODULEMODE
、
PowerState
、
CLKTRCTRL
是下命令,读
IDLEST
、
PowerStateSt
、
CLKACTIVITY
是查状态。
永远不要假设命令会立即生效
,一定要等待状态确认。这是嵌入式硬件编程的黄金法则。
第三,善用工具与官方资源。 不要徒手解析PDF手册来计算位偏移。利用好SDK中的头文件、驱动库和配置工具(如TI的SysConfig图形化工具)。在调试时,善用仿真器查看寄存器实时状态,用功耗分析工具关联软件行为与电流变化。
第四,功耗优化是一个系统工程。 PRCM提供了硬件杠杆,但何时拉下杠杆需要软件策略。从简单的空闲时关闭显示屏背光,到复杂的基于负载预测的DVFS和CPU热插拔,都需要软件框架(如Linux PM)的良好支持。PRCM配置是基础,而智能的电源管理策略才是发挥其威力的关键。
最后,PRCM的配置虽然繁琐��但它是你真正“驾驭”一颗复杂芯片的标志。当你能够精准地控制系统中每一份能量的来去,让设备在性能和续航间优雅地舞蹈时,那种对系统的掌控感,正是嵌入式开发的乐趣所在。希望这篇结合了手册解读与实战经验的梳理,能为你拨开PRCM的迷雾,提供一份可靠的导航图。

305


被折叠的 条评论
为什么被折叠?



