行业资讯

嵌入式EMIF接口配置详解:异步与SDRAM时序计算及中断处理实战

发布时间:2026/7/22 14:43:31
嵌入式EMIF接口配置详解:异步与SDRAM时序计算及中断处理实战 1. EMIF接口嵌入式系统的“记忆管家”在嵌入式系统开发中处理器CPU就像大脑而外部存储器如SDRAM、NOR Flash则是它的“记忆库”。要让大脑高效、准确地存取记忆库里的数据就需要一个可靠的“记忆管家”——这就是外部存储器接口。在TI的许多处理器中这个管家被称为EMIF。我接触过不少基于C6000或ARM Cortex-A系列的项目但凡涉及到外扩内存EMIF的配置总是绕不开的一环配置得当与否直接决定了系统是稳定运行还是频繁崩溃。很多刚接触底层驱动的工程师面对EMIF那一长串寄存器描述和时序参数常常感到无从下手。手册上虽然列出了每个比特位的定义但为什么要这么设、参数怎么算、配置错了会怎样这些实战中的关键点往往语焉不详。今天我就结合手册里的核心寄存器掰开揉碎了讲讲EMIF特别是异步接口和SDRAM的配置逻辑以及中断机制如何为系统稳定性保驾护航。无论你是正在调试一块新的核心板还是想深入理解存储器访问的底层时序这篇文章都能给你提供一套可直接“抄作业”的配置思路和避坑指南。2. 异步存储器接口配置与慢速设备的“对话艺术”异步存储器比如我们常用的NOR Flash、SRAM或者一些老式的FPGA配置芯片它们没有统一的时钟信号来同步数据传输。处理器想和它们“对话”必须事先约定好一套严格的“握手”协议什么时候发出地址喊话什么时候给出读/写命令提出要求数据线在什么时候准备好数据回应这些时间关系都必须由EMIF通过配置寄存器来精确控制。这个过程本质上是在用处理器的快节奏去迁就存储器的慢节奏。2.1 核心寄存器CEnCFG 详解异步接口的配置核心是CEnCFG寄存器其中n对应芯片选择信号EMIF_nCS[n]。通常CS0和CS1可能预留给SDRAM而CS2到CS5则用于连接异步设备。手册中重点描述了CE2CFG到CE5CFG。这个寄存器的每一个字段都直接对应着读写时序波形图上的一个时间段。寄存器位域全景与功能映射比特位字段名功能描述配置要点与影响31SS选择选通模式0常规模式1选择选通模式。常规模式下nOE输出使能和nWE写使能信号独立选择选通模式下nOE被忽略读写仅由nWE区分nCS作为数据选通。30EW扩展等待使能使能后访问周期可通过EMIF_nWAIT信号被外部设备拉长。关键点若你的芯片没有EMIF_nWAIT引脚此位必须清零。29-26W_SETUP写建立时间定义nCS/nWE有效前地址/控制信号需要提前稳定的时钟周期数周期数-1。25-20W_STROBE写选通时间定义nWE信号保持有效的时钟周期数周期数-1即数据被写入存储器的时间窗口。19-17W_HOLD写保持时间定义nWE无效后地址/控制信号需要继续保持稳定的时钟周期数周期数-1。16-13R_SETUP读建立时间定义nCS/nOE有效前地址/控制信号需要提前稳定的时钟周期数周期数-1。12-7R_STROBE读选通时间定义nOE信号保持有效的时钟周期数周期数-1即存储器输出数据有效的时间窗口。6-4R_HOLD读保持时间定义nOE无效后地址/控制信号需要继续保持稳定的时钟周期数周期数-1。3-2TA最小转向时间定义一次读操作和下一次写操作或反之之间必须插入的最小空闲时钟周期数周期数-1。用于防止总线冲突。1-0ASIZE数据总线宽度008位0116位10/11保留。必须与物理连接的存储器数据位宽严格一致。2.2 时序参数计算从数据手册到寄存器值手册第17.4.2.2节给出了一个连接SHARP Flash的经典计算示例。我们以此为例拆解计算逻辑。假设EMIF_CLK 100 MHz周期tEMIF_CLK 10 ns。1. 读时序计算 (R_STROBE,R_HOLD,TA)计算的目标是确保在nOE有效的选通窗口内Flash输出的数据能够满足EMIF输入寄存器的建立和保持时间要求。关键参数tD(EMIF输出延迟)EMIF_CLK高电平到地址/控制信号有效最大7ns。tELQV(Flash输出延迟)nCE有效到数据输出有效最大90ns。tSU(EMIF输入建立时间)EMIF_CLK高电平前数据必须稳定的时间最小6.5ns。tEHQZ(Flash输出高阻延迟)nCE无效后数据线变为高阻态的时间最大55ns。tH(EMIF输入保持时间)EMIF_CLK高电平后数据必须保持的时间最小1ns。R_STROBE计算这个时间必须覆盖从EMIF发出地址到EMIF锁存到稳定数据的整个路径延迟。R_STROBE (tD tELQV tSU) × fEMIF_CLK - 1 (7ns 90ns 6.5ns) × 100 MHz - 1 103.5ns × 100 MHz - 1 10.35 - 1 9.35取整数R_STROBE 10。手册示例中取了100xA并加了1个周期裕量最终取110xB。R_HOLD与TA计算这两个参数共同保证读操作后总线能安全释放避免与后续操作冲突。满足EMIF保持时间R_HOLD tH × fEMIF_CLK - 1 1ns × 100MHz -1 -0.9此条件极易满足R_HOLD取0亦可。满足Flash总线释放时间R_HOLD TA (tD tEHQZ) × fEMIF_CLK - 2。这里减2是因为R_HOLD和TA的定义都是“周期数-1”。计算得R_HOLD TA 4.2。TA最大为3因此可取R_HOLD2,TA3。2. 写时序计算 (W_SETUP,W_STROBE,W_HOLD)计算目标是满足Flash对写脉冲宽度和写周期时间的要求。关键参数tELEHnCE/nWE低电平脉冲最小宽度50ns。tEHEL连续两次写操作之间nCE/nWE高电平最小宽度30ns。tAVAV写周期最小时间90ns。W_STROBE计算必须满足写脉冲宽度。W_STROBE tELEH × fEMIF_CLK - 1 50ns × 100 MHz - 1 5 - 1 4取W_STROBE 4。W_SETUP与W_HOLD计算它们之和需满足写间隔三者之和需满足总写周期。满足写间隔W_SETUP W_HOLD tEHEL × fEMIF_CLK - 2 30ns×100MHz -2 1满足写周期W_SETUP W_STROBE W_HOLD tAVAV × fEMIF_CLK - 3 90ns×100MHz -3 6手册示例给出了一组解W_SETUP1,W_STROBE5,W_HOLD0并最终为每个参数增加了1个周期10ns的裕量得到W_SETUP2,W_STROBE6,W_HOLD1。实操心得一裕量Margin是安全的基石手册计算示例最后一步“Adding a 10 ns margin”至关重要。在实际PCB设计中信号完整性、负载效应都会引入延迟。我个人的经验法则是在计算值的基础上为关键路径如R_STROBE,W_STROBE至少增加20%-30%的时钟周期裕量。例如计算得到R_STROBE最小需要10个周期我会配置为12或13。这能有效应对板级差异和批次性器件参数波动避免在高温或低压等边际条件下出现偶发性读写错误。2.3 模式选择与总线宽度SS (Select Strobe Mode)常规模式使用独立的nOE和nWE。选择选通模式则仅用nWE来区分读写nCS作为数据选通。选择依据完全取决于外围存储器的接口类型。大部分标准异步储器使用常规模式。ASIZE (总线宽度)这是最易出错的地方之一。如果你连接的是16位Flash如手册示例中的LH28F800BJE-PTTL90却将ASIZE配置为8位那么EMIF只会使用数据总线的低8位进行访问。这会导致所有奇数地址的16位数据访问出错或者需要进行字节拼装引发难以调试的数据错误。务必在硬件设计阶段就明确总线宽度并在软件中准确配置。3. SDRAM接口配置与同步高速存储的“节奏共舞”SDRAM与异步存储器完全不同它在时钟边沿同步传输数据速度更快但协议也更复杂。EMIF需要扮演一个合格的“SDRAM控制器”严格按照JEDEC规范发出激活、预充电、读写、刷新等命令并满足一系列苛刻的时序参数。配置SDRAM的核心就是将SDRAM芯片数据手册中的时间参数单位通常是纳秒转换为EMIF控制器所需要的时钟周期数。3.1 核心时序寄存器SDTIMR 详解SDRAM时序寄存器包含了SDRAM操作中最关键的一组时序参数。每个字段的值都是“所需最小时钟周期数减1”。SDTIMR 关键字段与SDRAM命令流关系字段对应SDRAM参数物理意义计算公式与示例 (100MHz)T_RFCtRFC刷新周期。一次刷新命令完成后到下一次刷新或激活命令前必须等待的时间。T_RFC (tRFC / tEMIF_CLK) - 1例tRFC68ns, 则T_RFC (68/10)-15.8取6。T_RPtRP预充电时间。发出预充电命令后到可以发出行激活命令前必须等待的时间。T_RP (tRP / tEMIF_CLK) - 1例tRP20ns, 则T_RP (20/10)-11取1。T_RCDtRCD行到列延迟。发出行激活命令后到可以发出读/写命令前必须等待的时间。T_RCD (tRCD / tEMIF_CLK) - 1例tRCD20ns, 则T_RCD (20/10)-11取1。T_WRtWR(或tRDL)写恢复时间。最后一次数据写入后到发出预充电命令前必须等待的时间确保数据被可靠写入存储单元。T_WR (tWR / tEMIF_CLK) - 1例tWR20ns(2个时钟)则T_WR (20/10)-11取1。T_RAStRAS行激活时间。行激活命令后到发出预充电命令前必须保持的最小时间。T_RAS (tRAS / tEMIF_CLK) - 1例tRAS49ns, 则T_RAS (49/10)-13.9取4。T_RCtRC行周期时间。两次对同一bank的行激活命令之间的最小间隔时间。tRC ≈ tRAS tRP。T_RC (tRC / tEMIF_CLK) - 1例tRC68ns, 则T_RC (68/10)-15.8取6。T_RRDtRRD行到行激活延迟。对不同bank发出两次行激活命令之间的最小间隔时间。T_RRD (tRRD / tEMIF_CLK) - 1例tRRD14ns, 则T_RRD (14/10)-10.4取1。手册第17.4.2.1.2节的表格和计算过程完美展示了如何根据一颗具体的SDRAM芯片三星K4S641632H的参数计算出SDTIMR各个字段的值并最终组合成寄存器值0x61114610。实操心得二关注参数间的依赖与最坏情况计算这些参数时不能孤立地看。例如tRC必须大于等于tRAS tRP。在选取计算值时必须使用数据手册中“最小值Min”一栏的参数并向上取整到整数个时钟周期。此外一些SDRAM参数可能以时钟周期CLK给出如tWR可能写作2 CLK此时需要根据你的SDRAM时钟频率可能与EMIF_CLK同源但需注意比例换算成时间后再计算。手册示例中tWR就是通过tRDL2 CLK和时钟周期换算得到的。3.2 其他关键SDRAM配置寄存器仅有SDTIMR还不够SDRAM的配置是一个系统工程。SDRAM配置寄存器定义SDRAM的基本工作模式。NM数据总线宽度如032位116位。CLCAS延迟如011b3个时钟周期。这是SDRAM从收到读命令到输出第一个数据之间的延迟必须与SDRAM芯片模式寄存器MRS的设置完全一致。IBANK芯片内部Bank数量如010b4个Bank。PAGESIZE页大小行大小影响突发传输效率。SDRAM自刷新退出时序寄存器当SDRAM从低功耗的自刷新模式退出时需要一段稳定时间tXSR才能接受新的命令。SDSRETR中的T_XS字段就是用来配置这个等待时间的。配置不足会导致退出自刷新后的首次访问失败。SDRAM刷新控制寄存器SDRAM需要定期刷新以保持数据。SDRCR中的RR字段决定了刷新命令的发送间隔。计算公式为RR (刷新周期 / 刷新次数) × fEMIF_CLK。例如64ms内需完成4096次刷新则刷新间隔为64ms/409615.625μs。在100MHz下RR 15.625μs × 100MHz 1562.5取整后RR1562 (0x61A)。设置过小浪费带宽设置过大会导致数据丢失。3.3 SDRAM初始化序列不可省略的“上电仪式”SDRAM上电后必须经过一个严格的初始化序列才能正常工作EMIF通常在上电复位后会自动完成。但手册第17.4.2.1.1节提到了一个关键场景动态改变EMIF时钟频率。如果你在系统运行中通过PLL提高了EMIF_CLK的频率必须按以下步骤操作通过字节写操作将SDCR中的SR位设置为1让SDRAM进入自刷新模式。改变PLL配置切换到新的时钟频率。再次通过字节写操作将SR位清零使SDRAM退出自刷新。EMIF会自动重新初始化SDRAM。为什么是字节写因为对SDCR的字写操作可能会触发EMIF的SDRAM初始化序列这在运行时是不希望发生的。字节写可以只修改SR位而不触发其他动作。4. EMIF中断处理系统的“安全哨兵”EMIF的中断机制主要用来处理异步访问超时这是一个非常重要的可靠性特性。想象一下处理器去访问一个外部设备发出了读请求但设备因为某种故障如未响应、损坏一直没有通过nWAIT信号告知“数据已准备好”或一直拉低nWAIT如果没有超时机制处理器就会永远挂起等待导致整个系统死锁。4.1 中断寄存器组协同工作的三层机制EMIF的中断管理通过一组寄存器协同完成构成了“原始状态-屏蔽控制-CPU中断”的完整通路。中断原始状态寄存器这是中断信号的源头。AT异步超时标志。当使能了扩展等待EW1且在一次异步访问中EMIF_nWAIT信号在AWCC寄存器定义的MAX_EXT_WAIT周期内仍未变为无效高电平此位被硬件置1。无论中断是否被屏蔽此位都会置位用于状态查询。WR等待上升沿标志。检测到EMIF_nWAIT引脚上有上升沿时置位。LT行捕获标志。当发生非法的内存访问类型或无效的缓存行大小时置位。操作写1清除W1C。中断屏蔽设置/清除寄存器这是中断的“开关”。INTMSKSET写1到AT_MASK_SET位使能异步超时中断。此时如果INTRAW.AT置位则会影响到INTMSK.AT_MASKED。INTMSKCLR写1到AT_MASK_CLR位关闭异步超时中断。这两个寄存器位是互斥的个置位另一个就清零简化了开关操作。中断屏蔽后状态寄存器这是最终送达CPU中断控制器的状态。INTMSK当INTRAW中的某个中断标志置位且INTMSKSET中对应的屏蔽位已被设置即中断已使能则INTMSK中对应的*_MASKED位会被置1。只有INTMSK中的位被置1才会向CPU产生中断请求。操作同样为写1清除W1C。清除INTMSK中的位也会自动清除INTRAW中对应的原始状态位。4.2 中断处理流程与编程模型一个健壮的中断处理流程通常如下// 1. 初始化配置异步访问参数CEnCFG包括使能扩展等待EW和设置最大等待周期AWCC.MAX_EXT_WAIT EMIF_ASYNC_CFG-CE2CFG ... | (1 30); // 设置EW位 EMIF_ASYNC_CFG-AWCC ... ; // 设置MAX_EXT_WAIT为一个合理的值如255 // 2. 使能EMIF异步超时中断 EMIF_INT-INTMSKSET (1 0); // 设置AT_MASK_SET位使能中断 // 3. 在CPU的中断服务程序(ISR)中处理 void EMIF_ISR(void) { // 读取中断状态以判断来源 uint32_t masked_status EMIF_INT-INTMSK; if (masked_status (1 0)) { // AT_MASKED中断 // 处理异步超时错误 printf(EMIF Async Timeout Error!\n); // 可在此处尝试恢复操作如重试、标记设备故障等 // ... // **关键步骤清除中断标志** // 写1清除INTMSK中的标志位这会连带清除INTRAW中的原始位 EMIF_INT-INTMSK (1 0); // W1C操作 } // ... 处理其他EMIF中断源 }实操心得三中断使能与超时周期设置使能时机建议在系统外设初始化阶段就使能EMIF超时中断。不要等到访问设备时才打开因为无法预测第一次访问何时发生故障。MAX_EXT_WAIT设置这个值定义了EMIF等待nWAIT信号的最长时钟周期数。设置太小可能导致正常但较慢的设备被误判为超时设置太大则系统在设备真正故障时响应过慢。需要根据所接最慢设备的数据手册中的“最大访问时间”来估算并留足裕量。例如一个Flash的最大读访问时间为150ns在100MHz下即15个周期那么MAX_EXT_WAIT可以设置为20-30。中断服务程序在ISR中除了记录错误、尝试恢复最重要的一步是清除中断标志。忘记清除会导致中断持续触发系统无法退出中断。同时ISR应尽量短小避免复杂操作。5. 配置实战从原理图到稳定代码纸上得来终觉浅我们结合手册第17.4节的示例梳理一遍从硬件设计到软件配置的完整流程。5.1 硬件设计检查清单在写代码之前必须反复核对原理图地址映射确认EMIF的地址线EMIF_A[x:y]和Bank地址线EMIF_BA[x:y]是否正确连接到存储器的地址引脚。对于16位宽的SDRAM通常EMIF_A[12:0]接SDRAM_A[12:0]EMIF_BA[1:0]接SDRAM_BA[1:0]。数据总线确认EMIF_DATA[15:0]连接16位存储器EMIF_DATA[31:0]连接32位存储器。特别注意字节序大端/小端是否与处理器和软件预期一致。控制信号SDRAMEMIF_nCAS,EMIF_nRAS,EMIF_nWE,EMIF_CKE,EMIF_nCS[0],EMIF_nDQM[1:0]必须一一对应。异步FlashEMIF_nCS[2],EMIF_nOE,EMIF_nWE是关键。若使用nWAIT功能需连接Flash的RY/BY就绪/忙信号到EMIF_nWAIT。终端匹配与走线对于高速SDRAM如133MHz以上需考虑数据线组的等长布线、终端电阻ODT的配置以减少信号反射和保证时序裕量。5.2 软件配置步骤与代码框架以下是一个基于手册示例的配置顺序框架实际值需根据你的具体器件计算。// 假设基地址定义 #define EMIF_BASE 0x80000000 #define EMIF_SDTIMR (*(volatile uint32_t *)(EMIF_BASE 0x20)) #define EMIF_SDSRETR (*(volatile uint32_t *)(EMIF_BASE 0x3C)) #define EMIF_SDRCR (*(volatile uint32_t *)(EMIF_BASE 0x34)) // 假设偏移 #define EMIF_SDCR (*(volatile uint32_t *)(EMIF_BASE 0x18)) // 假设偏移 #define EMIF_CE2CFG (*(volatile uint32_t *)(EMIF_BASE 0x10)) #define EMIF_INTMSKSET (*(volatile uint32_t *)(EMIF_BASE 0x48)) void EMIF_Init(void) { // --- 第1步配置SDRAM时序 (SDTIMR) --- // 根据SDRAM芯片手册计算值例如三星K4S641632H 100MHz // T_RFC6, T_RP1, T_RCD1, T_WR1, T_RAS4, T_RC6, T_RRD1 // 组合成寄存器值参考手册图17-28 EMIF_SDTIMR 0x61114610; // 示例值 // --- 第2步配置SDRAM自刷新退出时间 (SDSRETR) --- // T_XS (tXSR / tEMIF_CLK) - 1, 示例取6 EMIF_SDSRETR 0x6; // --- 第3步配置SDRAM刷新率 (SDRCR) --- // RR (刷新周期 / 刷新次数) * fEMIF_CLK, 示例0x61A EMIF_SDRCR 0x61A; // --- 第4步配置SDRAM工作模式 (SDCR) --- // NM1 (16-bit), CL011b (CAS Latency 3), IBANK010b (4 banks), PAGESIZE0 (256 words) // 注意先进入自刷新才能改频率此处假设频率已设好 // 通过字节写操作仅修改SR位避免触发初始化 *((volatile uint8_t *)(EMIF_SDCR) 3) ~(1 7); // 清除SR位退出自刷新如果之前进入过 // 然后配置其他位 EMIF_SDCR 0x4720; // 示例值SR0, NM1, CL3, IBANK4, PAGESIZE256 // --- 第5步配置异步存储器 (如CS2连接的Flash) --- // 根据Flash手册计算示例值SS1, EW0, W_SETUP2, W_STROBE6, W_HOLD1, // R_SETUP1, R_STROBE0xB, R_HOLD3, TA3, ASIZE1 (16-bit) EMIF_CE2CFG 0x886225BD; // 示例值 // --- 第6步配置并使能中断如果需要 --- // 先设置异步等待周期配置寄存器(AWCC)的最大等待时间 // *((volatile uint32_t *)(EMIF_BASE 0xXX)) ... ; // 设置AWCC // 使能异步超时中断 EMIF_INTMSKSET (1 0); // 设置AT_MASK_SET位 // --- 第7步验证配置 --- // 可以对配置的内存区域进行简单的读写测试例如写入一个已知模式再读回比较。 uint16_t *test_addr (uint16_t *)(EMIF_BASE 0x02000000); // CS2地址空间 *test_addr 0xAA55; if (*test_addr ! 0xAA55) { // 初始化失败处理 } }5.3 常见问题与调试技巧实录即使按照手册配置在实际调试中仍会遇到各种问题。下面是我总结的一些常见坑点和排查思路。问题1SDRAM初始化失败读写数据全为0或全为1。可能原因时序参数过于紧张计算出的周期数没有向上取整或未留裕量在低温或电压偏低时失效。CAS延迟配置错误SDCR.CL字段与SDRAM芯片模式寄存器MRS中编程的CAS Latency不匹配。必须完全一致。硬件问题时钟未连接、电源不稳、控制信号线连接错误。排查步骤使用示波器或逻辑分析仪抓取EMIF_CLK、EMIF_nCAS、EMIF_nRAS、EMIF_nWE、EMIF_CKE和EMIF_nCS[0]的波形。确认上电后有一系列稳定的初始化命令Precharge All, Auto Refresh, MRS Set等。核对SDTIMR每个字段的计算过程确保使用的是参数表中的最小值Min并增加1-2个周期的裕量重新配置。确认SDCR中的NM总线宽度、IBANKBank数与硬件连接一致。问题2异步Flash访问不稳定偶发性数据错误。可能原因nWAIT信号处理不当如果Flash支持nWAIT或RY/BY且已连接但CEnCFG.EW位未使能或AWCC.MAX_EXT_WAIT设置过小。时序裕量不足PCB走线过长导致信号延迟计算时未考虑此因素。TA转向时间不足在密集的读、写操作交替时总线方向切换时间不够导致总线冲突。排查步骤测量Flash的nWAIT引脚在读写时的波形确认其是否被正确拉低/拉高。增大CEnCFG中的R_STROBE、W_STROBE等参数特别是增加TA的值。在代码中在连续的读操作和写操作之间手动插入几个NOP指令或软件延迟观察问题是否消失。如果消失说明硬件时序TA需要调整。问题3系统运行一段时间后死机疑似EMIF中断导致。可能原因中断标志未清除在中断服务程序ISR中忘记清除INTMSK或INTRAW中的中断标志导致中断持续触发CPU无法执行主程序。中断服务程序执行时间过长在ISR中进行了复杂操作导致其他高优先级任务或中断被阻塞。异步超时频繁发生外部存储器设备不稳定或访问时序配置错误导致频繁产生超时中断。排查步骤在EMIF ISR的入口处首先读取并保存INTRAW和INTMSK的值处理完后务必执行写1清除操作。检查AWCC.MAX_EXT_WAIT的设置是否合理。如果设备正常但偶尔响应慢可以适当增大该值。在ISR中仅设置错误标志位将复杂的错误处理如重试、日志记录放到主循环或低优先级任务中。问题4改变系统时钟频率后外部存储器访问出错。可能原因未按照规范重新配置SDRAM。直接改变EMIF的输入时钟如通过PLL提高CPU主频而SDRAM的时序寄存器仍基于旧频率配置必然出错。正确操作必须遵循“自刷新 - 改频 - 退出自刷新”的流程如3.3节所述。并且改频后可能需要根据新的fEMIF_CLK重新计算并配置SDTIMR、SDSRETR、SDRCR等所有与时序相关的寄存器。调试利器内存测试模式编写一个全面的内存测试函数远比简单的单次读写更有用。一个基础的测试应包括地址线测试写入每个地址线独有的模式如1 addr_bit再读回验证。数据线测试写入 walking 1/0 模式如0xAAAA5555,0xCCCC3333等检查数据总线是否有短路或对地/电源粘连。全空间测试写入伪随机序列如利用CRC32生成再读回校验。这可以检测存储单元是否稳定。 当测试失败时出错的地址和数据模式往往能直接指向硬件问题如某根数据线虚焊或严重的时序问题。