[应用相关] STM32与FPGA通过FSMC通信

[复制链接]
1348|33
paotangsan 发表于 2025-11-12 14:39 | 显示全部楼层 |阅读模式
在现代高性能嵌入式系统中,单一芯片往往难以兼顾复杂控制逻辑与高速数据处理。一个典型的解决方案是—— 让STM32负责任务调度和协议管理,而FPGA承担实时信号采集、并行计算或接口桥接 。这种“软件+硬件”的协同架构已在工业视觉、电机控制、通信网关等领域广泛应用。

但问题随之而来:如何实现两者之间的高效通信?传统串行接口如SPI、I2C虽然简单易用,但在图像传输或高采样率AD/DA场景下很快成为瓶颈。此时,开发者往往会将目光投向STM32的一个强大外设: FSMC(Flexible Static Memory Controller) 。

它允许MCU像访问外部SRAM一样直接读写FPGA内部的寄存器或缓存区,从而构建出一条 类内存映射的并行通道 ,理论带宽可达数十MB/s。更重要的是,这种通信方式对CPU负担极小,几乎无需中断介入,非常适合需要持续、低延迟交互的应用。

FSMC的本质是一个专为连接静态存储器设计的控制器,常见于STM32F1/F4/F7/H7等系列。它的核心能力在于模拟标准存储器时序,支持NOR Flash、PSRAM以及 任何具备类似行为的外设 ——这正是我们将FPGA接入的关键突破口。

当STM32发出一个地址(例如 0x60000000 ),FSMC会自动根据Bank配置激活对应的片选信号(如NE1)。随后,地址、数据和控制线同步动作:
- 地址通过 A[0..n] 输出(可复用或独立引脚模式)
- 数据经 D[0..15] 双向总线传输
- OE (读使能)、 WE (写使能)等控制信号配合完成一次访问

整个过程如同MCU在操作一片外挂SRAM,而FPGA只需模拟其响应逻辑即可。

值得注意的是,并非所有STM32都具备FSMC模块。比如F0/F3系列就没有该外设,必须依赖GPIO模拟或使用更高级的FMC(Flexible Memory Controller)。典型支持型号包括STM32F103ZET6、STM32F407VG等LQFP-100及以上封装器件,这些芯片通常提供多达40个相关引脚资源。

为了充分发挥性能,我们需要深入理解几个关键时序参数:

Address Setup Time ( ADDSET ) :地址有效到片选拉低前的建立时间
Address Hold Time ( ADDHLD ) :片选结束后地址仍需保持的时间
Data Setup Time ( DATAST ) :数据出现在总线上所需的准备周期
Bus Recovery Time ( BUSRECOVERY ) :两次连续访问间的恢复间隔
这些值以HCLK(AHB时钟)周期为单位配置,在HAL库中通过 FSMC_NORSRAM_TimingTypeDef 结构体设置。实际调试时建议从保守值开始(如 DATAST=6~10 ),再逐步压缩以提升速率。

相比SPI这类串行总线,FSMC的优势显而易见:

466066912c758137ce.png

显然,FSMC更适合那些 对吞吐量和确定性有严苛要求 的场合,尽管代价是更高的硬件复杂度。

那么FPGA端该如何响应呢?本质上,它需要扮演一个“伪SRAM”角色,正确解析来自STM32的地址、数据和控制信号。以下是Verilog实现的核心思路:

module fsmc_slave (
    input               clk,
    input               rst_n,

    // 双向数据总线
    inout       [15:0]  data_io,
    input       [15:0]  addr,

    // 控制信号
    input               ce_n,     // 片选 (e.g., NE1)
    input               oe_n,     // 读使能
    input               we_n,     // 写使能
    input       [1:0]   ub_lb     // 字节使能
);

reg [15:0] registers [0:255];  // 256个16位寄存器空间
reg [15:0] data_reg;

// 双向IO控制:仅在读取时驱动总线
assign data_io = (ce_n || oe_n) ? 16'bz : data_out;
assign data_out = data_reg;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        data_reg <= 16'h0000;
    else if (!ce_n && !we_n) begin  // 写操作
        case ({ub_lb})
            2'b10: registers[addr] <= {8'hzz, data_io[7:0]};     // 写低字节
            2'b01: registers[addr] <= {data_io[15:8], 8'hzz};   // 写高字节
            2'b00: registers[addr] <= data_io;                  // 全写
            default: ;
        endcase
    end
    else if (!ce_n && !oe_n) begin  // 读操作
        data_reg <= registers[addr];
    end
end

endmodule





这段代码展示了最基本的FSMC从机模型:

使用 inout 声明数据总线,在非读状态置为高阻态避免冲突
支持字节使能(UB/LB),允许单独修改高低字节
所有操作在系统时钟上升沿触发,确保同步稳定性
当然,真实项目中可能还需要考虑更多细节:

电平匹配 :STM32 I/O一般为3.3V LVTTL,若FPGA核心电压为1.8V,则必须确认IO Bank供电及标准是否兼容(如LVCMOS33)
地址映射一致性 :FSMC Bank1子区起始地址固定,例如NE1对应 0x60000000 ,FPGA需据此解码物理地址
时序裕量 :如果FPGA内部逻辑延迟较大,可在STM32侧增加 DATAST 等待周期;更进一步,还可启用 NWAIT 引脚实现流控,由FPGA动态拉低告知“尚未准备好”
抗干扰措施 :长走线易引发亚稳态,建议在FPGA输入端加入两级同步寄存器进行打拍处理
在一个典型的图像采集系统中,这套机制的价值尤为突出。设想如下流程:

FPGA连接CMOS传感器,实时捕获一帧图像并暂存于Block RAM
该缓冲区首地址映射至FSMC空间(如 0x60001000 )
STM32通过指针直接读取:
c uint16_t *img_ptr = (uint16_t *)0x60001000; for(int i = 0; i < PIXEL_COUNT; i++) { pixel_buffer = img_ptr; }
完成后交由JPEG编码并通过USB上传PC
整个过程无需分包、无协议解析开销,实现了近乎“零延迟”的数据搬移。相比之下,SPI不仅速率受限,还需频繁切换命令与数据阶段,极易造成帧率下降甚至丢帧。

类似的场景还包括:

多轴伺服控制系统 :STM32下发位置指令,FPGA以微秒级精度更新PWM占空比
软件定义无线电 :高速ADC采样数据通过FSMC批量送至MCU进行FFT分析
工业网关设备 :FPGA实现CAN/Ethernet物理层解析,STM32专注上层协议转换
这些案例共同验证了一个设计哲学: 把合适的事情交给合适的单元去做 。MCU擅长顺序控制与复杂算法,而FPGA则在并行处理与时序敏感任务上无可替代。

当然,要成功落地这一方案,工程实践中仍有若干要点需要注意:

首先是 引脚规划 。FSMC通常占用超过40个GPIO,且分布较为集中(如STM32F407的PD口大部分被征用)。务必提前在原理图阶段锁定复用功能引脚,避免后期因重映射导致性能下降或功能不可用。

其次是 信号完整性 。并行总线工作在几十MHz频率下,极易受到串扰和反射影响。推荐做法包括:

在每条地址/数据线上串联22~33Ω电阻,抑制高频振铃
PCB布线尽量保持等长,尤其是地址组与数据组之间
电源层分割合理,FSMC区域远离开关电源噪声源
至于时序配置,以下是一段经过验证的HAL库初始化示例:

FSMC_NORSRAM_TimingTypeDef timing = {0};
timing.AddressSetupTime      = 3;  // 3 HCLK cycles
timing.AddressHoldTime       = 1;
timing.DataSetupTime         = 6;  // 关键!根据FPGA响应能力调整
timing.BusTurnAroundDuration = 0;
timing.CLKDivision           = 1;
timing.DataLatency           = 0;
timing.AccessMode            = FSMC_ACCESS_MODE_A;

hnor.Init.NSBank             = FSMC_NORSRAM_BANK1;
hnor.Init.DataAddressMux     = FSMC_DATA_ADDRESS_MUX_DISABLE;
hnor.Init.MemoryType         = FSMC_MEMORY_TYPE_SRAM;
hnor.Init.MemoryDataWidth    = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
hnor.Init.BurstAccessMode    = FSMC_BURST_ACCESS_MODE_DISABLE;
hnor.Init.WriteOperation     = FSMC_WRITE_OPERATION_ENABLE;
hnor.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
hnor.Init.SynchronousMode    = FSMC_ASYNCHRONOUS_MODE;

HAL_SRAM_Init(&hnor, &timing, &timing);






调试过程中强烈建议配合逻辑分析仪抓取真实波形,重点观察:

地址与数据是否错位
OE/WE跳变时机是否符合预期
数据稳定窗口是否足够宽
也可以编写简单的回环测试程序:STM32向某地址写入特定模式(如0x55AA),然后立即读回验证一致性。一旦发现错误,优先延长 DATAST 而非怀疑FPGA逻辑。

最终你会发现,FSMC+FPGA的组合不仅仅是一种通信手段,更是一种系统级的设计范式。它打破了MCU与逻辑器件之间的壁垒,使得嵌入式系统能够同时拥有灵活的软件架构和强大的硬件加速能力。

对于追求极致性能的产品而言,掌握这项技术意味着你可以从容应对图像、音频、运动控制等高负载场景。即使面对日益复杂的实时需求,也能游刃有余地划分职责边界——让STM32专注于“思考”,让FPGA专注于“执行”。

而这,正是现代嵌入式开发的魅力所在。
————————————————
版权声明:本文为CSDN博主「fun88」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fun88/article/details/154447127

minzisc 发表于 2025-11-14 21:03 | 显示全部楼层
FSMC 配置为 SRAM 模式,使用 8/16/32bit 数据总线
dspmana 发表于 2025-11-15 15:24 | 显示全部楼层
推荐 16 位数据宽度 + 保守时序配置,降低开发难度,后期再根据需求优化速率
saservice 发表于 2025-11-15 16:10 | 显示全部楼层
长走线可能引发亚稳态,建议在FPGA输入端加入两级同步寄存器
macpherson 发表于 2025-11-15 20:24 | 显示全部楼层
据FPGA内部逻辑划分地址区间,例如将低8位用于寄存器访问,高地址用于块RAM缓存
alvpeg 发表于 2025-11-17 08:14 | 显示全部楼层
FSMC的4个BANK可独立配置,避免多设备冲突。例如,BANK1用于FPGA,BANK2用于NAND Flash。
ingramward 发表于 2025-11-17 14:59 | 显示全部楼层
使用复用FSMC功能引脚,包括地址线、数据线、片选、读写信号
cemaj 发表于 2025-11-17 15:28 | 显示全部楼层
STM32 作为主控,FPGA 作为协处理器,FSMC 提供了高速并行通信链路
gygp 发表于 2025-11-17 17:10 | 显示全部楼层
FSMC​ 是 STM32F1xx和部分其他系列提供的一个 静态存储器扩展接口
macpherson 发表于 2025-11-17 17:39 | 显示全部楼层
若出现数据错码、丢包,优先调整 FSMC 时序参数,再检查 FPGA 逻辑是否在控制信号有效期间完成数据锁存 / 输出
mikewalpole 发表于 2025-11-17 18:16 | 显示全部楼层
FPGA 可以非常灵活地模拟一个“静态存储器”接口,与 FSMC 无缝对接
fengm 发表于 2025-11-17 18:37 | 显示全部楼层
FPGA端需实现双向数据总线,读操作时驱动数据线,写操作时释放总线
iyoum 发表于 2025-11-17 20:18 | 显示全部楼层
映射 FPGA 地址空间,实现数据的块读写 / 单字节读写
sdlls 发表于 2025-11-17 22:09 | 显示全部楼层
避免 FSMC 信号与高频信号平行布线,间距 ≥3mm,减少电磁耦合
uiint 发表于 2025-11-18 20:11 | 显示全部楼层
信号完整性是高速通信的基础              
maudlu 发表于 2025-11-18 21:05 | 显示全部楼层
FSMC 提供了地址线、数据线、控制信号等,类似于传统 MCU 访问外部存储的方式
ccook11 发表于 2025-11-19 08:20 | 显示全部楼层
并行总线的串扰和反射是高频通信的主要问题,务必缩短走线、匹配阻抗、优化地平面
wangdezhi 发表于 2025-11-19 11:43 | 显示全部楼层
建议优先参考成熟例程,并通过仿真工具验证时序
ulystronglll 发表于 2025-11-19 13:27 | 显示全部楼层
当多主设备同时访问FSMC时,需在FPGA内实现仲裁逻辑,优先响应高优先级请求
lzbf 发表于 2025-11-19 14:00 | 显示全部楼层
高速、低协议开销、直接内存映射访问、适合大数据量交互
您需要登录后才可以回帖 登录 | 注册

本版积分规则

82

主题

4367

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部