STM32H7 FMC同步模式NOR Flash突发读时序配置与实测校准
一、同步突发读原理
STM32H7的FMC(Flexible Memory Controller)支持同步模式访问NOR Flash,通过CLK信号同步数据传输,实现远高于异步模式的吞吐率。同步突发读的核心是:FMC在CLK上升沿采样数据,Flash在CLK边沿输出数据,双方必须严格满足时序关系。
关键时序参数包括:
- CLK分频:FMC时钟(HCLK3)分频后输出到Flash,决定突发速率。
- 数据延迟(Data Latency):从地址锁存到第一个数据有效的CLK周期数,对应Flash的初始访问时间。
- 保持时间(Hold Time):数据保持有效的CLK周期数,用于补偿PCB走线延迟。
- 建立时间(Setup Time):片选/地址建立到CLK有效的时间。
若参数配置不当,会出现读取数据错位、偶发错误甚至总线HardFault。
二、CubeMX配置步骤
以STM32H743 + S29GL256P NOR Flash为例:
- 使能FMC:在Connectivity中选FMC,模式选“Synchronous NOR Flash”。
- 配置时钟:FMC时钟源为HCLK3(200MHz),CLK分频选2,输出100MHz。
-
设置时序:
- Address setup: 1 HCLK
- Address hold: 1 HCLK
- Data setup: 2 HCLK
- Bus turn around: 1 HCLK
- CLK division: 2
- Data latency: 4 CLK
- Hold time: 1 CLK
- GPIO:确保FMC_CLK、FMC_NWAIT等引脚正确映射。
三、完整代码示例
#include "stm32h7xx_hal.h"
FMC_NORSRAM_TimingTypeDef Timing = {0};
FMC_NORSRAM_InitTypeDef Init = {0};
void MX_FMC_Init(void)
{
FMC_NORSRAM_TimingTypeDef ExtTiming = {0};
/* 同步模式时序 */
Timing.AddressSetupTime = 1;
Timing.AddressHoldTime = 1;
Timing.DataSetupTime = 2;
Timing.BusTurnAroundDuration = 1;
Timing.CLKDivision = 2;
Timing.DataLatency = 4;
Timing.AccessMode = FMC_ACCESS_MODE_B; // 同步突发模式
/* 扩展时序(用于同步模式保持) */
ExtTiming.CLKDivision = 2;
ExtTiming.DataLatency = 4;
ExtTiming.AccessMode = FMC_ACCESS_MODE_B;
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_ENABLE;
Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
HAL_FMC_NORSRAM_Init(FMC_NORSRAM_DEVICE, &Init);
HAL_FMC_NORSRAM_Timing_Init(FMC_NORSRAM_DEVICE, &Timing, FMC_NORSRAM_BANK1);
HAL_FMC_NORSRAM_Extended_Timing_Init(FMC_NORSRAM_DEVICE, &ExtTiming, FMC_NORSRAM_BANK1, Init.ExtendedMode);
HAL_FMC_NORSRAM_WriteOperation_Enable(FMC_NORSRAM_DEVICE, FMC_NORSRAM_BANK1);
}
/* 突发读测试 */
void NOR_BurstReadTest(void)
{
uint16_t *nor_addr = (uint16_t *)0x60000000;
uint16_t buffer[256];
for (int i = 0; i < 256; i++) {
buffer[i] = nor_addr[i]; // 触发突发读
}
}
四、实测校准方法
- 示波器测量:用探头同时抓取FMC_CLK和FMC_D0,观察数据有效窗口。
- 调整DataLatency:若数据在CLK上升沿不稳定,逐步增加DataLatency(每次+1),直到数据稳定。
- 调整HoldTime:若数据在下一个CLK沿前变化,增加HoldTime(每次+1)。
- 验证:写入已知模式(如0xAA55),连续读取1MB,比较错误率。
推荐使用STM32H7的FMC错误中断或DMA传输校验。
五、注意事项
- 时钟相位:确保FMC_CLK与Flash的CLK极性一致,否则需调整ClockPhase。
- NWAIT信号:若Flash支持,使能NWAIT可动态插入等待周期,提高鲁棒性。
- PCB走线:CLK与数据线等长,避免skew超过0.5ns。
- 电压与温度:高速下时序会漂移,建议留1-2个CLK余量。
- Cache一致性:若使用D-Cache,需调用SCB_InvalidateDCache_by_Addr()。
通过以上配置与校准,STM32H7可稳定实现100MHz同步突发读,吞吐率可达200MB/s。