STM32H7 FMC同步模式NOR Flash时序参数逐位计算与示波器验证实战

1. 同步模式时序原理

STM32H7的FMC(Flexible Memory Controller)支持同步模式访问NOR Flash,此时FMC输出时钟FMC_CLK,数据在时钟边沿采样。关键参数:

  • CLKDIV:FMC_CLK分频系数,FMC_CLK = HCLK / (CLKDIV + 1)。
  • DATAST:数据建立时间,以FMC_CLK周期为单位,表示读/写数据有效到下一个时钟边沿的延迟。
  • ADDHLD:地址保持时间,以HCLK周期为单位,表示地址有效到数据相位开始的延迟。

同步读时序:地址在ADDHLD后有效,经过DATAST个FMC_CLK周期后数据被采样。写时序类似,但数据由FMC驱动。

2. 逐位计算步骤

假设HCLK = 200MHz,NOR Flash要求:

  • tCLK ≥ 10ns(FMC_CLK周期)
  • 读数据建立时间tDS ≥ 15ns
  • 地址保持时间tAH ≥ 5ns

2.1 计算CLKDIV

FMC_CLK周期 = (CLKDIV + 1) * HCLK周期。HCLK周期 = 5ns。要求FMC_CLK周期 ≥ 10ns,则CLKDIV + 1 ≥ 2,取CLKDIV = 1(FMC_CLK = 100MHz,周期10ns)。

2.2 计算DATAST

DATAST需满足:DATAST * FMC_CLK周期 ≥ tDS。tDS = 15ns,FMC_CLK周期 = 10ns,则DATAST ≥ 1.5,取整为2。

2.3 计算ADDHLD

ADDHLD以HCLK周期为单位:ADDHLD * HCLK周期 ≥ tAH。tAH = 5ns,HCLK周期 = 5ns,则ADDHLD ≥ 1,取1。

3. 完整配置代码

#include "stm32h7xx_hal.h"

FMC_NORSRAM_TimingTypeDef Timing = {0};
FMC_NORSRAM_InitTypeDef Init = {0};

void FMC_Init(void) {
    // 使能FMC时钟和GPIO时钟
    __HAL_RCC_FMC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOF_CLK_ENABLE();
    __HAL_RCC_GPIOG_CLK_ENABLE();

    // 配置GPIO为复用推挽,高速
    GPIO_InitTypeDef GPIO_Init = {0};
    GPIO_Init.Mode = GPIO_MODE_AF_PP;
    GPIO_Init.Pull = GPIO_NOPULL;
    GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_Init.Alternate = GPIO_AF12_FMC;

    // 地址线A0-A25, 数据线D0-D15, 控制线等(根据实际连接)
    // 此处省略具体引脚配置,需参考原理图

    // FMC NOR/SRAM 初始化
    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_DISABLE;
    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.WriteFifo = FMC_WRITE_FIFO_DISABLE;
    HAL_FMC_NORSRAM_Init(&hfmc, &Init);

    // 时序配置
    Timing.ClockDivision = 1;      // CLKDIV = 1
    Timing.DataLatency = 2;        // DATAST = 2
    Timing.AddressSetupTime = 1;   // ADDHLD = 1
    Timing.AddressHoldTime = 0;    // 同步模式忽略
    Timing.DataSetupTime = 2;      // 同DATAST
    Timing.BusTurnAroundDuration = 0;
    HAL_FMC_NORSRAM_Timing_Init(&hfmc, &Timing, FMC_NORSRAM_BANK1);

    // 使能FMC控制器
    __HAL_FMC_NORSRAM_ENABLE(&hfmc, FMC_NORSRAM_BANK1);
}

4. 示波器验证方法

  1. 测量FMC_CLK频率:探头接FMC_CLK引脚,确认周期为10ns(100MHz)。
  2. 测量读时序:触发FMC_CLK上升沿,观察地址线、数据线。地址应在ADDHLD后稳定,数据在DATAST个时钟后有效。
  3. 测量写时序:类似,检查数据在时钟边沿前稳定。
  4. 调整参数:若数据建立不足,增大DATAST;若地址保持不足,增大ADDHLD。

5. 注意事项

  • CLKDIV必须保证FMC_CLK不超过Flash最大频率。
  • DATAST和ADDHLD需留有余量,考虑PCB走线延迟。
  • 同步模式下,连续时钟模式可提高吞吐量。
  • 使用HAL库时,注意Timing结构体成员对应关系。
  • 验证时使用高带宽示波器(≥500MHz)和低电容探头。

通过逐位计算和示波器验证,可确保FMC与NOR Flash稳定通信,发挥STM32H7高性能优势。