1. EMIFA接口与NAND Flash交互的核心机制
在嵌入式系统设计中,外部存储器接口(EMIFA)扮演着连接处理器核心与外部存储世界的桥梁角色。它绝不仅仅是一个简单的地址/数据总线驱动器,而是一个集成了复杂状态机、时序控制和协议处理能力的智能控制器。当我们聚焦于NAND Flash这类异步、页式访问的存储设备时,EMIFA的设计哲学和实现细节就显得尤为重要。其核心目标是在满足NAND Flash苛刻的时序要求下,最大化数据吞吐效率,同时为上层软件提供清晰、可靠的状态反馈和控制接口。
1.1 NAND Flash状态寄存器(NANDFSR)的深度解析
NAND Flash的操作本质上是命令驱动的。无论是读、写还是擦除,在发出命令后,Flash芯片内部都需要时间来完成相应的物理操作(如电荷注入、隧道效应等)。这段时间内,设备处于“忙”状态,无法接受新的命令。EMIFA通过NANDFSR寄存器,为软件提供了一个直接窥探Flash内部工作状态的窗口。
这个寄存器的作用非常纯粹:它直接反映了EMA_WAIT引脚的电平状态。在硬件设计上,EMA_WAIT引脚必须连接到NAND Flash芯片的R/B#(Ready/Busy)信号。当Flash内部忙碌时,R/B#信号被拉低;操作完成,准备就绪时,R/B#信号恢复为高电平。因此,软件读取NANDFSR的值,实际上就是在读取R/B#信号的实时状态。
这里有一个关键细节:NANDFSR反映的是“原始”状态。这意味着它的值不受异步等待周期配置寄存器(AWCC)中WPn位的影响。WPn位用于配置EMA_WAIT引脚的有效电平(高有效或低有效),以适配不同异步设备的等待协议。但对于NAND Flash模式,EMIFA硬件逻辑固定地将EMA_WAIT(即R/B#)的低电平视为“忙”,高电平视为“就绪”。这种设计简化了软件逻辑,软件无需关心极性配置,直接判断NANDFSR是否为0即可知道Flash是否忙碌。
实操心得:状态轮询与超时处理在实际编程中,单纯轮询NANDFSR是一种简单但低效的方式。一个健壮的驱动应该实现带超时的轮询。例如,在发起一个页编程(Page Program)命令后,代码应进入一个循环,不断读取NANDFSR,同时递减一个超时计数器。如果Flash在超时前变为就绪,则操作成功;如果超时计数器归零仍为忙,则意味着操作可能失败(如坏块、电压异常),需要进入错误处理流程。超时时间应参考Flash数据手册中最长的页编程或块擦除时间,并留有一定余量。
1.2 等待上升沿中断(Wait Rise Interrupt)的妙用
轮询始终会占用CPU资源。为了将CPU从这种低效的等待中解放出来,EMIFA提供了基于硬件事件的异步通知机制——等待上升沿中断。其工作原理如下:
- 事件检测:当EMIFA在
EMA_WAIT引脚上检测到一个从低到高的跳变(上升沿)时,硬件会自动将中断原始状态寄存器(INTRAW)中的WR(Wait Rise)位置1。这个动作与WPn位的配置无关,只要检测到上升沿就触发。 - 中断使能:
WR位置1仅代表事件发生了。是否产生CPU中断,还取决于中断是否被使能。通过设置中断掩码设置寄存器(INTMSKSET)中的WR_MASK_SET位为1,来使能此中断。 - 中断状态:一旦中断被使能且事件发生,中断掩码寄存器(
INTMSK)中的WR_MASKED位也会被置1。这个位是INTRAW.WR与中断使能状态的“与”结果,更直接地指示了是否有有效的中断等待处理。 - 中断清除:中断服务程序(ISR)在处理完事件后,必须通过向
INTRAW.WR位写入1来清除中断状态。这个操作会同时清除INTRAW.WR和INTMSK.WR_MASKED位。
为什么这个机制如此重要?它实现了高效的“命令-通知”式异步操作。软件流程可以这样设计:
- 发起操作:CPU向NAND Flash发送读/写命令序列。
- 触发等待:命令发出后,Flash拉低
R/B#,CPU无需轮询,可以转而执行其他任务或进入低功耗模式。 - 硬件通知:Flash操作完成,
R/B#变高,EMIFA检测到上升沿,触发中断。 - 处理完成:CPU被中断唤醒,进入ISR,知道之前的Flash操作已完成,可以安全地读取数据或发起下一阶段操作。
这种方式极大地提高了系统的并发性和能效比。
1.3 与非CE无关型(Non-CE Don‘t Care)NAND Flash的接口变通
EMIFA在NAND Flash模式下的一个硬件限制是,它不支持在tR(读周期时间)期间需要片选信号(CE#)持续保持有效的Flash器件。标准的NAND Flash接口时序中,在发出读命令和地址后,需要等待tR时间才能读取数据。有些Flash要求在这整个tR期间CE#必须持续有效(即保持低电平),而EMIFA的硬件时序生成器可能在tR期间会释放CE#。
面对这种不兼容,手册给出了一个经典的软件辅助硬件(Software-Assisted Hardware)解决方案:使用一个通用的GPIO引脚来模拟控制Flash的CE#信号。
具体操作步骤:
- 硬件连接:将一颗GPIO引脚连接到NAND Flash的
CE#引脚上。EMIFA自身的EMA_CS[n]引脚可能悬空或接固定电平。 - 操作开始:在发起任何NAND Flash操作(命令、地址、数据阶段)之前,软件先将这个GPIO配置为输出并拉低,手动使能Flash芯片。
- EMIFA操作:随后,软件再通过EMIFA的地址/数据总线向Flash发送命令序列。此时,EMIFA控制的
EMA_WE(写使能)、EMA_OE(读使能)等信号正常工作,但片选由GPIO提供。 - 操作结束:等待操作完成(通过轮询
NANDFSR或中断)后,软件再将GPIO拉高,禁用Flash。
注意事项与潜在风险这个方法虽然巧妙,但引入了时序上的软件开销。GPIO的置位/清零操作由CPU执行,其速度远慢于EMIFA的硬件状态机,这可能会在命令序列的各个阶段之间引入不可预测的微小延迟。对于时序非常严格的Flash型号,这种延迟可能导致操作失败。因此,在选用此方案前,必须仔细核对目标Flash数据手册中的最小CE#脉冲宽度、命令/地址/数据建立保持时间等参数,确保软件GPIO操作引入的延迟仍在允许范围内。通常,这会要求CPU运行在较高主频,且GPIO操作代码路径经过高度优化。
2. 扩展等待模式(Extended Wait Mode)与异步超时管理
当EMIFA连接低速异步设备(如Nor Flash、SRAM或某些定制外设)时,固定的访问周期可能无法满足其较长的数据准备时间。扩展等待模式就是为了解决这个问题而设计的,它允许外部设备通过EMA_WAIT信号动态地“拉长”EMIFA的访问周期。
2.1 扩展等待模式的工作原理
使能该模式非常简单,只需在对应的异步片选配置寄存器(CEnCFG)中设置EW位。一旦使能,EMIFA在每次访问该片选空间时,会在固定的建立(Setup)周期和编程的选通(Strobe)周期之后,持续采样EMA_WAIT引脚的状态。
- 等待插入:如果
EMA_WAIT引脚处于有效电平(由AWCC.WPn位定义极性,高有效或低有效),EMIFA就会暂停当前总线周期,插入额外的等待时钟周期。此时,所有控制信号(CE#,OE#,WE#)保持当前状态,地址和数据总线也保持不变,相当于给外部设备“冻结”了时间。 - 等待退出:当外部设备完成操作,将
EMA_WAIT信号置为无效电平时,EMIFA会结束等待状态,继续完成剩余的选通周期(如果还有的话),然后进入保持(Hold)周期,最终结束本次访问。 - 时序约束:为了确保EMIFA能可靠采样到
EMA_WAIT信号,手册对建立和选通周期的总和做出了限制(必须大于4个EMA_CLK周期)。这是因为EMIFA需要一定的时间来稳定总线并采样外部信号,如果周期太短,采样窗口不足,可能导致误判。
2.2 异步超时中断与安全防护
扩展等待模式赋予了外部设备极大的灵活性,但也带来了系统挂起的风险:如果外部设备故障,EMA_WAIT信号永远保持有效怎么办?为了防止整个系统被一个故障外设“拖死”,EMIFA引入了异步超时(Asynchronous Timeout)保护机制。
异步等待周期配置寄存器(AWCC)中的MAX_EXT_WAIT字段定义了等待周期的上限。当EMIFA插入的等待周期数达到这个最大值时,无论EMA_WAIT信号状态如何,它都会强制终止等待,继续完成总线周期。同时,如果异步超时中断被使能(通过设置INTMSKSET.AT_MASK_SET),此时还会产生一个中断。
配置要点:MAX_EXT_WAIT的值需要根据外设的最长可能响应时间来谨慎设置。设得太小,可能导致正常设备操作超时失败;设得太大,则故障情况下的系统恢复时间过长。一个合理的做法是,参考外设数据手册中的最大访问时间,换算成EMIFA时钟周期数,再乘以一个安全系数(如1.5倍)。
2.3 数据总线保持(Data Bus Parking)机制及其例外
为了降低功耗和减少总线噪声,EMIFA在空闲时会执行“数据总线保持”操作:它持续驱动数据总线,使其保持在上一次写入数据的电平值。这可以防止总线浮空,避免因引脚电平不确定而产生的漏电流。
然而,存在一个重要的例外情况:当EMIFA处于自刷新(Self-Refresh)状态时执行异步读操作。自刷新状态是为了SDRAM省电而设计的,此时EMIFA的核心时钟可能被大幅降低或门控。如果在这种状态下发起一个异步读操作,在操作结束后,EMIFA可能不会重新驱动数据总线,导致总线进入高阻态。
风险与解决方案:总线浮空意味着连接到该总线上所有设备的输入引脚处于不确定电平,这可能导致额外的功耗,甚至引发逻辑错误。手册明确建议应避免在此状态下进行异步读操作。如果系统设计无法避免,则必须在硬件上为EMIFA数据总线(EMA_D[15:0])添加外部上拉电阻(例如10kΩ)。电阻值的选择需要计算,确保在所有可能的总线负载和漏电流情况下,高电平电压仍能满足VIH(输入高电平电压)的最低要求。
3. EMIFA的中断系统与电源管理策略
EMIFA的中断系统设计精炼而实用,仅通过一个中断线向CPU报告三种关键事件。同时,其电源管理策略与存储器的特性深度结合,旨在满足嵌入式系统对低功耗的严苛要求。
3.1 三种中断事件详解
除了前述的等待上升沿中断(WR)和异步超时中断(AT),EMIFA还支持第三种中断:行捕获中断(LT, Line Trap Interrupt)。
- 行捕获中断(LT):EMIFA的地址生成模式仅支持线性递增(Linear Increment)和缓存行回绕(Cache Line Wrap)两种。如果DMA控制器或CPU等主设备试图以不支持的寻址模式(例如位反转寻址)访问EMIFA映射的内存空间,EMIFA会触发此中断。同时,它会将此次访问按线性递增模式处理。这个中断对于调试DMA配置错误或异常的软件访问模式非常有用。
中断控制流程总结:
- 事件发生:WR、AT、LT三个条件之一触发,
INTRAW中对应位被硬件置1。 - 使能控制:通过
INTMSKSET寄存器使能特定中断,通过INTMSKCLR寄存器禁用。 - 状态查询:
INTMSK寄存器反映了“已使能且已发生”的中断状态,是中断服务程序(ISR)中判断中断源的直接依据。 - 中断清除:向
INTRAW的对应位写1,可清除该中断的原始状态和掩码状态。
3.2 复位与初始化序列的严谨性
EMIFA拥有两个层级的复位信号:CHIP_RST(芯片级复位)和MOD_G_RST(模块级全局复位)。CHIP_RST会复位整个模块,包括状态机和所有存储器映射寄存器;而MOD_G_RST仅复位状态机,寄存器值得以保留。
一个至关重要的警告:在任何一个复位信号有效期间,软件绝对不能访问EMIFA的寄存器或通过EMIFA访问外部存储器。因为此时内部状态机处于非工作状态,此类访问请求可能无法得到响应,导致发起访问的主设备(如CPU、DMA)挂起,等待超时,从而引发系统级故障。
复位释放后,如果连接了SDRAM,EMIFA会自动执行SDRAM初始化序列。但请注意,即使初始化是自动的,软件仍需遵循一个特定的流程(如手册第16.2.4.5节所述),主要是在初始化前后正确配置SDRAM配置寄存器(SDCR),并可能涉及自刷新状态的进出。
3.3 多级电源管理策略
EMIFA的电源管理是一个由浅入深的渐进式策略,功耗与唤醒延迟的权衡是核心考量。
第一级:自刷新模式这是最温和的省电方式。通过设置SDCR.SR位,EMIFA命令连接的SDRAM进入自刷新状态。SDRAM利用内部时钟进行刷新,EMIFA和主控的时钟可以保持运行。退出延迟短,适用于短时空闲。EMIFA自身功耗降低有限,主要节省的是SDRAM的功耗。
第二级:掉电模式通过驱动EMA_SDCKE信号为低,使SDRAM进入更深的掉电状态。EMIFA会在需要刷新时临时唤醒SDRAM,完成后再次进入掉电。此模式SDRAM功耗比自刷新更低,但EMIFA仍需定期操作,自身功耗未显著降低。
第三级:时钟门控这是最彻底的省电手段,通过电源与睡眠控制器(PSC)和PLL控制器,直接关闭EMIFA模块的输入时钟。模块内部逻辑停止翻转,静态功耗大幅降低。前提是必须先将SDRAM置于自刷新模式,以保持数据。唤醒时,需要先恢复时钟,再将SDRAM退出自刷新。
PSC为时钟门控提供了两种子模式:
- 自动睡眠/自动唤醒:在此模式下,即使EMIFA处于睡眠(时钟关闭),如果收到访问请求,模块会自动唤醒(恢复时钟)处理请求,处理完毕后再自动睡眠。这适用于间歇性访问的场景,实现了功耗与性能的自动平衡。
- 同步复位/使能:在此模式下,进入同步复位状态后,EMIFA完全“沉睡”,不响应任何访问请求。必须由软件显式将其切换回“使能”状态,才能恢复工作。这适用于系统明确知道将进入长时间无访问状态的场景,避免了自动唤醒的开销。
配置心得:功耗与实时性的权衡选择哪种电源管理模式,取决于系统的功耗预算和性能要求。对于实时性要求高的系统,可能只敢使用自刷新模式。对于大部分时间休眠、偶尔唤醒采集数据的设备,自动睡眠模式非常合适。而对于完全断电前保存状态的场景,则可以使用同步复位模式。关键是要在关闭EMIFA时钟前,务必确认SDRAM已稳定进入自刷新状态,否则数据丢失将是灾难性的。
4. 系统级设计考量与实战配置示例
将EMIFA集成到系统中,不能只关注其本身,必须从系统全局视角审视其带来的影响和约束。
4.1 异步访问时长与SDRAM��新死线
当EMIFA同时连接SDRAM和异步存储器(如Flash)时,一个隐蔽但致命的问题会出现:过长的异步访问会阻塞SDRAM的刷新,导致数据丢失。
SDRAM需要定期刷新以保持数据。EMIFA内部有一个刷新计数器来管理此事。但如果一个来自异步存储器的访问请求耗时过长,它可能独占EMIFA接口,导致刷新被延迟超过最大允许时间(tREFI)。更严重的是,一个打开的行(Active Row)必须在tRASmax时间内被预充电(Precharge),否则也会损坏数据。
系统设计约束: 手册给出了一个明确的约束:任何异步请求的持续时间,不能超过min(tRASmax, 11 * tREFI)。对于典型的SDRAM,tRASmax约为120µs,tREFI约为15.7µs(64ms/4096行),因此11 * tREFI约为172.7µs。所以,异步单次访问最长不得超过约120µs。
如何确保满足约束?这需要从多方面控制:
- 限制请求大小:EMIFA单次最大传输为16个字(32字节@16位总线,64字节@8位总线)。需评估最大请求所需的时钟周期数。
- 优化时序参数:合理设置异步访问的建立、选通、保持时间,在满足外设时序的前提下尽可能缩短。
- 慎用扩展等待:
MAX_EXT_WAIT的设置不能只考虑外设需求,还必须用上述死线进行校验。 - 考虑总线宽度:使用16位数据总线相比8位总线,传输相同数据量的周期数减半,直接降低了访问时长。
4.2 缓存填充请求的阻塞效应
当CPU从EMIFA连接的外部存储器执行代码时,其内部缓存会发生“缓存行填充”操作,即一次性从外部内存读取一整行数据(例如32字节)。EMIFA为这种填充提供了一个高优先级的专用端口。
这引发了两个系统级问题:
- 缓存填充被饿死:如果存在一个高优先级的主设备(如视频处理DMA)持续向EMIFA发起请求,它可能通过外部仲裁器长期占用EMIFA,导致CPU的缓存填充请求无法及时得到响应,造成CPU执行停滞(Cache Miss Stall)。
- 其他请求被阻塞:反过来,当EMIFA正在处理一个缓存填充请求时,这个操作是不可打断的。在此期间到达的其他所有请求(无论优先级高低)都必须排队等待。这增加了其他请求的延迟(Latency)。
设计建议: 在系统设计初期,需要分析最坏情况下的访问延迟。特别是要评估在最长可能的缓存填充操作期间,其他高实时性请求(如音频DMA)的延迟是否仍在可接受范围内。可能需要通过调整仲裁权重、限制高优先级主设备的突发长度、或将关键数据与代码放入片内SRAM等方式来规避风险。
4.3 实战配置:连接SDRAM与Flash
手册提供了一个连接三星K4S641632H SDRAM和夏普LH28F800BJE Flash的示例。这里以SDRAM配置为例,详解寄存器配置背后的计算逻辑。
核心配置寄存器:
SDRAM时序寄存器(SDTIMR):此寄存器配置SDRAM操作的各种延迟。每个字段的值并非随意填写,而是根据SDRAM数据手册的时序参数和EMIFA时钟频率(
fEMA_CLK)计算得出。公式为:寄存器值 >= (时序参数 × 时钟频率) - 1。- 示例:计算T_RP。手册要求
tRP(行预充电时间)最小为20ns。假设fEMA_CLK = 100MHz,周期为10ns。则T_RP >= (20ns / 10ns) - 1 = 2 - 1 = 1。因此T_RP字段至少设置为1。工程师通常会在此基础上增加一些余量(比如设为2),以应对时钟抖动和信号完整性带来的时序裕量损失。
- 示例:计算T_RP。手册要求
SDRAM刷新控制寄存器(SDRCR):其
RR(Refresh Rate)字段决定自动刷新的间隔。计算依据是:RR <= fEMA_CLK × tRefreshPeriod / ncycles。- 示例:K4S641632H的刷新周期
tRefreshPeriod是64ms,需要在64ms内完成4096次刷新(ncycles)。fEMA_CLK=100MHz。则RR <= (100e6 Hz × 64e-3 s) / 4096 ≈ 1562.5。取整后RR设置为1562(0x61A)。这个值设置得越小,刷新越频繁,功耗略高但更安全;设置得越大,刷新间隔越长,功耗更低但风险增加。必须小于等于计算值。
- 示例:K4S641632H的刷新周期
SDRAM自刷新退出时序寄存器(SDSRETR):配置从自刷新状态退出的延迟
T_XS,计算方法与时序寄存器类似,对应参数tXSR。
配置流程要点:
- 先静后动:在改变EMIFA或PLL时钟前,应先将SDRAM置于自刷新模式(写
SDCR的高字节设置SR位),防止时钟变化期间丢失数据。 - 配置时序:按照计算好的值,配置
SDTIMR、SDSRETR、SDRCR。 - 触发初始化:通过对
SDCR的低字节进行写操作(通常是与之前相同的值),来触发EMIFA执行完整的SDRAM初始化序列。这个序列包括预充电、多个自动刷新、模式寄存器设置等,均由硬件自动完成。 - 退出自刷新:如果之前进入了自刷新,在时钟稳定且初始化完成后,再通过写
SDCR高字节清除SR位,使SDRAM退出自刷新,进入正常工作状态。
整个配置过程体现了硬件模块化设计的优势:软件只需配置好参数,复杂的底层时序和状态转换由硬件状态机可靠完成,极大地降低了驱动开发的难度和风险。然而,对数据手册参数的精确理解、对时序的计算与余量分配,依然是确保系统长期稳定运行的关键。