1. 项目概述与核心价值

对于任何一位嵌入式开发者而言,系统启动(Boot)都是项目开发中第一个,也是最关键、最容易“踩坑”的环节。它决定了你的代码能否在芯片上电后,从一片混沌的硬件状态中,正确地被找到、加载并运行起来。尤其在像TI C2000™系列TMS320F2838x这样的高性能多核微控制器上,启动流程的复杂性呈指数级上升——你不仅要考虑主核CPU1如何启动,还要规划好从核CPU2和连接管理器CM的启动时机与方式。

很多工程师拿到芯片后,往往直接套用官方例程的默认配置,对Boot ROM的理解停留在“知道有这么回事”的层面。直到产品需要现场升级、产线需要多版本测试,或者系统需要从通信接口恢复时,才会发现启动模式配置不当带来的种种麻烦:比如无法进入引导加载程序、多核启动顺序错乱,甚至因为配置错误导致芯片“变砖”。我经历过不止一次,因为一个GPIO上拉电阻没处理好,或者OTP配置写错一个字节,导致整批板卡需要返工重烧的窘境。

因此,深入理解TMS320F2838x的Boot ROM机制,并掌握其灵活的启动模式配置方法,绝非纸上谈兵,而是保障产品可靠性、可维护性和开发效率的基石。本文将基于官方技术手册,结合我多年的实战经验,为你彻底拆解F2838x的启动流程、配置方法以及那些手册上不会写的“避坑指南”。无论你是正在评估这款芯片,还是已经深陷启动问题的调试中,相信都能在这里找到清晰的路径和实用的解决方案。

2. Boot ROM核心机制深度解析

Boot ROM,顾名思义,是芯片出厂时固化在只读存储器中的一段不可修改的代码。它的使命非常明确:在芯片上电复位后,接管系统的控制权,完成最基础的硬件初始化,然后根据特定的“线索”,找到用户应用程序的入口,并将控制权移交出去。你可以把它想象成电脑的BIOS,但更精简、更专用。

2.1 启动流程总览:从复位到应用

TMS320F2838x的启动并非一个简单的线性过程,而是一个包含决策分支的状态机。其核心流程可以概括为以下几个阶段:

  1. 硬件复位与初始化 :无论是上电复位、看门狗复位还是外部复位,芯片都会从固定的复位向量开始执行Boot ROM代码。首先进行的是最底层的硬件初始化,包括关闭看门狗、配置系统时钟(PLL)、初始化内部RAM、为上电自检做准备等。这个过程是芯片“活过来”的基础。
  2. 启动路径决策 :这是Boot ROM最核心的“智能”部分。芯片会检查两个关键条件:
    • 调试器连接状态 :检查JTAG口是否有调试器连接。如果有,则进入 仿真启动 流程;如果没有,则进入 独立启动 流程。这是开发阶段和量产阶段行为差异的根源。
    • 启动模式配置 :根据配置寄存器(OTP或仿真寄存器)和硬件引脚(BMSP)的状态,解码出当前应该执行的启动模式(例如,从Flash启动、从SCI接口等待下载等)。
  3. 模式执行与跳转 :根据解码出的启动模式,Boot ROM执行相应的操作。如果是外设启动(如SCI、CAN),则会初始化对应的外设,并进入引导加载程序,等待主机发送程序数据。如果是Flash或RAM启动,则直接计算好入口地址,跳转到用户应用程序。
  4. 多核启动协调 :对于CPU2和CM这两个从核,它们的启动完全由主核CPU1控制。CPU1需要在合适的时机,通过IPC(进程间通信)寄存器为它们配置启动模式,并释放其复位,它们才会开始各自的启动流程。

2.2 仿真启动 vs. 独立启动:开发与生产的桥梁

理解这两种启动流程的差异,是灵活运用Boot模式的关键。

  • 仿真启动 :当JTAG调试器连接时触发。在此模式下,Boot ROM会 忽略OTP中的硬件配置 ,转而去读取一组位于RAM中的仿真配置寄存器(如 EMUBOOTPINCONFIG , EMUBOOTDEF )。这带来了巨大的灵活性:

    • 无需烧写OTP :你可以在开发阶段,通过CCS的调试脚本或直接在内存窗口中修改这些仿真寄存器的值,实时试验不同的BMSP引脚和BOOTDEF表配置,而无需每次修改都进行一次耗时的OTP烧写。
    • 快速迭代 :极大地加速了启动方案的验证过程。你可以模拟各种引脚状态组合,快速验证你的自定义启动表是否按预期工作。
    • 安全网 :即使OTP配置错误,只要连接调试器,依然可以通过仿真启动模式让芯片“活过来”,从而有机会修复OTP。
  • 独立启动 :当芯片独立运行(无调试器)时触发。此模式下,Boot ROM严格依赖 一次性可编程存储器 中的配置。

    • 依赖OTP :从 Z1-BOOTPINCONFIG Z1-BOOTDEF (或Z2区域)读取BMSP和启动模式表的配置。这些配置在芯片出厂后,通常只能写入一次(或有限的次数)。
    • 最终方案 :这是产品量产时的最终启动配置。一旦确定,就需要将配置烧录到OTP中,芯片此后将永远按照此配置启动。
    • 区域优先级 :F2838x支持两个配置区域(Zone1和Zone2)。Boot ROM会优先检查Zone2的配置是否有效(Key是否为0x5A),如果有效则使用Zone2,否则使用Zone1。这为固件升级提供了“黄金备份”机制:可以将旧版本配置放在Zone1,新版本配置放在Zone2,通过某种方式(如应用程序)控制使用哪个区域。

实操心得:开发阶段的工作流 我的标准做法是:在开发初期,完全在仿真启动模式下进行所有启动逻辑的调试和验证。只有当启动方案(包括引脚分配、模式顺序)100%稳定后,才将最终的配置值计算好,通过编程工具一次性烧录到OTP的Zone1区域。Zone2区域暂时保留,作为未来升级的备用。千万不要在方案未经验证时就贸然烧写OTP。

3. 启动模式配置的实战拆解

官方手册列出了多达十余种启动模式,但实际项目中常用的集中在Flash、SCI、CAN、SPI等几种。配置的核心在于两件事: 告诉芯片用哪几个GPIO引脚来做选择 ,以及 每个引脚组合对应哪种启动模式

3.1 核心寄存器:BOOTPINCONFIG 与 BOOTDEF

这是整个自定义启动的“控制中心”。

  • BOOTPINCONFIG (启动引脚配置寄存器) : 这个寄存器的核心作用是 映射 。它将抽象的“启动模式选择引脚”(BMSP0, BMSP1, BMSP2)映射到具体的物理GPIO引脚上。

    • 位域 :32位寄存器分为4个8位字段: KEY BMSP2 BMSP1 BMSP0
    • KEY (位31:24) :必须写入 0x5A ,Boot ROM才会认为本寄存器的配置是有效的。在仿真模式下,写入 0xA5 可以模拟独立启动流程,这是一个非常实用的调试功能。
    • BMSPx (位23:0) :每个字段对应一个BMSP。写入的值代表GPIO编号(例如, 0x00 代表GPIO0, 0x0F 代表GPIO15)。如果写入 0xFF ,则表示禁用该BMSP。
    • 引脚限制 GPIO42, GPIO43, 以及GPIO169-GPIO255不能用作BMSP 。如果配置了这些引脚,Boot ROM会自动回退到该BMSP的工厂默认GPIO(对于BMSP2,默认是禁用状态 0xFF )。
  • BOOTDEF (启动定义表寄存器) : 这是一个64位的寄存器,可以看作一个拥有8个“格子”的查找表。每个“格子”(BOOT_DEF0 到 BOOT_DEF7)对应BMSP引脚组合解码后的一个索引值,里面存放着该索引对应的具体启动模式代码。

    • 索引计算 :将BMSP0视为最低有效位(LSB),BMSP2视为最高有效��(MSB)。芯片上电时会读取这些引脚的电平(高/低),组成一个二进制数,这个数就是BOOTDEF表的索引。
      • 例如,使用BMSP0和BMSP1两个引脚,那么可能的索引是: 00 (0), 01 (1), 10 (2), 11 (3)。你需要预先在BOOT_DEF0到BOOT_DEF3中填好这四种情况分别对应的启动模式。
    • 模式代码 :每个BOOT_DEFx字段需要填入一个特定的值来代表一种启动模式及其选项。例如, 0x03 代表从Flash启动(入口点选项0), 0x02 代表CAN启动, 0x09 代表USB启动等。具体代码需查阅手册的 Section 5.7.8

3.2 配置流程四步法

根据手册指引,我将自定义启动配置总结为以下四个可操作的步骤:

  1. 规划启动模式需求 : 这是设计阶段。你需要问自己:我的产品需要哪些启动方式?

    • 主程序运行 :毫无疑问,需要Flash启动。
    • 固件升级 :可能需要通过CAN、SCI或USB进行引导加载。
    • 工厂测试 :可能需要通过并行IO或SPI从外部存储器快速加载测试程序。
    • 调试 :可能需要一个“等待”模式,等待调试工具连接。 列出所有需要的模式,并确定一个 默认模式 (通常是Flash启动)。
  2. 计算所需BMSP数量 : 这是一个简单的数学问题。你需要多少种启动模式,决定了需要几个BMSP引脚。

    • 0个BMSP:1种模式(固定模式)。
    • 1个BMSP:2种模式(引脚高低电平代表两种选择)。
    • 2个BMSP:4种模式。
    • 3个BMSP:8种模式。 公式:模式数量 ≤ 2^(BMSP数量) 。通常建议预留1-2个空位或重复模式以备不时之需。
  3. 分配物理GPIO引脚 : 为选定的BMSP分配具体的GPIO引脚。这里有几个关键考量:

    • 避开功能冲突 :你选择的GPIO在板级设计中,是否已经被用作其他关键功能(如关键信号输入、LED驱动、通信接口)?启动时这些引脚的电平状态必须可控。
    • 硬件设计 :这些引脚需要通过上拉/下拉电阻固定到确定电平(VCC或GND),以确保每次上电状态一致。也可以设计为通过跳线帽或测试点连接,便于在产线切换。
    • 示例 :决定使用2个BMSP,选择 GPIO50 作为BMSP0, GPIO51 作为BMSP1,BMSP2禁用( 0xFF )。
  4. 构建BOOTDEF查找表 : 根据BMSP引脚组合(索引),填充BOOTDEF寄存器。这是配置的“灵魂”。

    • 索引映射 :根据步骤2和3的规划,画出真值表。
    • 填充模式代码 :查阅手册,将规划好的启动模式对应的十六进制代码填入相应的BOOT_DEFx位置。
    • 处理未用索引 :对于没有用到的索引(比如你只有3种模式但用了2个BMSP,会有1个索引空余),建议将其设置为一个安全的模式,例如 Wait Boot Flash Boot ,避免芯片因解码到未定义模式而进入不可预测状态。

3.3 配置实例详解

我们结合手册中的例子,来看一个更贴近实际项目的“三模式”配置场景。

场景 :一个工业控制器,需要三种启动方式:1) 正常从Flash运行主程序;2) 通过CAN总线进行固件升级;3) 通过SCI接口进行调试和程序下载。

分析 :三种模式,至少需要2个BMSP引脚(提供4种组合,我们只用3种)。

步骤

  1. 规划 :主模式Flash,备用模式CAN,调试模式SCI。
  2. 计算BMSP :需要2个引脚(BMSP0, BMSP1),提供4个索引(0,1,2,3)。我们使用其中3个。
  3. 分配GPIO :选择 GPIO12 作为BMSP0, GPIO13 作为BMSP1。硬件上, GPIO12 GPIO13 通过10kΩ电阻下拉到GND。板子上预留两个测试点,可以通过跳线帽连接到3.3V来拉高电平。
  4. 构建BOOTDEF表
    • 索引0 ( BMSP1=0, BMSP0=0 ):默认情况(两引脚均下拉),我们希望进入 CAN升级模式 。填入 0x02
    • 索引1 ( BMSP1=0, BMSP0=1 ):仅BMSP0拉高,我们希望进入 SCI调试模式 。填入 0x08 (假设0x08是SCI-A启动代码,需查表确认)。
    • 索引2 ( BMSP1=1, BMSP0=0 ):仅BMSP1拉高,我们希望进入 Flash主程序模式 。填入 0x03
    • 索引3 ( BMSP1=1, BMSP0=1 ):两引脚均拉高。这个组合我们暂时不用,为安全起见,也设置为 Flash Boot (0x03) Wait Boot (0x20)

对应的寄存器配置值

  • BOOTPINCONFIG = 0x5AFF0D0C
    • KEY = 0x5A
    • BMSP2 = 0xFF (禁用)
    • BMSP1 = 0x0D (GPIO13)
    • BMSP0 = 0x0C (GPIO12)
  • BOOTDEF = 0x00000000 03080203
    • BOOT_DEF0 = 0x02 (CAN)
    • BOOT_DEF1 = 0x08 (SCI)
    • BOOT_DEF2 = 0x03 (Flash)
    • BOOT_DEF3 = 0x03 (Flash, 安全备用)
    • BOOT_DEF4 ~ BOOT_DEF7 = 0x00 (默认,通常会导致跳转到Flash或Wait)

注意事项:引脚电平采样时机 Boot ROM在启动初期、系统时钟稳定后不久就会采样BMSP引脚的电平。此时,你的应用程序尚未运行,GPIO模块可能也未初始化。因此, 必须确保这些引脚在硬件上有确定的上拉或下拉 (通常下拉更常见,因为低电平被视为默认状态)。如果引脚浮空,电平不确定,将导致启动模式解码错误,这是最常见的启动失败原因之一。

4. 多核启动(CPU2与CM)的协同设计

TMS320F2838x的多核架构中,CPU1是主核,拥有完整的自主启动能力。而CPU2和CM(Connectivity Manager)作为从核,它们的启动完全受控于CPU1。这是一个典型的“主从式”启动模型。

4.1 从核启动的本质:IPC通信

CPU2和CM自身也有Boot ROM,但它们的Boot ROM功能相对简单:初始化自己的RAM,然后 等待CPU1的指令 。这个指令传递的通道,就是IPC(Inter-Processor Communication)寄存器。

  • 核心寄存器
    • CPU1TOCPU2IPCBOOTMODE :CPU1通过此寄存器告诉CPU2以何种模式启动。
    • CPU1TOCMIPCBOOTMODE :CPU1通过此寄存器告诉CM以何种模式启动。
    • CPU1TOCPU2IPCFLG0 / CPU1TOCMIPCFLG0 :标志寄存器。CPU1在配置好上述模式寄存器后,必须置位对应的FLG0,从核的Boot ROM检测到这个标志位,才会读取模式寄存器并开始执行相应的启动流程。

4.2 从核启动流程与CPU1的职责

从核的启动必须在CPU1的控制下进行,有两种触发时机:

  1. 复位后立即配置(推荐)

    • CPU1在自己的启动流程中,较早地完成系统时钟(包括给CPU2/CM的时钟)配置。
    • CPU1写入 CPU1TOCPU2IPCBOOTMODE CPU1TOCMIPCBOOTMODE 寄存器,设置好期望的启动模式(如从Flash特定地址启动、从RAM启动、等待IPC拷贝等)。
    • CPU1置位 IPCFLG0
    • CPU1释放CPU2/CM的硬件复位。
    • CPU2/CM解除复位后,运行自己的Boot ROM,发现FLG0已置位,便读取模式寄存器,并开始执行对应的启动操作。
  2. 先复位,后配置(动态启动)

    • CPU1先释放CPU2/CM的复位,让它们运行起来。
    • CPU2/CM的Boot ROM发现FLG0为0,便会进入 等待启动模式 ,在一个循环中持续检查 IPCFLG0
    • 当CPU1在应用程序中需要启动从核时,再写入模式寄存器并置位FLG0。
    • CPU2/CM检测到FLG0变化,读取模式并跳转执行。

模式寄存器配置示例 : 假设我们希��CPU2从Flash地址 0x80000 开始执行,CM则等待CPU1通过IPC消息传递代码。

// CPU1 应用程序中的代码
// 配置CPU2从Flash启动,入口地址为0x80000
// 假设 0x01 代表从指定地址跳转(需查具体手册定义)
EALLOW;
CpuSysRegs.CPU1TOCPU2IPCBOOTMODE.all = 0x00080001; // 高16位可能为地址,低16位为模式
EDIS;

// 配置CM进入IPC RAM拷贝等待模式
// 假设 0x02 代表IPC拷贝模式
EALLOW;
CpuSysRegs.CPU1TOCMIPCBOOTMODE.all = 0x00000002;
EDIS;

// 触发从核启动
EALLOW;
CpuSysRegs.CPU1TOCPU2IPCFLG0.all = 1; // 置位CPU2启动标志
CpuSysRegs.CPU1TOCMIPCFLG0.all = 1;    // 置位CM启动标志
EDIS;

// 最后,释放从核的复位(如果它们还在复位中的话)
// 这通常通过控制某个系统控制寄存器的位来实现
SysCtrlRegs.SECMSEL.bit.CPU2RESETEN = 0; // 假设位名称,请查手册
SysCtrlRegs.SECMSEL.bit.CMRESETEN = 0;

实操心得:多核启动的顺序与同步 在多核系统中,启动顺序至关重要。一个常见的策略是“CPU1先启动,完成关键外设和全局数据初始化后,再启动从核”。务必在CPU1的应用程序中,确保所有需要共享的资源(如共享RAM、通信外设)初始化完成,并且必要的IPC通信机制就绪后,再触发CPU2和CM的启动。否则,从核可能访问到未初始化的内存或外设,导致硬件错误或数据竞争。

5. 常见问题排查与调试技巧实录

即使理解了原理,实际配置和调试中依然会遇到各种问题。下面是我在多个项目中总结的“踩坑”记录和解决方法。

5.1 问题排查速查表

现象 可能原因 排查步骤与解决方法
芯片上电后无反应,调试器无法连接 1. Boot模式配置错误,进入了不期望的外设等待模式(如SCI)。
2. BMSP引脚浮空,解码到未定义的启动模式。
3. OTP配置损坏,Boot ROM流程卡死。
1. 检查硬件 :用万用表测量你规划的BMSP引脚在上电瞬间的电平,确保是预期的拉高或拉低,而非浮空。
2. 强制进入Flash启动 :尝试将所有的BMSP引脚(根据手册默认引脚)通过电阻强制拉高或拉低,使其解码到Flash模式。
3. 使用仿真启动 :连接JTAG调试器,在CCS中查看PC指针是否停在Boot ROM区域,并检查仿真配置寄存器 EMUBOOTPINCONFIG EMUBOOTDEF 的值。
可以连接调试器,但程序无法加载到Flash或加载后不运行 1. BOOTDEF表中Flash启动的入口地址选项配置错误。
2. Flash初始化或时钟配置有问题,导致Boot ROM跳转到错误地址。
3. 应用程序的向量表或启动代码(如 c_int00 )链接地址与Boot ROM跳转地址不匹配。
1. 检查BOOTDEF值 :确认Flash启动的模式代码是否正确(例如是 0x03 还是 0x04 ,对应不同入口点)。
2. 单步调试Boot ROM :在Boot ROM结束跳转到应用代码前设置断点,观察跳转地址是否与你的 .out 文件入口地址一致。
3. 检查链接命令文件 :确认代码段(尤其是 .cinit , .text )是否正确地链接到了Flash区域,并且中断向量表重定位是否正确。
CPU2或CM启动失败,卡在等待循环 1. CPU1没有正确配置 IPCBOOTMODE 寄存器。
2. CPU1没有置位 IPCFLG0
3. CPU2/CM的时钟没有使能。
4. CPU1没有释放CPU2/CM的硬件复位。
1. 检查IPC寄存器 :在CPU1的代码中,在置位FLG0前后,通过调试器查看 IPCBOOTMODE 寄存器的值是否正确写入。
2. 检查时钟配置 :确认系统时钟控制寄存器中,给CPU2和CM的时钟门控是否已打开。
3. 检查复位状态 :查看系统控制寄存器中,CPU2和CM的复位释放位是否已正确操作。
使用外设启动(如CAN)时,主机工具无法连接 1. 外设引脚复用配置冲突,Boot ROM未能正确初始化外设。
2. 波特率、时钟等通信参数不匹配。
3. Boot ROM使用的外设实例是第一个(如CAN-A),而你的硬件连接到了CAN-B。
1. 查阅手册确认 :Boot ROM 固定使用每个外设的第一个实例 (SCIA, CANA, SPIA等)。确保你的硬件连接与此一致。
2. 检查引脚配置 :确认用于启动的外设引脚没有被其他功能占用,且上电后处于正确的状态(例如CAN需要终端电阻)。
3. 核对通信参数 :Boot ROM使用固定的波特率、数据格式。确保你的主机工具(如CAN bootloader上位机)参数设置与之完全一致。

5.2 高级调试技巧:利用仿真寄存器

仿真启动模式是调试Boot问题的“瑞士军刀”。

  1. 动态修改启动模式 :在CCS调试状态下,即使你的OTP配置是Flash启动,你也可以通过修改 EMUBOOTPINCONFIG EMUBOOTDEF 的内存值(地址分别为 0xD00 0xD04 ),然后进行软复位,来立即测试其他启动模式(如SCI、CAN),而无需重新烧写程序或改动硬件。
  2. 诊断OTP配置 :如果你怀疑OTP配置有问题,可以在仿真启动模式下,将 EMUBOOTPINCONFIG.KEY 写为 0xA5 。这会告诉Boot ROM“模拟独立启动流程”,即它会去读取OTP中的配置。然后你可以单步跟踪,看Boot ROM解码出的BMSP值和BOOTDEF索引是否正确,从而判断OTP配置是否生效。
  3. 观察启动状态 :Boot ROM在执行过程中,会在特定的RAM位置(具体地址需查手册)留下状态信息或错误码。在仿真模式下,你可以在这些内存地址设置数据观察点,了解Boot流程走到了哪一步,或者在哪个环节失败。

5.3 OTP烧写的注意事项

OTP是一次性可编程存储器,烧写需谨慎。

  • 先仿真,后烧写 :这是铁律。务必在仿真模式下将所有启动逻辑验证无误后,再计算最终的OTP配置值。
  • 理解Zone1和Zone2 :建议先将稳定版本配置烧录到Zone1。Zone2留空或作为备份。未来如果需要更新启动配置,再烧录Zone2。Boot ROM优先使用Zone2,这为你提供了回滚到Zone1旧配置的可能。
  • 使用官方工具 :使用TI提供的Uniflash或CCS中的OTP编程工具进行烧写,并仔细核对地址和数值。烧写过程需要特定的电压和时序,切勿在不可靠的电源环境下操作。
  • 备份配置 :将你计算出的 BOOTPINCONFIG BOOTDEF 的十六进制值记录在项目文档中。一旦烧写,这就是芯片的“启动基因”。

6. 安全启动与异常处理机制浅析

TMS320F2838x的Boot ROM还集成了一些安全与健壮性相关的机制,了解它们有助于构建更可靠的系统。

6.1 安全Flash启动

这是一种增强安全性的启动方式。Boot ROM会计算Flash中特定区域代码的哈希值(例如SHA-256),并与存储在安全存储中的预期值进行比较。只有校验通过,才会跳转执行。这用于防止未经授权的固件运行。配置此模式需要在BOOTDEF中使用特定的模式代码,并提前在Flash中布置好安全启动相关的数据结构和密钥。

6.2 异常与错误处理

Boot ROM并非“一崩了之”,它对运行中可能出现的硬件错误有基本的处理策略,这对于诊断复杂问题很有帮助。

  • CPU1的哲学 :“记录错误,继续前进”。对于大多数可纠正的错误(如时钟失效、单比特RAM错误),Boot ROM会尝试清除错误标志,记录错误状态到特定寄存器,然后尽可能继续启动流程,力图将系统交付给应用程序。应用程序可以在启动后读取这些错误状态寄存器,进行更复杂的错误处理或上报。
  • CPU2/CM的哲学 :“报告错误,等待救援”。从核在Boot过程中遇到严重错误(如不支持的启动模式、安全启动失败),会通过IPC向CPU1发送错误消息,然后自己进入等待循环。这意味着从核的启动失败不会导致整个系统崩溃,而是由主核CPU1���决定如何处置(比如尝试重新配置并启动从核,或记录错误并降级运行)。

如何利用错误信息 : 手册中的 Table 5-16 详细列出了各种异常事件及Boot ROM的动作。例如,如果遇到“PIE向量不匹配”错误,CPU1会尝试跳转到一个可配置的错误处理函数地址。你可以在应用程序中提前设置这个地址,指向一段错误处理代码,从而捕获Boot阶段的严重配置错误。

理解这些机制,意味着当系统出现异常复位或启动失败时,你不再是无头苍蝇,而是可以通过查询状态寄存器、分析IPC消息,定位到问题是发生在Boot ROM阶段还是应用程序阶段,是硬件故障还是配置错误,从而大幅缩短故障排查时间。

更多推荐