TMS320x2806x DSP时钟失效检测与NMI看门狗机制深度解析
1. 项目概述:时钟失效,嵌入式系统的“心脏骤停”危机
在嵌入式系统,尤其是工业控制、汽车电子和新能源领域,系统的可靠性往往比性能更关键。想象一下,一个正在高速运转的电机驱动器,或者一个正在执行精密轨迹规划的机器人控制器,其核心“脉搏”——系统时钟——突然停止或变得不稳定,会发生什么?轻则数据错乱、控制失准,重则可能导致设备损毁甚至安全事故。这种“心脏骤停”式的故障,正是时钟失效检测机制要防范的核心风险。
TMS320x2806x系列DSP,作为TI C2000平台中广泛应用的高性能微控制器,其内部集成了两套相辅相成的硬件安全机制来应对时钟失效: 缺失时钟检测复位(MCLKRS) 和 NMI看门狗(NMI Watchdog) 。前者是“快速反应部队”,一旦检测到时钟完全丢失,立即触发系统复位,让系统进入一个已知的“跛行回家”安全状态;后者则是“预警与决策系统”,它提供了一个宝贵的窗口期,允许软件在系统被强制复位前,有机会执行优雅的关闭、状态保存或切换到备用时钟源等关键安全操作。
本文将深入拆解这两大机制的硬件原理、寄存器配置、软件处理流程以及在实际项目中必须注意的“坑”。无论你是正在评估C2000系列芯片的架构师,还是正在调试相关故障的嵌入式工程师,理解这些细节都将帮助你构建出更健壮、更可靠的系统。我们将从最基础的时钟树开始,一步步揭示时钟失效是如何被检测的,软件又该如何与之共舞,最终实现从硬件故障中“软着陆”。
2. 时钟失效检测与NMI看门狗的核心原理剖析
要理解失效检测,必须先理解TMS320x2806x的时钟架构。系统的核心时钟源是外部晶振或时钟源提供的 OSCCLK 。这个时钟经过锁相环(PLL)模块,可以倍频或分频,产生供给CPU内核的 CLKIN 以及整个芯片的 SYSCLKOUT 。时钟失效检测逻辑,本质上就是持续监控 OSCCLK 或PLL输出的 VCOCLK 是否存在。
2.1 缺失时钟检测复位(MCLKRS)机制
MCLKRS是芯片内置的第一道防线。其工作原理可以类比为一个“心跳监测器”。
2.1.1 监测逻辑与计数器
芯片内部有两个关键的计数器: OSCCLK 计数器和 VCOCLK 计数器。它们持续对相应的时钟信号进行计数。在正常操作下,软件会定期(通过正确的操作序列)清除这些计数器,防止其溢出。如果 OSCCLK 或 VCOCLK 信号丢失,计数器将停止更新,但计数器的时钟(来自另一个仍在运行的时钟域,例如内部的备用振荡器或PLL的“跛行模式”时钟)仍在驱动它,最终导致计数器溢出。
一旦溢出发生,硬件会立即置位 PLLSTS[MCLKSTS] 状态位,并产生一个内部的 MCLKRS (缺失时钟复位)信号。这个复位信号会复位CPU内核和大部分逻辑,但 请注意几个关键细节 :
- 它是一个内部复位 :不会拉低芯片外部的
XRS引脚。这意味着外部电路可能感知不到这次复位。 - PLL相关寄存器不被复位 :
PLLCR(PLL控制寄存器)和PLLSTS(PLL状态寄存器)保持原状。这很重要,因为软件需要根据PLLSTS[MCLKSTS]位来判断复位原因。 - 系统进入“跛行模式” :复位后,CPU的
CLKIN时钟会自动切换到PLL的“跛行模式”时钟(limp mode clock)。这是一个由内部RC振荡器产生的、频率较低但稳定的备用时钟,通常频率在10MHz量级,目的是保证CPU在最基本的频率下还能运行代码,而不是彻底“死机”。
注意: “跛行模式”的频率精度和稳定性远低于正常的外部时钟,不能用于需要精确时序的外设(如PWM、ADC采样)。软件检测到进入该模式后,首要任务应是安全关闭所有可能产生危险输出的外设(如将PWM引脚置为高阻态),然后进行系统关机或重启。
2.1.2 软件如何响应MCLKRS
系统从MCLKRS复位中启动后,软件的第一要务就是检查“我是怎么来到这里的?”。
// 系统初始化早期,检查复位原因
if (SysCtrlRegs.PLLSTS.bit.MCLKSTS == 1)
{
// 检测到时钟失效导致的复位!
// 1. 记录故障日志(如果非易失性存储器可用)
// 2. 执行安全关闭流程:禁用PWM输出、关闭功率器件、保存关键状态等
// 3. 清除失效状态标志,否则检测电路会再次触发复位
SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1; // 写1清零MCLKSTS位,并复位检测计数器
// 4. 决策:尝试恢复?还是进入永久安全状态?
// 例如,可以尝试重新初始化时钟系统,如果失败则进入停机状态。
EnterSafeState();
}
else
{
// 正常上电复位或外部引脚复位,继续常规初始化
// 确保MCLKCLR位是0(默认),使能时钟失效检测
SysCtrlRegs.PLLSTS.bit.MCLKCLR = 0;
}
关键点 :清除 MCLKSTS 位是通过向 MCLKCLR 位写1实现的,而不是直接写 MCLKSTS 位。如果清除后 OSCCLK 仍然缺失,计数器会重新开始累积并再次触发MCLKRS,形成一个复位循环。因此,在跛行模式下,软件必须非常小心地操作,避免长时间运行。
2.2 NMI看门狗(NMI Watchdog)机制
MCLKRS是“一刀切”的复位,而NMI看门狗提供了更精细的处理手段。它本质上是MCLKRS机制的一个“可编程延迟触发器”。
2.2.1 工作流程与核心价值
在早期的280x/2833x器件中, VCOCLK 计数器溢出会直接触发MCLKRS。而在2806x中,这个溢出首先产生一个 CLOCKFAIL 信号。这个信号被送入NMI看门狗电路,其后续行为由用户配置决定:
- 立即复位(默认) :上电后,
CLKCTL[NMIRESETSEL]位默认为0,CLOCKFAIL会立即触发MCLKRS,行为与旧器件一致。 - 中断预警(需使能) :将
CLKCTL[NMIRESETSEL]位设置为1,CLOCKFAIL信号会触发一个NMI(不可屏蔽中断)。此时,NMI看门狗计数器(NMIWDCNT)开始以SYSCLKOUT频率递增。
NMI看门狗的核心价值在于“时间窗” :从 CLOCKFAIL 发生到NMI看门狗计数器溢出触发复位( NMIRS ),中间有一段由 NMIWDPRD 寄存器设定的时间。在这段时间内,CPU会响应NMI中断。在NMI中断服务程序(ISR)中,软件可以:
- 安全地关闭PWM驱动,通过将
CLOCKFAIL信号连接到TZ5(Trip Zone 5)来实现PWM引脚高阻态。 - 保存关键的运行状态和数据到RAM或非易失性存储器。
- 尝试切换到备用时钟源(如果系统设计有)。
- 清除
CLOCKFAIL标志,如果问题已解决,则阻止复位发生。 - 执行一个干净的系统关机流程。
如果NMI ISR没有在计数器溢出前完成这些操作, NMIWDCNT 达到 NMIWDPRD 设定值,将产生 NMIRS ,进而触发MCLKRS,复位整个系统。
2.2.2 与CPU看门狗的区别
务必区分 NMI看门狗 和 CPU看门狗 (Section 1.3.4)。前者专门监控时钟失效,后者监控程序跑飞。它们的触发源、计数器时钟和用途完全不同。NMI看门狗是系统级的安全机制,而CPU看门狗是应用级的健康检查机制。
3. 关键寄存器详解与软件配置实战
理解了原理,我们来看如何操作。所有相关寄存器均受 EALLOW 保护,修改前需执行 EALLOW 指令,修改后执行 EDIS 。
3.1 缺失时钟检测相关寄存器
PLL状态寄存器 (PLLSTS) - 关键位
| 位域 | 名称 | 类型 | 描述 |
|---|---|---|---|
| 1 | MCLKSTS | R | 缺失时钟状态位 。1表示发生了缺失时钟复位,且CPU正运行在跛行模式。此位只能通过写 MCLKCLR 位清零。 |
| 0 | MCLKCLR | W | 缺失时钟清除位 。写1将清除 MCLKSTS 位,并复位内部的缺失时钟检测计数器。写0无效。 |
软件操作流程 :
// 使能EALLOW保护寄存器的写权限
EALLOW;
// 检查并清除历史时钟失效状态
if (SysCtrlRegs.PLLSTS.bit.MCLKSTS == 1)
{
// 处理历史时钟失效事件...
SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1; // 清除状态,使能检测
}
// 确保检测功能开启(MCLKCLR=0)
SysCtrlRegs.PLLSTS.bit.MCLKCLR = 0;
// 关闭EALLOW保护
EDIS;
3.2 NMI看门狗相关寄存器组
NMI看门狗涉及一组寄存器,地址从 0x7060 开始。
3.2.1 NMI配置寄存器 (NMICFG)
| 位域 | 名称 | 类型 | 描述 |
|---|---|---|---|
| 1 | CLOCKFAIL | R/W | CLOCKFAIL中断使能位 。这是启用NMI看门狗预警功能的关键! 0: CLOCKFAIL 条件直接导致复位(默认)。 1: CLOCKFAIL 条件产生NMI中断。 一旦置1,只能通过器件复位清零。 |
3.2.2 NMI标志寄存器 (NMIFLG)
| 位域 | 名称 | 类型 | 描述 |
|---|---|---|---|
| 1 | CLOCKFAIL | R | CLOCKFAIL中断标志位 。指示 CLOCKFAIL 条件是否已锁存。 0:无 CLOCKFAIL 条件。 1:检测到时钟失效。 |
| 0 | NMIINT | R | NMI中断标志位 。指示是否产生了NMI中断。 0:无NMI中断。 1:NMI中断已产生。 在清除此标志前,不会产生新的NMI中断。 |
3.2.3 NMI标志清除寄存器 (NMIFLGCLR)
| 位域 | 名称 | 类型 | 描述 |
|---|---|---|---|
| 1 | CLOCKFAIL | W | CLOCKFAIL标志清除 。写1清除 NMIFLG[CLOCKFAIL] 位。 |
| 0 | NMIINT | W | NMIINT标志清除 。写1清除 NMIFLG[NMIINT] 位。 |
重要顺序 :在NMI ISR中,应先清除
CLOCKFAIL标志,再清除NMIINT标志。如果硬件和软件在同一周期对同一标志位进行置位和清零操作,硬件具有优先级。
3.2.4 NMI看门狗计数器与周期寄存器
- NMIWDCNT :16位递增计数器,当任何使能的FAIL标志(如
CLOCKFAIL)置位时开始计数。时钟为SYSCLKOUT。读此寄存器可获知当前计数。 - NMIWDPRD :16位周期寄存器。当
NMIWDCNT值达到NMIWDPRD时,触发NMIRS复位。复位默认值为0xFFFF(最大值)。 软件应在初始化时根据系统需要设置一个合理的值。
计算超时时间 :假设 SYSCLKOUT = 100 MHz , NMIWDPRD = 0x2710 (10,000)。 超时时间 = NMIWDPRD / SYSCLKOUT = 10,000 / 100,000,000 Hz = 0.1 ms 。 这个时间非常短,意味着NMI ISR必须极其高效。通常需要设置一个更长的周期,例如 0xFFFF (约0.655ms @100MHz),为软件争取更多反应时间。
3.2.5 完整初始化与NMI ISR示例
// 系统初始化部分
EALLOW;
// 1. 配置NMI看门狗周期,例如设置为0xC350 (50,000个SYSCLKOUT周期)
SysCtrlRegs.NMIWDPRD.all = 0xC350;
// 2. 使能CLOCKFAIL触发NMI中断,而不是立即复位
SysCtrlRegs.NMICFG.bit.CLOCKFAIL = 1;
// 3. 清除任何可能存在的旧标志
SysCtrlRegs.NMIFLGCLR.bit.CLOCKFAIL = 1;
SysCtrlRegs.NMIFLGCLR.bit.NMIINT = 1;
EDIS;
// 4. 配置PIE,将NMI中断向量指向我们的服务函数
// 假设NMI中断在PIE向量表中的位置已定义
EALLOW;
PieVectTable.NMI_INT = &NMI_Isr;
EDIS;
// 使能CPU级中断和PIE模块中断(此处简化,实际需配置IER、PIEIER等)
IER |= M_INT1; // 使能INT1组(通常NMI位于此)
EINT; // 全局中断使能
// NMI中断服务程序
__interrupt void NMI_Isr(void)
{
// 1. 立即采取安全硬件动作(例如,通过配置TZ5让PWM进入高阻)
// 2. 保存关键上下文到安全区域(如冗余RAM)
SaveCriticalContext();
// 3. 判断是否为CLOCKFAIL触发
if (SysCtrlRegs.NMIFLG.bit.CLOCKFAIL == 1)
{
// 4. 记录故障:可能是时钟源失效
LogFault(FAULT_CLOCK_FAIL);
// 5. 尝试纠正措施(例如,如果有备用时钟源,则切换)
// SwitchToBackupClock(); // 如果设计支持
// 6. 清除标志位,顺序很重要!
SysCtrlRegs.NMIFLGCLR.bit.CLOCKFAIL = 1; // 先清CLOCKFAIL
SysCtrlRegs.NMIFLGCLR.bit.NMIINT = 1; // 再清NMIINT
// 7. 如果无法恢复,准备优雅关机
PrepareForSystemHalt();
}
else
{
// 其他原因触发的NMI(如果有其他使能源)
// 处理其他NMI事件...
SysCtrlRegs.NMIFLGCLR.bit.NMIINT = 1;
}
// 8. 如果需要,可以在这里主动复位系统
// SysCtrlRegs.SYSRS.bit.xxx = 1; // 触发软件复位
// 9. 中断返回(如果未复位)
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // 清除PIE应答位
}
4. 不同工作模式下的行为与关键注意事项
时钟失效检测和NMI看门狗的行为会因芯片的工作模式不同而变化,理解这些差异对设计低功耗或高可靠性系统至关重要。
4.1 低功耗模式下的行为
4.1.1 IDLE模式 在IDLE模式下,所有时钟( OSCCLK , CLKIN , SYSCLKOUT )都正常运行。因此,时钟失效检测逻辑和NMI看门狗也完全正常工作。任何时钟失效都会像在正常运行时一样被检测和处理。
4.1.2 STANDBY模式 在STANDBY模式下,输入到CPU的 CLKIN 被关闭( SYSCLKOUT 也停止),但振荡器和PLL仍在运行,看门狗(如果使能)也在工作。
- 时钟失效检测 :如果此时检测到输入时钟
OSCCLK失效,MCLKSTS状态位仍会被置位,并产生缺失时钟复位(MCLKRS)。 - 特别情况 :如果进入STANDBY时PLL处于旁路模式(
PLLCR=0),且发生了时钟失效,那么PLL的跛行模式时钟(或其1/2、1/4分频)会自动路由给CPU,让系统在极低频率下“苟活”。
4.1.3 HALT模式 在HALT模式下,所有时钟,包括振荡器和PLL,都被关闭。这是最深的低功耗模式。
- 退出HALT时 :当通过GPIO信号唤醒退出HALT模式时,振荡器和PLL重新上电。用于检测时钟失效的计数器(
VCOCLK和OSCCLK)只有在这次上电完成后才会被使能。 - 致命警告 : 绝对不要在跛行模式(
PLLSTS[MCLKSTS]=1)下尝试进入HALT模式! 因为此时OSCCLK可能已经失效,系统时钟不稳定。如果强行进入HALT,器件可能无法正确进入HALT,而是错误地进入STANDBY模式,或者直接挂起,导致无法唤醒。软件在执行IDLE指令进入低功耗模式前,必须检查MCLKSTS位是否为0。
4.2 PLL旁路模式下的行为
当 PLLCR 寄存器设置为 0x0000 时,PLL被旁路。 OSCCLK (或其分频)直接连接到CPU的 CLKIN 。
- 如果此时
OSCCLK被检测为丢失,设备会自动切换到PLL的跛行模式时钟。 - 后续行为取决于
OSCCLK的时钟源和NMIRESETSEL位的设置(立即复位或触发NMI)。
4.3 仿真调试下的行为
在连接仿真器进行调试时(如设置断点导致CPU挂起),NMI看门狗模块的行为如下,这对于调试与时钟失效相关的代码非常关键:
- CPU挂起时 :NMI看门狗计数器暂停。
- 自由运行模式 :计数器正常运作。
- 实时单步模式 :计数器暂停,即使在实时中断内也保持暂停。
- 实时自由运行模式 :计数器正常运作。
这意味着,如果你的代码依赖NMI看门狗在特定时间内触发复位,在单步调试时这个超时可能会被“冻结”,从而掩盖问题。测试相关功能时,最好在自由运行模式下进行。
5. 系统设计实践与避坑指南
将理论转化为实践,这里有几个关键的设计决策和常见的“坑”。
5.1 外部硬件看门狗电路:最后的防线
数据手册的“Note”部分给出了一条黄金建议:对于CPU工作频率绝对关键的应用,应实现一个外部机制,在输入时钟失效时将DSP保持在复位状态。这是一个硬件层面的冗余保护。
典型设计 :使用一个简单的RC电路。一个GPIO引脚定期输出脉冲给电容放电,防止其电压达到阈值。如果时钟失效,CPU代码停止运行,GPIO停止放电,电容电压逐渐上升,最终触发一个连接到 XRS 引脚的比较器或复位芯片,强制DSP复位。这种电路甚至能检测Flash存储器故障(因为代码停跑)。
软件配合 :初始化一个高优先级定时器中断,在中断服务程序中翻转用于放电的GPIO引脚。即使主循环卡死,只要定时器中断还能响应,放电就会继续。一旦时钟失效导致所有代码停止,放电停止,硬件看门狗触发。
5.2 安全操作PLL控制寄存器
修改 PLLCR 寄存器以改变系统时钟频率是一个高风险操作,必须严格遵循数据手册图1-24的流程。核心要点是:
- 在修改前,确保
PLLSTS[MCLKSTS] = 0(不在跛行模式)。 - 按照特定序列(通常涉及等待PLL锁定)进行操作。
- 绝对禁止在跛行模式下写
PLLCR。因为写PLLCR时,器件会临时切换到OSCCLK/2作为CPU时钟源。如果在跛行模式下(OSCCLK可能已失效),这个操作会导致系统时钟停止,芯片锁死。
5.3 NMI看门狗周期与中断服务程序设计的权衡
NMIWDPRD 的设置是一个权衡:
- 周期太短 :给软件反应的时间窗口太小,可能来不及完成安全关闭操作就复位了,失去了NMI预警的意义。
- 周期太长 :从时钟失效到最终复位的时间过长,系统在异常时钟下运行太久,可能导致外设行为不可控,扩大故障影响。
建议 :
- 分层处理 :在NMI ISR中,最先执行的几条指令必须是 原子性 的硬件安全操作,例如通过写寄存器立即将PWM输出强制置为安全状态(高阻或固定电平)。这个操作应在几百个时钟周期内完成。
- 后续操作 :完成硬件安全操作后,再进行数据保存、状态记录等较慢的操作。即使此时看门狗超时复位,系统也已处于硬件安全状态。
- 周期计算 :根据最坏情况下的指令执行时间(考虑所有可能的中断嵌套)来估算ISR执行时间,并留出至少50%的余量来设置
NMIWDPRD。
5.4 与CPU看门狗的协同
一个健壮的系统通常会同时启用CPU看门狗和NMI看门狗。
- CPU看门狗 :监控应用程序主循环或关键任务是否按时“喂狗”,防止软件跑飞。
- NMI看门狗 :专用于监控时钟硬件故障。
它们互不干扰,共同构成了从软件异常到硬件故障的全方位监控。在软件架构上,喂狗操作应放在主循环或低优先级任务中,而NMI ISR则专注于处理最紧急的硬件故障。
5.5 诊断与日志记录
当系统从复位中恢复,诊断复位原因是关键。
- 检查
PLLSTS[MCLKSTS]:判断是否为时钟失效。 - 检查
WDCR[WDFLAG]:判断是否为CPU看门狗超时。 - 检查
SYSRSTSTAT寄存器 (如果器件提供):获取更详细的复位源信息。 - 非易失性故障日志 :在RAM中维护一个故障计数器或状态字,每次复位后加1。在系统初始化稳定后,将其保存到Flash的某个扇区。这样即使完全断电,也能追溯历史故障信息。在NMI ISR中,应尽可能将关键变量(如故障时的系统状态、寄存器值)保存到一块不被初始化代码清零的保留RAM区域。
6. 常见问题排查与调试技巧
在实际开发和调试中,你可能会遇到以下问题:
6.1 系统意外复位, MCLKSTS 位被置位
- 可能原因1:外部时钟源不稳定 。使用示波器测量
X1/X2引脚或XCLKOUT引脚的波形,检查幅值、频率和抖动是否在数据手册要求范围内。注意旁路模式与振荡模式的电路差异。 - 可能原因2:PLL配置或切换时序错误 。严格检查配置PLL的代码是否遵循了手册的流程,特别是等待锁定的循环次数是否足够。在时钟切换期间,避免执行对时序敏感的操作。
- 可能原因3:电源噪声 。时钟电路对电源质量敏感。检查芯片的模拟电源引脚(
VDDA)和数字电源的滤波是否良好,地线是否干净。 - 排查步骤 :简化代码,在
main()函数最开始就检查PLLSTS寄存器并打印或通过GPIO指示状态。逐步添加外设初始化代码,定位导致时钟不稳定的操作。
6.2 使能NMI中断后,系统不再复位而是挂死
- 可能原因:NMI中断服务程序(ISR)未正确编写或使能 。
- 检查向量表 :确认
PIEVECTTABLE中NMI中断的入口地址是否正确指向你的NMI_Isr函数。 - 检查中断使能 :确认
IER寄存器中相应的位(通常是INT1)已置位,并且使用了EINT指令开启了全局中断。 - 检查PIE配置 :对于C2000,NMI通常映射到PIE的INT1.x,需要配置
PIEIER1和PIEACK寄存器。 - ISR内部错误 :NMI ISR中清标志的顺序错误(应先清
CLOCKFAIL,再清NMIINT),或进行了复杂、耗时的操作导致未能及时清除标志,而NMI看门狗又已超时,可能引发不可预知的行为。确保ISR尽可能简短高效。 - 仿真器影响 :在调试时,CPU挂起会暂停NMI看门狗计数器,这可能掩盖了超时问题。尝试在自由运行模式下测试。
- 检查向量表 :确认
6.3 进入低功耗模式后无法唤醒,或唤醒后行为异常
- 检查
MCLKSTS位 :在进入HALT或STANDBY前,务必确认PLLSTS[MCLKSTS]为0。 - 检查唤醒源配置 :确认
LPMCR0寄存器、GPIOLPMSEL寄存器以及PIE中WAKEINT中断的配置正确。 - 检查唤醒信号时序 :从STANDBY唤醒时,GPIO唤醒信号需要持续足够数量的
OSCCLK周期(由QUALSTDBY配置)。从HALT唤醒时,信号需要保持低电平足够长的时间,以待振荡器起振和PLL锁定。这个时间可能需要数毫秒,具体参考数据手册的时序参数。 - HALT模式下的看门狗 :如果希望通过看门狗从HALT模式唤醒(通过复位),需要设置
CLKCTL[WDHALTI]位,使看门狗在HALT模式下保持活动。但请注意,这是通过看门狗 复位 唤醒,而不是中断,唤醒后RAM内容可能保留,但外设需要重新初始化。
6.4 如何测试时钟失效检测功能? 直接拔掉晶振进行测试是破坏性的。可以通过软件模拟来测试NMI看门狗流程:
- 正确初始化NMI看门狗,使能
CLOCKFAIL中断。 - 在
NMIFLGFRC寄存器中,向CLOCKFAIL位写1,可以强制置位CLOCKFAIL标志,从而触发NMI中断流程。 - 在NMI ISR中设置断点或通过GPIO翻转来观察ISR是否被正确执行,以及安全关闭流程是否生效。
- 通过不清除
CLOCKFAIL和NMIINT标志,来测试NMI看门狗超时复位功能是否正常。
调试这类底层硬件安全机制,逻辑分析仪和示波器是必不可少的工具。通过监控 XRS 引脚、关键GPIO(用于指示状态)和时钟引脚,可以清晰地看到从故障发生、中断触发到系统复位或恢复的整个时间序列,从而精准定位问题所在。记住,可靠性设计的一半功夫在于充分的测试和验证。
更多推荐
所有评论(0)