QSPI、OSPI与FSMC的区别与内存映射分析

基本概念与区别

1. FSMC (灵活静态存储控制器)

  • 接口类型:并行接口,通常8/16位数据总线
  • 总线标准:传统并行总线协议
  • 速度:相对较低,通常最高约100MHz
  • 应用场景:SRAM、NOR Flash、PSRAM、LCD等并行接口外设

2. QSPI (四线串行外设接口)

  • 接口类型:串行接口,1/2/4线数据传输
  • 总线标准:SPI协议的扩展
  • 速度:中等,通常最高约108MHz,有效带宽达到50MBytes/s (4线x108MHz/8位)
  • 应用场景:Serial NOR Flash、EEPROM等

3. OSPI (八线串行外设接口)

  • 接口类型:串行接口,1/2/4/8线数据传输
  • 总线标准:QSPI的扩展,兼容QSPI
  • 速度:较高,通常最高约200MHz,有效带宽可达到200MBytes/s (8线x200MHz/8位)
  • 应用场景:高速Serial NOR Flash、Hyperflash、Hyper RAM

内存映射功能对比

FSMC内存映射

  • 直接映射:FSMC直接将外部存储设备映射到CPU的地址空间
  • 访问方式:CPU直接通过地址访问,无需专用命令
  • 优势:实现简单,无需特殊初始化序列
  • 延迟:相对较低,通常1-2个时钟周期
  • 地址范围:STM32上通常映射到0x6000 0000 - 0x6FFF FFFF

QSPI内存映射

  • 间接映射:通过QSPI控制器将闪存内容映射到系统地址空间
  • 访问流程
    1. 控制器发送特定命令(通常是0x0B/0xEB)
    2. 发送地址
    3. 插入可选的虚拟周期
    4. 连续读取数据
  • 映射机制:QSPI控制器自动处理命令序列
  • 地址范围:典型映射到0x9000 0000 - 0x9FFF FFFF

OSPI内存映射

  • 增强型映射:支持QSPI的所有功能,并增加了8线模式支持
  • 访问流程:与QSPI相似,但可以使用8线传输
  • 高级特性
    1. 支持更复杂的命令序列
    2. 双闪存同时访问(STM32H7系列)
    3. 内存映射期间支持XIP缓存
  • 地址范围:类似QSPI,但可能有所扩展

XIP (执行时位置)实现方式

FSMC-XIP实现

// FSMC配置NOR Flash映射
void FSMC_NOR_Init(void) {
    FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef p;
    
    // 配置基本时序
    p.FSMC_AddressSetupTime = 0x06;
    p.FSMC_AddressHoldTime = 0x00;
    p.FSMC_DataSetupTime = 0x0B;
    // ...其他时序配置
    
    // 配置NOR控制器
    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
    FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
    // ...其他控制器配置
    
    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
    
    // 映射后可直接访问和执行,无需额外步骤
}

// 代码执行示例
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
void ExecuteFromNOR(void) {
    // 直接跳转到NOR Flash中的代码
    Jump_To_Application = (pFunction)(0x60000000 + 0x1000); // 示例地址
    Jump_To_Application();
}

QSPI-XIP实现

// QSPI内存映射模式配置
void QSPI_MemoryMapped_Init(void) {
    QSPI_CommandTypeDef s_command;
    QSPI_MemoryMappedTypeDef s_mem_mapped_cfg;
    
    // 配置读取命令
    s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
    s_command.Instruction = QUAD_INOUT_FAST_READ_CMD; // 通常是0xEB
    s_command.AddressMode = QSPI_ADDRESS_4_LINES;
    s_command.AddressSize = QSPI_ADDRESS_24_BITS;
    s_command.DataMode = QSPI_DATA_4_LINES;
    // ...其他命令配置
    
    // 配置内存映射参数
    s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
    
    // 启用内存映射模式
    HAL_QSPI_MemoryMapped(&hqspi, &s_command, &s_mem_mapped_cfg);
    
    // 此时Flash已映射到地址空间,可以执行代码
}

// 代码执行示例
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
void ExecuteFromQSPI(void) {
    // 使能Cache以提高XIP性能
    SCB_EnableICache();
    SCB_EnableDCache();
    
    // 跳转到QSPI映射区域的代码
    Jump_To_Application = (pFunction)(0x90000000 + 0x1000); // 示例地址
    Jump_To_Application();
}

OSPI-XIP实现

// OSPI内存映射模式配置 (STM32H7系列示例)
void OSPI_MemoryMapped_Init(void) {
    OSPI_RegularCmdTypeDef sCommand;
    OSPI_MemoryMappedTypeDef sMemMappedCfg;
    
    // 配置读取命令 (8线模式)
    sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
    sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
    sCommand.Instruction = OCTO_READ_CMD; // 例如0x8B/0xEC
    sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
    sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
    sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
    sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
    sCommand.DataMode = HAL_OSPI_DATA_8_LINES;
    // ...其他命令配置
    
    // 配置内存映射参数
    sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;
    
    // 启用OSPI内存映射模式
    HAL_OSPI_MemoryMapped(&hospi, &sCommand, &sMemMappedCfg);
    
    // 此时可以直接执行映射区域的代码
}

// 代码执行示例
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
void ExecuteFromOSPI(void) {
    // 使能Cache以提高XIP性能
    SCB_EnableICache();
    SCB_EnableDCache();
    
    // 跳转到OSPI映射区域的代码
    Jump_To_Application = (pFunction)(0x90000000 + 0x1000); // 示例地址
    Jump_To_Application();
}

性能与应用对比

XIP性能对比

  1. 访问延迟

    • FSMC: 低延迟,但总体带宽受限
    • QSPI: 首次访问延迟高,但连续读取性能好
    • OSPI: 首次访问延迟较高,但连续读取性能最佳
  2. 缓存影响

    • 三种接口都受益于CPU缓存
    • 对于QSPI/OSPI,缓存几乎是必需的
    • STM32H7还为QSPI/OSPI提供了专用的ART加速器
  3. 代码执行速度

    • FSMC: ~15-30MB/s
    • QSPI: ~30-50MB/s
    • OSPI: ~80-200MB/s

适用场景

  • FSMC:

    • 需要兼容旧设备
    • 需要简单直接的访问方式
    • 接口引脚数量不受限
  • QSPI:

    • 需要节省PCB空间(较少引脚)
    • 中等执行性能要求
    • 大多数现代系统选择
  • OSPI:

    • 高性能应用
    • 运行复杂应用程序
    • 需要支持大容量闪存

总结

FSMC、QSPI和OSPI代表了嵌入式系统外部存储接口的发展历程:从并行到串行,从单线到多线。在内存映射和XIP方面,三种接口都支持,但实现复杂度和性能各不相同。对于现代STM32应用,QSPI和OSPI因其更好的性能/空间比和灵活性而成为更流行的选择,特别是对于需要执行复杂代码的应用程序。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐