STM32H7 FMC同步模式下NOR Flash突发读时序参数计算与验证
1. 同步突发读的优势与挑战
STM32H7的FMC(Flexible Memory Controller)支持同步模式访问NOR Flash,利用时钟同步和突发传输,可大幅提升连续读取带宽。相比异步模式,同步模式需要精确配置时序参数,否则会出现数据采样错误。
核心参数:
-
CLKDivision:FMC输出时钟分频,决定FMC_NCLK频率。 -
DataLatency:数据延迟周期,即从时钟边沿到数据有效的等待周期。 -
BusTurnAround:总线转向时间,用于读写切换。 -
ClockEdge:时钟边沿选择(上升沿/下降沿)。 -
BurstLength:突发长度(如4、8、16等)。
2. 时序计算原理
同步读时序基于FMC时钟FMC_NCLK。假设HCLK=200MHz,分频系数CLKDivision=2,则FMC_NCLK=100MHz,周期T=10ns。
NOR Flash数据手册会给出以下关键时间:
-
tCLK:时钟周期最小值。 -
tDV:数据有效到时钟边沿的建立时间。 -
tDH:时钟边沿后数据保持时间。 -
tLZ:时钟边沿到数据低阻(输出有效)的延迟。
DataLatency计算:
DataLatency = ceil( (tLZ + tDV) / T ) - 1
其中tLZ和tDV取最大值,T为FMC时钟周期。减1是因为FMC内部已有一个周期的固定延迟。
示例:若tLZ=8ns,tDV=2ns,T=10ns,则DataLatency = ceil(10/10)-1 = 0。
建立/保持时间检查:
- 建立时间:
tDV >= (DataLatency+1)*T - tLZ - 保持时间:
tDH >= T - tDV(需满足Flash要求)
3. 配置步骤与代码
以STM32H7 HAL库为例,配置FMC同步模式读NOR Flash。
#include "stm32h7xx_hal.h"
FMC_NORSRAM_TimingTypeDef Timing = {0};
FMC_NORSRAM_InitTypeDef Init = {0};
/* 1. 使能FMC时钟和GPIO */
__HAL_RCC_FMC_CLK_ENABLE();
// GPIO配置略(参考数据手册)
/* 2. 配置时序参数 */
Timing.AddressSetupTime = 2; // 地址建立时间(HCLK周期)
Timing.AddressHoldTime = 1; // 地址保持时间
Timing.DataSetupTime = 4; // 数据建立时间(异步模式用)
Timing.BusTurnAroundDuration = 1; // 总线转向
Timing.CLKDivision = 2; // FMC_NCLK = HCLK/2
Timing.DataLatency = 1; // 数据延迟周期
Timing.AccessMode = FMC_ACCESS_MODE_D; // 模式D(同步突发)
/* 3. 初始化NORSRAM控制器 */
Init.NSBank = FMC_NORSRAM_BANK1;
Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
Init.MemoryType = FMC_MEMORY_TYPE_NOR;
Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_ENABLE;
Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
Init.WaitSignal = FMC_WAIT_SIGNAL_ENABLE;
Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
Init.ClockEdge = FMC_CLK_RISING_EDGE;
Init.ClockDivision = FMC_CLK_DIV_2;
HAL_FMC_NORSRAM_Init(FMC_NORSRAM_DEVICE, &Init);
HAL_FMC_NORSRAM_Timing_Init(FMC_NORSRAM_DEVICE, &Timing, FMC_NORSRAM_BANK1);
/* 4. 使能FMC */
HAL_FMC_NORSRAM_Extended_Timing_Init(FMC_NORSRAM_DEVICE, &Timing, FMC_NORSRAM_BANK1, FMC_EXTENDED_MODE_DISABLE);
__HAL_FMC_NORSRAM_ENABLE(FMC_NORSRAM_DEVICE, FMC_NORSRAM_BANK1);
4. 验证方法
-
示波器测量:观察
FMC_NCLK、FMC_NADV、FMC_NWE、数据线,检查数据采样点是否在有效窗口内。 - 软件测试:写入已知模式(如0xAA55),连续读取并校验。使用DMA可测试突发性能。
- 性能对比:测量同步模式与异步模式的读取速度,通常同步模式可提升2-3倍。
-
边界测试:改变
DataLatency,观察何时出现错误,确定安全裕量。
5. 注意事项
-
时钟分频:
CLKDivision不能过小,需满足Flash的tCLK最小值。 -
数据延迟:
DataLatency过小会导致采样错误,过大降低性能。建议留1个周期裕量。 -
总线转向:读写切换频繁时,
BusTurnAroundDuration需足够大。 - PCB布局:同步时钟线需等长,减少 skew。
- 电压与温度:时序参数随电压温度变化,需按最坏情况设计。
- HAL库版本:不同版本API可能略有差异,请参考对应手册。
通过精确计算和实验验证,可充分发挥STM32H7 FMC同步模式的高速读取能力,满足嵌入式系统对存储带宽的严苛需求。