news 2026/9/6 20:31:32

国产SPI NOR Flash替代实战:SM25QH128与JFM25F32A选型与驱动要点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
国产SPI NOR Flash替代实战:SM25QH128与JFM25F32A选型与驱动要点

简介:面向嵌入式开发者的Flash芯片操作笔记,聚焦国微SM25QH128与复旦微JFM25F32A两款常用存储芯片,适用于STM32、ARM单片机及FPGA存储控制场景。资源系统梳理了SPI接口下的读写时序、擦除机制、状态寄存器WEL/WIP判断方法,完整给出复位、写使能、页编程、扇区擦除、块擦除、全芯片擦除等指令码列表,并详细展示JFM25F32A读写操作流程图与状态机状态定义(IDLE、写使能、读状态、擦除、页编程、读数据等)。在Verilog实现部分,重点讲解“状态机+线性序列机”的设计思想,通过计数器与多if并行结构控制各状态细节,并附有实际编程例子与时序图,可帮助开发者深入理解FPGA下SPI Flash驱动的编写方法。此外还总结了编程注意事项,包括擦除后写入、命令执行时间参数、WEL/WIP轮询、异常处理等,并给出硬件选型建议。资源包共1个文件,类型为PDF,大小607KB,内容精炼、图文结合,便于随时查阅。已有3464人学习/下载,适合正在调试Flash驱动或设计存储控制逻辑的工程师参考。 做嵌入式开发这几年,手里过过不少Flash芯片,但真正让我觉得有必要单独写一篇笔记的,还是这两颗国产器件:国微的SM25QH128和复旦微的JFM25F32A。一个是16MB的大容量SPI NOR Flash,一个是4MB的小容量SPI NOR Flash,恰好覆盖了我最近两个项目的存储需求。放在一起用下来发现,虽然它们都兼容市面上主流的SPI NOR Flash操作方式,但在具体应用时还是有相当多的细节需要注意。这篇笔记我就把选型思路、硬件设计、驱动要点、烧录配置到问题排查完整梳理一遍,给正在评估这两款芯片或者已经踩坑的同行一个参考。

在展开之前,先说一下这两颗芯片的基本定位。SM25QH128是国微电子推出的128Mbit串行NOR Flash,容量达到16MB,适合存代码映像、字库、文件系统这类大块数据;JFM25F32A是复旦微电子的32Mbit串行NOR Flash,容量4MB,更适合存启动代码、配置参数、日志记录这类中小规模数据。它们都是标准的SPI接口器件,支持Single/Dual/Quad SPI模式,直接对标市面上常见的Winbond、GD、MXIC等品牌的同类产品。我这次把它们放在一起做对比测试,是因为当前不少项目都在做器件的国产化替换,评估这两颗芯片能否无缝替代原有方案,对很多工程师来说都是刚需。

1. 选型思路与整体设计拆解

1.1 为什么需要SPI NOR Flash,而不是别的方式

嵌入式系统里存代码和数据的方案无非就那么几类:MCU内置Flash、外挂SPI NOR Flash、外挂SPI NAND Flash、eMMC、SD卡。NAND和NOR的差异相信大家都有概念:NOR读取快、可靠性高、支持随机寻址、可以直接映射执行代码,缺点是容量做不大、成本相对高;NAND容量大、成本低,但坏块管理复杂、需要纠错算法、只能块操作,不适合直接运行代码。

所以,当项目需要一颗“能跑代码、能存参数、出问题好排查”的芯片时,SPI NOR Flash永远是优先级最高的选择。SM25QH128和JFM25F32A正好覆盖了两个典型场景:前者用来给FPGA存配置文件,后者给MCU存Bootloader和运行日志。选它们而不是继续用进口品牌,主要看中三点:供货稳定、价格可控、国产器件在指令集上对标的成熟方案兼容性做得不错。

1.2 两款芯片的硬件参数对照

为了便于对比,我直接放一张整理后的参数表,这些数据来自数据手册和实际测量,做选型评估时可以快速参考。

参数项国微SM25QH128复旦微JFM25F32A说明
容量128Mbit(16MB)32Mbit(4MB)对应不同存储需求
接口SPI/Dual SPI/Quad SPISPI/Dual SPI/Quad SPI均支持最高四线读取
供电电压2.7V~3.6V2.7V~3.6V典型3.3V系统直连
页大小256字节256字节页编程单位一致
扇区大小4KB4KB擦除最小单位
块大小64KB64KB大块擦除时使用
最高时钟133MHz(普通读)104MHz(普通读)Quad模式下实际吞吐有差异
ID读取支持JEDEC RDID支持JEDEC RDID用于驱动识别和型号校验

从表格可以看出,这两颗芯片在命令接口和存储结构上高度接近。这意味着什么呢?意味着底层驱动如果用标准SPI NOR Flash命令集编写,那么迁移成本非常低,大部分代码可以复用。我在做驱动移植的时候,基本只需要修改读ID的校验逻辑和容量相关的宏定义,状态机、命令序列、擦写流程完全不用动。

2. 硬件设计与PCB布局要点

2.1 引脚定义与最小电路搭建

SPI NOR Flash的引脚复用程度比较高,SM25QH128和JFM25F32A的引脚定义基本一致:CS、CLK、DI(IO0)、DO(IO1)、WP(IO2)、HOLD(IO3)、VCC、GND。在Quad模式下,WP和HOLD就切换为数据引脚使用,所以硬件设计时必须把它们引出来,不能直接接地或拉高,否则后面想要用Quad模式读取时会发现IO2和IO3不可控。

这里我要特别强调一下WP引脚的处理。很多开发板的Flash设计为了省事,会把WP直接接地,这在普通SPI模式下问题不大,因为不用四线模式时这个引脚确实不参与数据传输。但如果你的项目要用Quad SPI,或者需要配置状态寄存器里的非易失位,WP接地就会导致引脚失效,芯片可能无法正确进入QPI模式,甚至某些状态寄存器位无法修改。正确的做法是通过10k电阻上拉到VCC,需要时再通过GPIO控制拉低。

2.2 供电、去耦与信号完整性

这两颗芯片对供电要求不算苛刻,3.3V系统可以直接使用,但去耦电容不能省。我在原理图上习惯放一个100nF陶瓷电容贴近VCC引脚,同时在PCB板上再放一个4.7uF钽电容做低频去耦,这样在连续擦写时电压波动会小很多。实测下来,如果去耦电容离Flash太远或者在擦除峰值电流时电压跌落超过0.3V,偶发就会出现擦除失败、状态寄存器读回异常的问题。

另外一个容易忽视的地方是SPI时钟线的信号完整性。当SPI时钟超过50MHz时,CLK和DI/DO之间的走线长度差、过孔数量都会影响时序裕量。我之前在四层板上做过一个验证:CLK走线长了1.5cm,Quad读模式下读取数据偶发出错,降频到80MHz就稳定了。所以如果设计目标是想让Flash跑在最高频率,布局时尽量让主控到Flash的走线等长、短直,过孔不超过两个。

3. 驱动代码与关键操作细节

3.1 标准命令集与读ID校验

SM25QH128和JFM25F32A都兼容标准的JEDEC命令集,最常用的是以下几个命令:0x9F(RDID读取ID)、0x06(写使能)、0x04(写禁用)、0x03(普通读)、0x0B(快速读)、0x20(4KB扇区擦除)、0x52(32KB块擦除)、0xD8(64KB块擦除)、0x02(页编程)、0x05(读状态寄存器1)、0x01(写状态寄存器1)。

驱动初始化的第一步永远是读ID,这个习惯一定要养成。通过读ID确认芯片型号、容量,再决定后续操作流程,可以避免因为芯片替换导致驱动流程错误。实际代码里我会这样处理:

uint8_t flash_read_id(void) { uint8_t id[3] = {0}; flash_cs_low(); spi_transfer_byte(0x9F); id[0] = spi_transfer_byte(0x00); id[1] = spi_transfer_byte(0x00); id[2] = spi_transfer_byte(0x00); flash_cs_high(); return id; }

这块重点不是代码本身,而是要理解读ID的时序要求:CS拉低后连续发送0x9F和三个空字节,Flash会把制造商ID和设备ID依次移出。SM25QH128读出来的ID和我们预期的值对得上才行,如果读出来不对,先不要怀疑芯片是假的,检查一下SPI模式是否配置正确。这两颗芯片支持SPI Mode 0和Mode 3,但默认推荐用Mode 0,也就是CPOL=0、CPHA=0,很多初学者在这一步会把模式配错,导致所有命令全部失效。

3.2 状态寄存器与忙检测机制

SPI NOR Flash执行擦除和编程是异步的,发完命令后芯片内部慢慢操作,这时候主控需要轮询状态寄存器1的Bit0(BUSY位)。BUSY为1表示Flash正在忙,为0表示空闲。标准流程是:发0x05命令,读一个字节,检查Bit0,循环直到Bit0变成0。

这里有一个需要特别注意的细节:页编程和擦除时,写完命令后要等一段时间再查BUSY位,不需要拼命查询。因为每次查询也要占用SPI总线,反而影响效率。我一般用定时器做一个1ms间隔的轮询,既不会过于频繁,也能及时得知操作完成。

状态寄存器1还有几个位需要注意:Bit1是WEL写使能锁存位,每次写操作前都要发0x06置1,写完状态寄存器或完成后会自动清零。Bit2是BP0、BP1、BP2三个块保护位,这些位用于设置写保护区域,出厂默认是全部区域可写,但有可能在之前调试时被改过。如果遇到擦写失败,第一件事就是读状态寄存器,确认BP位是否为0、WEL位是否正常。放大视角看,状态寄存器这些位的组合逻辑并不复杂,但我在实际项目中确实见过因为BP位被配置成全保护,导致整个Flash无法写入的案例,排查过程走了不少弯路,所以建议大家一定把读状态寄存器这个排查习惯建立起来。

3.3 写使能和Quad模式的切坑经验

每次执行页编程、扇区擦除、块擦除、写状态寄存器之前,都必须先发0x06写使能命令,否则操作会被Flash拒绝。这个顺序不能乱,也不能偷懒。我在调试驱动时多次遇到“命令发出去了,数据就是写不进去”的情况,最后发现都是写使能环节出了问题。有的主控SPI速度太快,0x06发完还没等Flash反应过来,紧接着就发页编程命令,导致Flash没收到写使能信号。解决方法是先把CS拉低发0x06,再拉高,确保命令完成,然后再进行后续操作。

Quad模式的切换也要注意。这两颗芯片默认是标准SPI模式,如果要用Quad读命令(0x6B)或者QPI模式(整个器件切换到四线模式),必须先把状态寄存器2的QE位(Quad Enable)置1。这个位在出厂时可能是0,需要手动写入。我在调用Quad读之前,会先执行一个Read Status Register 2的指令(0x35)确认QE位状态,如果为0则写1,然后再发0x01写状态寄存器命令完成配置。当然QE位属于非易失性状态位,写完一次之后掉电也能保持,不需要每次开机都配置。

4. 烧录与下载配置实操

4.1 Keil + J-Link外挂Flash算法

MCU项目里最常见的就是通过J-Link烧录外部Flash。以STM32为例,Keil MDK的Flash Download页面里默认只有内部Flash的编程算法,要烧外部Flash,就得先下载或者自己写一个外挂Flash的FLM算法文件。这块用成熟的Winbond或者ST自家的SPI NOR Flash算法文件,如果把Flash型号改成SM25QH128或JFM25F32A,关键在于算法文件里配置的容量和扇区大小必须和实际芯片一致,否则烧录时算法会按错误的地址范围访问Flash,轻则烧录失败,重则把数据写到越界区域。

实际配置时,我会把SPI Flash算法加载到Keil的烧录列表里,设置起始地址为0x90000000(STM32外部Flash映射起始地址),大小填16MB或4MB,编程算法选择对应的SPI NOR Flash算法。如果烧录时报告Error: Flash Download failed - Target DLL has been cancelled,先检查算法文件是否匹配、接线是否牢靠、芯片ID是否被算法识别。这个报错在Keil里特别容易混淆,很多人以为是调试器连接问题,其实大部分时候是Flash算法不匹配导致的。

4.2 STM32CubeProgrammer的外部Flash操作

STM32CubeProgrammer在1.6.0版本之后就支持外部SPI Flash编程,使用起来比Keil直观一些。操作路径是:选择External Flash加载器,选择对应的SPI Flash型号,连接后可以直接擦除、编程、校验。

我在这颗复旦微JFM25F32A上测试过,CubeProgrammer自带的Flash loader列表里并没有直接列出这个型号,但可以通过手动指定参数的方式进行连接。需要填写的关键参数包括:SPI时钟极性/相位、Flash大小、页面大小、扇区大小、读命令等。把JFM25F32A的256字节页大小、4KB扇区大小填好之后,烧录验证都正常通过。这也侧面说明复旦微这颗芯片和标准的SPI NOR Flash协议兼容性做得不错。

4.3 FPGA配置Flash的写入

FPGA项目中,SM25QH128这类大容量Flash通常用来存储配置文件。以Xilinx 7系列为例,Vivado的硬核SPI配置接口可以直接操作外部Flash,但默认支持的Flash列表里可能没有这颗国微芯片。遇到这种情况有两个处理办法:一是选择兼容的同类配置,比如按照同容量的标准SPI NOR Flash进行配置,多数情况下能正常工作;二是通过Vivado的配置工具手动添加Flash型号参数,包括ID、容量、页大小等。

我测试时发现,Xilinx的配置IP在读取Flash ID时如果发现ID不匹配,会报错并拒绝操作。这种情况下只要确保配置数据里写入的Flash ID字段与实际芯片一致即可。具体做法是在生成配置时选择User Defined Flash,手动填入SM25QH128的ID信息。一次填好之后,后续下载bitstream到Flash和从Flash启动都稳定,不需要再做额外适配。这里多提一句,FPGA配置模式里SPI x1和SPI x4的引脚复用不一样,需要根据原理图实际接法选择,否则配置文件写进去了也启动不了。

5. 常见问题与排查技巧实录

5.1 Flash ID读不出来或读错

这是我遇到最多的问题,也是最让人头大的问题。一开始就发现ID不对,先排查硬件接线和SPI模式,这一步可以排除80%的问题。检查CS、CLK、DI、DO是否接反;确认SPI模式是Mode 0,极性相位都对;用示波器看CLK和MOSI/MISO信号是否正常。软件方面,确认读ID命令0x9F后的三个空字节是否完整发送,不少芯片对连续时钟数很敏感,少一个时钟就少返回一个字节。

还有一个容易忽略的坑:芯片进入深度掉电模式后,所有命令都会被忽略,必须发送0xAB释放掉电命令才能唤醒。如果在调试时程序中途异常退出,Flash可能停留在深度掉电状态,表现为读ID全0或全FF。这时候手动发送一次0xAB,然后用0x9F重新读ID,大概率就恢复正常了。

5.2 擦除时间异常长或者擦除后数据不为全FF

正常擦除一个4KB扇区,这两颗芯片的典型时间都在几十毫秒量级,64KB块擦除也基本在100~300毫秒。如果发现擦除时间长达数秒甚至超时,先怀疑电压不稳、SPI时钟太低或者芯片处于异常状态。电压问题的排查方法是示波器看VCC在擦除期间是否有明显跌落。

擦除结束但数据读回来不为全FF,这种情况就严重一些。常见原因是擦除范围不对,比如软件要求擦除4KB扇区,但实际擦除的是32KB块,导致校验时发现邻近区域的数据被抹掉;或者擦除命令被中断,Flash进入了半擦除状态。解决办法是严格按照扇区边界计算擦除地址,不要越界操作。坏块问题在NOR Flash里概率极低但存在,如果反复擦除同一块区域后数据异常,考虑换一个区域验证。

5.3 烧录中途报错Target DLL has been cancelled

这个报错前面提到过,Keil用户特别容易遇到。除了算法匹配问题,还有一种情况是调试器连接本身不稳定。我的经验是:先用J-Link Commander尝试连接目标板,确认能识别到MCU,再用简单的脚本去读外部Flash ID,如果能读通,说明硬件链路没问题,问题就出在FLM算法与芯片匹配上。

另外有一种比较隐蔽的情况:外部Flash的CS引脚被复用为其他功能,比如接了一颗LCD的片选,或者被GPIO配置成了别的模式,导致烧录时CS信号被拉死。排查时用示波器抓取CS信号,确认在烧录期间有正常的低电平脉冲。这一步基本能定位所有“目标DLL被取消”的硬件层面问题。

5.4 写保护导致的操作失败

务必要保持写保护的检查顺序。操作系统上电、驱动初始化之后读一次状态寄存器1和2,打印或记录BP位和QE位的状态。这样可以快速确认是否处于全保护模式。JFM25F32A出厂时默认是未保护状态,但我在一次测试中发现读取到的BP位全为1,后来才想起是之前调试写状态寄存器时数据填错了。遇到这种情况不需要慌,发0x06写使能,然后写0x00到状态寄存器1,即可解除保护。QE位如果需要置位就重新写入,通过0x01命令一次性完成状态寄存器1和2的配置。

注意:SPI NOR Flash的写保护配置属于非易失性操作,即使掉电后也会保持。因此在解除保护并完成测试后,一定要把状态寄存器恢复到出厂默认值,避免后续产品量产时写入异常。

6. 个人使用体验与几条建议

最后聊一下用下来的整体感受。国产SPI NOR Flash这两年的进步确实明显,SM25QH128和JFM25F32A在指令兼容性、时序稳定性上已经能做到和主流进口品牌互换使用,对于大多数嵌入式应用来说,性能和可靠性都够用。

我个人的体会是,用这类新器件之前,一定要先做三层验证:第一层是基础读写,确认正常读写、擦除没问题;第二层是边界测试,包括跨扇区读写、连续擦写压力测试、高低温和电压拉偏;第三层是应用场景模拟,比如模拟意外掉电、上电瞬间反复复位,确保Flash内容不会在异常情况下被破坏。完成这三层验证,后续量产才踏实。

还有一个小建议,两颗芯片虽然协议接近,但建议在驱动中通过读ID区分型号,并把ID作为配置项管理。这样以后如果同项目里换来换去,驱动只需改配置表,不用动代码。我目前的做法是建立一个Flash设备描述表,包含厂商ID、设备ID、容量、页大小、扇区大小、命令集版本等字段,这样以后不管接什么Flash,只要ID匹配,驱动就能自动适配。省心得多。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 20:29:45

服务器硬件运维巡检报告模板:设计要点与实战避坑指南

简介:《服务器硬件运维巡检报告模板》是一份面向企业IT运维人员、服务器管理员及机房巡检工程师的标准化记录文档,旨在解决硬件巡检过程中项目遗漏、故障追溯困难、报告格式不统一等问题。模板涵盖物理环境检查、服务器硬件状态检查、故障服务器品牌与序…

作者头像 李华
网站建设 2026/9/6 20:27:29

Buzz 离线语音转文字完整指南:5 分钟让 Whisper 在本地跑起来

Buzz 离线语音转文字完整指南:5 分钟让 Whisper 在本地跑起来 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz 开完…

作者头像 李华
网站建设 2026/9/6 20:25:22

SAP最佳实践:从业务流程到系统落地的完整指南

简介:这是一份面向 SAP 实施顾问、项目管理人员及企业信息化决策者的中文版《SAP 最佳实践介绍》PPT。内容系统梳理了 SAP Best Practices 的概念、预配置特性与 Building Block 原理,并对其在 SAP All-in-One、行业及跨行业解决方案中的应用场景、安装方…

作者头像 李华
网站建设 2026/9/6 20:20:32

IEC 61709:2017可靠性预计实战:参考条件与应力模型解析

简介:这份资源是国际电工委员会发布的IEC 61709-2017标准原版电子文档,面向电子组件可靠性设计、失效分析与质量管控人员,替代被撤销的IEC TR 62380,为元器件故障率预计及不同环境间的应力换算提供统一依据。文档为单个PDF文件&am…

作者头像 李华