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为例:

  1. 使能FMC:在Connectivity中选FMC,模式选“Synchronous NOR Flash”。
  2. 配置时钟:FMC时钟源为HCLK3(200MHz),CLK分频选2,输出100MHz。
  3. 设置时序
    • 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
  4. 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]; // 触发突发读
    }
}

四、实测校准方法

  1. 示波器测量:用探头同时抓取FMC_CLK和FMC_D0,观察数据有效窗口。
  2. 调整DataLatency:若数据在CLK上升沿不稳定,逐步增加DataLatency(每次+1),直到数据稳定。
  3. 调整HoldTime:若数据在下一个CLK沿前变化,增加HoldTime(每次+1)。
  4. 验证:写入已知模式(如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。