你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】利用 QuadSPI 外扩串行 NOR Flash 的实现

[复制链接]
STMCU小助手 发布时间:2022-2-22 18:48
前言+ R- e  e3 k% N2 B; A
STM32 提供了灵活多样的外扩存储器访问实现。本文中,介绍如何利用 QSPI (QuadSPI) 外扩串行NOR Flash 存储器。首先对 QSPI 接口功能特性进行介绍,然后分别介绍硬件设计和软件开发。并基于 STM32CubeMX,提供访问 MICRON N25Q128A13EF840F 的实现参考。
- a/ P  G% x0 t* W4 ^& b' `) J/ D* t$ ~5 S. R7 p
一 实现环境
5 t! f+ a- J. ^! u# g2 G+ q开发板:STM32F469G-DISCO
' I. o! _4 e7 F3 R0 `) G开发库:STM32CubeF4 v1.16.02 V8 e) p0 o1 o
STM32CubeMX: v4.22.0; o1 T& d! F9 ^, E/ r, B
集成开发环境:IAR v7.70.1.11486' Q: K9 S' [& W. j) Q

: }: Y7 ~1 ~/ \4 i% A4 G2 O2 c" _3 n实现过程在 STM32F469I-DISCO 板上展开,利用板上已有的串行 NOR Flash 存储器(MICRONN25Q128A13EF840F)。呈现整个开发涉及环节。在本文中,首先根据 QSPI 接口,介绍 QSPI 与外扩串行存储器硬件连接。另外,Cube 软件包中包含 QSPI 实现例,在本文对库中实现的 QSPI 例不做讨论,读者也可参考这些 QSPI 例进行设计。本文围绕由 STM32CubeMX 生成的工程,介绍如何实现对外扩串行 NOR Flash 存储器的访问。6 b  i5 M7 Z9 Q# n5 H7 y
/ |- S" S* {. C& Q6 Y
0 J1 a9 a, M, d/ Q8 R: K
二 QSPI 介绍
/ J+ ^8 D2 u: i" a' ]在呈现 QSPI 访问外扩 Flash 的实现例前, 需要对 QSPI 有一定的了解,在此对 QSPI 进行简短的介绍。更多内容请参考AN4760。
. H: H* h1 p' m6 t
& [% D% V5 k+ y' _& q- f2 G6 o) ?5 C5 B. x; k: d0 k& G
QSPI(Quad-SPI)支持四线串行访问形式。同时,QSPI 支持传统 SPI 和 Dual-SPI 模式,Dual-SPI 模式支持两线串行访问。与 FMC/FSMC 比较,QSPI 支持更低成本、更小封装外部串行 Flash 存储器,更少的 IO 引脚占用,有效减少 PCB 面积,降低 PCB 设计复杂度。* x) @* r5 \3 f5 @# C: N- a
QSPI 在不同系列 STM32 产品线的支持情况(仅部分罗列,未涵盖所有支持型号)。
" V. w* d: q$ ^3 p0 K$ R5 d8 N
8 U4 h, Z, g& y. e7 l( J2 [ {ZD9YHG}M$K_WY{}P38O6.png
8 {+ W6 e  j1 o6 l" f0 I; Z0 `0 h9 i- e7 Y( f8 ], n; W7 G. G7 w% K8 W
QSPI 接口提供了灵活可配置的 5 个阶段,如下图所示(仅用于理解阶段构成,时序图根据配置不同存在差异)。分别是命令阶段、地址阶段、复用字节阶段、Dummy 阶段和数据阶段。可以根据外扩 Flash 中命令时序对不同阶段进行配置。后续会以实例进行呈现。更多内容请参考 AN4760。
2 f+ L5 Y( V% L$ n; Q" Z2 d3 D
" b7 z4 [, T) ] G(43Z~J%M3`)LTRK~Y2U@[X.png
1 [. C3 n1 X6 P& P. j/ S* w. I. t1 X# O1 x! V8 U' Y7 n* ^. U, x
QSPI 支持三种模式,分别是:; z( J8 g& e( Y5 r: d
间接模式  所有操作通过 QSPI 寄存器实现,类似于传统 SPI,可以使用阻塞模式、中断模式或者 DMA 模式进行读写等访问。本文中提供的实现例为间接模式下的实现。2 ~! }  z* d3 v+ N1 }7 M
状态轮询模式  接口自动轮询指定寄存器,直到回读寄存器内容与指定条件匹配。可应用于状态检测,从而实现忙等待等效果。本文不对此模式进行实现介绍,应用实现可参考 Cube 软件包中 QSPI 例程。
) i6 V# Q- f& a0 c3 ?存储器映射模式  外扩 Flash 被视为内部存储器,支持 AHB 主器件直接访问,CPU 能够直接运行位于 QSPI 存储器的执行代码。内部系统架构如下图所示(以 STM32F469/F479 为例)。本文不对此模式进行实现介绍,应用实现可参考 Cube软件包中 QSPI 例程 QSPI_ExecuteInPlace。
1 d5 M4 @/ I/ L3 T& E/ b' u$ ]. T: j, a2 ~! F2 @
@2GQ%0WHO]3V789F0GKH{BH.png
' Z6 c+ Q; D. C6 `8 w1 g
. _& g8 S  k: Z1 @0 ]. Y8 ^# [2 ~- z5 o& L  V6 C" Q, a/ S3 M6 l7 E' D: o
三 QSPI 外扩串行 Flash 实现例  n' ]+ L. o8 ?$ F- B" ]9 j' K. |6 O/ Q* s
3.1 串行 Flash 介绍' F0 b5 A2 z- m: q# r+ d: H* h
以 MICRON N25Q128A13EF840F 为例,更多细节请参考存储器手册。N25Q128A13EF840F 引脚图、时序图和电气参数来源于 N25Q128A13 手册文档。
4 c2 A. j! R# V% i支持协议: SPI, Dual I/O(对应 Dual-SPI), Quad I/O(对应 Quad-SPI)4 y$ Q: D/ M; D5 N2 C7 M! o5 v
支持访问模式: 单线访问、双线访问、四线访问,得益于 QSPI 接口的灵活可配性,三种访问模式全部支持。
2 z- a# w% p- e4 y$ p9 X; E供电电压范围: 2.7 ~ 3.6V( ]" M* y2 i) d) s  ~
最大时钟频率: 108MHz
1 P  H- \4 N* P* T存储空间: 128Mb (16MB)/ u; D. X* v- L0 ^. g( `, y$ B% \
器件引脚示意图如下所示。由两根电源引脚和六根 QSPI 信号线构成。. p1 e, u3 V0 I" Y- _

0 O0 T& ?+ A# j  D3 C ZMJB2(7FWD5OZ0`4[0J~J[N.png * Y3 o# b- n. O. |2 }/ y- p

7 D3 G" Q* D5 a# F1 L. H下表为存储器 N25Q128A13xxx 命令(未列出全部命令)。通过下表可知,存储器提供了灵活的访问实现形式,而结合同样灵活可配的 QSPI 接口,能够实现存储器命令全支持。而本文仅为提供设计思路,呈现了部分命令在 QSPI 上的实现。% p% B6 a8 U# R' o2 f" a8 I
' V) N6 ]6 z% f* p# u+ P; q6 }( B, S
P~~V0$N(6V_$_G3A6XAJ(7K.png % R1 b% e* i% |( I9 p6 u

( Z# w' K) U7 a2 Q其中,默认读写默认 3 字节地址,四线快速读命令默认 Dummy 周期数为 8。  o3 G. \4 h2 T
6 \1 O- K- n. B8 R1 ^
3.2 硬件设计3 P, V7 ?' ]6 \  |) h0 j$ w
涉及到的信号线少,硬件设计简单,只需直接将 QSPI 的六根信号线与存储器连接即可。考虑到可测性,可以增加串行电阻或者测试点。硬件电路图如下所示。8 Z$ Q& d+ H% n  Z

4 ~0 c5 ~$ \- n: o Q{OUTZO[02XZ{L7_@%F)7O5.png 1 K+ w- u6 R9 p2 I, u8 O
& v5 e# x4 J) Q' w) u- N8 [
QSPI 接口 PCB 设计遵循如下几点,更多硬件设计内容请参考 AN4488。  _5 x9 |# f/ v+ W
a. 线阻 50Ω ±10%
9 }( b& A( P5 k% nb. 最大线长 < 120mmc. 避免在不同信号层走信号线
$ e! i) V; N: d6 A9 `d. 时钟线至少离其他信号线 3 倍线宽距离5 ?4 s. E2 v/ R' D) c
e. 数据信号线长差 ≤ 10mm
, w  X2 D7 x- r( v! pf. 避免时钟线采用蛇形走线,同时尽量减少数据线上过孔。$ B7 E% q$ \/ W7 X1 q! A

% }0 y& i+ T# L" ~  k
. h8 Z, Q( g0 ]# ^% v$ i3.3 软件开发流程5 K  C6 a6 q# J3 a. x, L
1 [+ l" v1 C3 k( a
Q6H]N_YL1]8O)6`AQWOC$H8.png
6 F$ ~8 t+ l6 C4 y' _" B9 s8 C8 e
/ q1 {$ h2 P) C/ u) d; y% {3.4 软件实现例# x+ j$ h# W2 X1 d
在环境搭建完成后,就可以利用 STM32CubeMX 根据硬件连接情况,进行 QSPI 配置,获取 IAR 工程。具体软件实现流
, A8 M5 ?, R8 l$ a+ W程如下。  t- X% A# k. P8 U: Y: [. L6 I  c
3 K. k. i$ \9 U  G- W$ y- }
# j/ g$ F; s# v' Q. Z0 k
~LQVQPWMRM80Y]~5FDOGOQ1.png 1 D* h. g6 e' g$ R& }
/ R& X0 X9 O! @7 X% D3 ~& o7 f
5 L, {& }6 }( w- A
a. 利用 STM32CubeMX 生成 IAR 工程
/ `4 d5 q& ^  z- ?& Z1 B3 f打开 STM32CubeMX - 点击”New project” - 在”Part Number Search’中输入 STM32F469NI - 点击”MCUs Liast”中出现的 STM32F469NIHx - 点击“Start Project” - 此时,基于 STM32F469NIHx 的 STM32CubeMX 工程被打开。如下,根据 STM32F469I-DISCO 板硬件连接情况(QSPI NCS, CLK, Q0, Q1, Q2, Q3 对应 PB6, PF10, PF8, PF9,PF7, PF6;外部高速晶振为 8MHz 无源晶振;调试接口采用 SWD 接口,其中 SWCLK, SWDIO 对应 PA14, PA13):选择” QuadSPI”为”Bank1 with Quad SPI Lines”(注:也可在开发过程中,先用 STM32CubeMX 查看 QSPI 接口对应的 IO 引脚,进行硬件开发) 。) d, C/ N7 t$ K. {& a6 Q- h$ w
注: 在如上选择后,右侧引脚图中 QSPI 对应的引脚会呈现绿色显示。需要根据电路图中所连接的 QSPI 引脚,进行复用引脚确认。例如,在默认情况下,QSPI IO0 对应到 PC9 引脚,而 STM32F469I-DISCO 板上的 QSPI IO0 与PF8 连接,并非 PC9。所以,需要在右侧引脚图中,按住 Ctrl 键,左键在 PC9 引脚按下,拖动至 PF8 处,松开左键和 Ctrl 键,实现 IO0 引脚的关联。6 V, d% ?+ ]0 }
选择“High Speed Clock(HSE)”为“Crystal/Ceramic Resonator”。
+ g5 `) o3 \4 N# S选择”Debug”为”Serial Wire”
1 f6 J/ R$ [4 v. L& D# c+ W" ]3 @% T* e* W7 u9 ^

7 B  i* s2 S+ ?# K; C% N6 b2 A, @ C23EP4AS9T7W`[OA%5S18`Q.png - p& i' s& r- o3 R; P

0 o+ v) c3 z! V6 X, h时钟配置如下图所示。设置输入时钟频率为 8MHz - 选择”HSE”做为 PLL 倍频时钟源 - 选择”PLLCLK”做为主频时钟源 - 设置 “HCLK”为 180MHz (FAHB 为 180MHz)- 点击 Enter 键,自动生成对应主频的时钟参数(仅提供时钟配置参考,并不限制一定要设置 180MHz 主频)。0 e* C7 n) [; g& Q% `
( I" I/ r" _/ ~% Q3 `; {# Y9 Y
6 N- o  S# A; Y* E9 V8 W* ~
%9`PUO)YAL~PXHD(E4H4_TB.png ) `+ c+ y# [" O5 `" N. I; y9 a

$ i% |. I# M( V) H6 `; @- J; QQSPI 配置如下图。参数的配置需要与存储器参数匹配。- F* \& F' P2 {1 O' M
• FIFO Threshold(FIFO 阈值) 配置为 4,并不严格要求。  w6 g- s/ H* {# O: H1 V6 H, w
• Smaple shift 选择“Sample shifting half cycle”。延后半个时钟,获取数据线上数据。可以使用在由于线路设计,数
! v' }$ \& }2 G* o5 \/ w7 M8 [4 P$ W据信号存在较大延迟的场景。
# |$ ?( w: [! Y( `6 Y( X7 O5 ~! T( H% |

- c  q) h2 R4 y9 k) N' n RQHJOG_`HZJN1HZD@)57FFX.png . Z  W1 Z2 |; ~7 p' g/ U$ c5 t
+ c4 Q( ~" _7 O$ A& n0 i, {# z5 c
使能 QSPI 中断。# P2 `( J9 P& l) @
- V. L+ Q8 l- M- a" D# g( r: k5 x
MY%W~@29U]WE69[]U4MJ~7Y.png
- Y' f, T4 v4 k) Z' I  o* \* h, }9 q0 r5 y! D$ g+ V, j4 J
点击菜单栏”Project” - “Settings” - 设置”Project Name” , “Project Location” 和 “Toolchain / IDE” 。其中“Toolchain/ IDE”设置为 EWARM 以便生成对应 IDE 的工程。其他选项保持默认。5 t6 K9 {, J/ F& O5 g: y& Y4 Z
点击菜单栏”Project”  “Generate Code”  等待 IAR 工程生成,出现”Code Generation”界面 - 点击”Open Project”打开工程。- V9 u0 ]- {9 n8 h
9 h! u" f4 @# K3 _( p$ o7 F! V- j
b. 完善工程。5 m- v4 A2 l1 O
由上述步骤获得的 IAR 工程中,包含了时钟配置及 QSPI 接口的初始化。对于外扩 Flash 的操作,还需要 添加外扩Flash 支持的命令进行操作。N25Q128A13EF840F 支持的部分命令可参见本文 3.1 小结。
; k  {8 G! P& N: G" o8 e: q5 e在这里出于简化考虑,仅提供了阻塞式读取 ID,擦除 Flash,块写和快读操作的实现。更多实现模式,可以参考Cube 软件包中提供的 QSPI 例程。% d) g# B! a+ p8 W
在 N25Q128A13EF840F 手册中提供了读 ID 命令时序,如下图所示。& P; r4 b; E+ J/ ~4 j5 }' P
6 v" N# T$ z3 @
PV{B8I~5GR7NA2~US_OS2T3.png
3 x; f9 c5 W0 Q, I
9 g  i, T5 k, U3 k' M" g5 g% @5 s0 k由时序图可知,读 ID 时序构成: 命令阶段 + 数据阶段。命令阶段和数据阶段线宽都为 1,读 ID 命令码为 0x9E 或者0x9F,ID 数据长度为 17 字节。% R/ U' ?; ]% |4 Y1 ^& T& [
在 N25Q128A13EF840F 手册中提供了写使能命令时序,如下图所示。
( ~& X1 [' I! m, \- U# d; l1 _
" t. s3 w" L) q0 a7 y- Z5 {7 }3 O
GCO@4Y}W4V@@XJW4S3CH_3Q.png
! z) P+ B0 B4 _# P& i: r; V$ L7 J7 a+ S; z" Z4 a
由时序图可知,块擦除时序仅有命令阶段。命令阶段线宽为 1,写使能命令码为 0x06。(注:这里仅呈现了单线命令模式的实现。除此之外,STM32 QSPI 接口和外扩存储器支持双线、四线模式)。1 r* q: B9 n  H8 S
在 N25Q128A13EF840F 手册中提供了扇区擦除命令时序,如下图所示。# j5 ]5 k8 ?" N
# o3 E. T4 G+ G" O0 _6 D
7Y(S}25F84FHD[Y@OV58]ID.png
6 M& X' U# M9 Z* G! y& W" L, ~4 C3 v# a8 k
由时序图可知,扇区擦除时序构成:命令阶段+地址阶段。命令阶段和地址阶段线宽为 1,扇区擦除命令码为 0xD8。其中地址为 24-bit,任一位于需要进行擦除操作的扇区范围内地址都有效。在此简单选择扇区 0 进行擦除,选择地址为 0。(注:这里仅呈现了单线命令模式的实现。除此之外,STM32 QSPI 接口和外扩存储器支持双线、四线模式)。在 N25Q128A13EF840F 手册中提供了四线快速写命令时序,如下图所示。
( a) V& j2 ~2 Q
' P9 W) n6 Q& y# r+ L PJL4TD`8P)2AEWOOG04QLI2.png 0 E- r& m; q% X5 T( D! `( l, L1 }
% b: e: W2 n8 f& U& @( @
由时序图可知,四线快速写命令时序构成:命令阶段+地址阶段+数据阶段。命令阶段和地址阶段线宽为 1,数据阶段线宽为 4,四线快速写命令码为 0x32。其中地址为 24-bit,对应写入起始地址。(注:这里仅呈现了单线命令模式的实现。除此之外,STM32 QSPI 接口和外扩存储器支持双线、四线模式)。
0 X9 l; X5 i* H* P1 b# U在 N25Q128A13EF840F 手册中提供了四线快速读命令时序,如下图所示。# k  \6 |  c0 U, }) n4 J( x" t, w
8 |) z0 ]6 D9 l" J) X4 |& v
K4~X}UFP]K)_{D~PF$KU{BS.png ' Q2 c' E9 B& u" ]
: _1 H) i. r' n  m8 w
由时序图可知,四线快速读命令时序构成:命令阶段+地址阶段+数据阶段。命令阶段和地址阶段线宽为 1,数据阶段线宽为 4,四线快速读命令码为 0x6B。其中地址为 24-bit,对应写入起始地址。四线快速读命令默认 Dummycycles 为 8。(注:这里仅呈现了单线命令模式的实现。除此之外,STM32 QSPI 接口和外扩存储器支持双线、四线模式)。: ^; w& }0 m5 @: f/ ^
在 main.c \ main 函数中,增加代码如下。
2 q8 z3 P( {' [4 j$ P5 l$ G- A
  1. … //系统、时钟、IO 和 QSPI 初始化
    4 {- ]& j/ t  q
  2. /* USER CODE BEGIN 2 */& H4 Z$ r9 ?9 s& V' X
  3. QSPI_CommandTypeDef sCommand;
    - D/ t3 q7 Z& ?$ y
  4. static uint8_t Buf_ID[17] = {0};. |1 {2 g* u  U+ U7 Z5 v7 o8 i/ A( a
  5. static uint8_t TxBuf[0x10] = "Ext Flash", RxBuf[0x10] = {0};' m: a! C2 h' p5 u- z7 l5 b+ Y
  6. 5 q8 h. a4 W. C# d: S
  7. sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; //DDR 模式失能, V. d' n4 s9 b
  8. sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; //DDR 模式下,数据延迟输出
    5 f# ], n0 Y4 C! \6 i$ F, T5 ]
  9. sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; //每次发送都包含命令阶段8 I+ \6 P. M, M! A
  10. /***** 读 ID 操作 *****/
    " U3 J- e( _9 F3 n
  11. sCommand.Instruction = 0x9F; //READ ID 命令码
    3 s, ?2 q6 \  s. U5 q
  12. sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; //命令线宽+ _0 r% M3 C  K+ K4 W
  13. sCommand.AddressMode = QSPI_ADDRESS_NONE; //地址线宽。无地址阶段
    * Q+ k4 R9 W  y. V8 [1 h* G
  14. sCommand.DataMode = QSPI_DATA_1_LINE; //数据线宽' g  K3 A( s0 l/ c
  15. sCommand.NbData = 17; //读取数据长度。ID 长度为 17 字节7 M% H1 z1 g( g& X7 S( ?8 q- z
  16. sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无复用字节阶段
    , i: {2 i9 _$ D2 a$ l7 J
  17. sCommand.DummyCycles = 0; //无 Dummy 阶段, i8 Z5 z# P) E% y- F* L) E+ _: i
  18. //配置命令(在有数据阶段时,命令在后续发送/接收 API 调用时发送)
    0 p: y- y# T) ~; w' I
  19. if (HAL_QSPI_Command(&hqspi, &sCommand, 5000) != HAL_OK)$ o* {, u0 \8 H0 T: j
  20. {
    9 v! j, f4 f9 K" `; D$ D
  21. Error_Handler();
    + N; O# y1 a2 |) Q/ u# u
  22. }
    0 o, A. R! D/ T- |5 \( ]* g% _  B
  23. //执行 QSPI 接收/ [" F- m, |# a4 u* n9 U# m
  24. if (HAL_QSPI_Receive(&hqspi, Buf_ID,5000) != HAL_OK)% `0 w7 b0 e9 X+ D
  25. {- y' e: ]6 @- Z+ L* f
  26. Error_Handler();4 {# x6 M( t) ^, x4 T: i4 F: @
  27. }
    & A. Z" ^" T; V" k- c/ e
  28. HAL_Delay(1); //延时 1ms. 单位为 SysTick 定时中断周期- a6 W$ }" v5 u' I- R3 u3 H) e9 \
  29. + u  a1 K  P4 B6 w9 E
  30. /***** 写使能操作(需要在块擦除之前,使外扩存储器处于写使能状态) *****/, B  M) P0 A: ~$ J6 U4 c$ F
  31. sCommand.Instruction = 0x06; //写使能 命令码. b4 {- x, c" R0 b9 i  G
  32. sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; //命令线宽
    / ~2 O! L; g. _% M8 f/ d, }
  33. sCommand.AddressMode = QSPI_ADDRESS_NONE; //地址线宽。无地址阶段2 N! R1 [5 @- B3 O$ O1 J& D1 X# e
  34. sCommand.DataMode = QSPI_DATA_NONE; //数据线宽。无数据阶段$ z- j! C5 `; t" _' W; H9 l  C3 S! Y
  35. sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无复用字节阶段  k+ e- u" Y: Y0 ^' c0 @( C/ E
  36. sCommand.DummyCycles = 0; //无 Dummy 阶段
    % y, ~7 T3 Q' _- `+ y
  37. //配置发送命令
    ) Y4 b6 \7 P  u, `  u. A- W6 M2 Y  W
  38. if (HAL_QSPI_Command(&hqspi, &sCommand, 5000) != HAL_OK), X' D' G+ l# d) m3 O  |; b& ~
  39. {
    ' L$ _4 w1 D# J# P5 ~
  40. Error_Handler();: O, A8 e" a7 h6 v3 Q. P; F* N  s+ i
  41. }5 F2 K2 C  k/ `& M( L2 @
  42. 3 O) _: W- j5 z4 H' E: \
  43. /***** 块擦除操作 *****/1 q8 N8 T7 D$ d5 U* ^% y
  44. sCommand.Instruction = 0xD8; //扇区擦除 命令码
    - q4 }$ u0 ^4 ?" g2 L% w9 b' a) U
  45. sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; //命令线宽1 u+ L4 d  O/ n; [
  46. sCommand.AddressMode = QSPI_ADDRESS_1_LINE; //地址线宽。无地址阶段
    , S  K2 ]2 l: W+ Z( t% P, [
  47. sCommand.AddressSize = QSPI_ADDRESS_24_BITS; //地址长度
    $ @# l+ m, x* ?6 \# g% ]# C
  48. sCommand.Address = 0; //位于所需擦除扇区内的任一地址。
    , X! y% F' ]; s# l3 b. A" V2 k
  49. sCommand.DataMode = QSPI_DATA_NONE; //数据线宽。无数据阶段& D+ I1 _; R' F: @% b1 n: h8 Z- r
  50. sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无复用字节阶段
    5 S* X6 R3 I4 g* [5 w5 Q
  51. sCommand.DummyCycles = 0; //无 Dummy 阶段
    . c' q4 @/ M3 U3 Y  r# K: m
  52. //配置发送命令' M. n) K$ y  U6 T+ C' A
  53. if (HAL_QSPI_Command(&hqspi, &sCommand, 5000) != HAL_OK)/ m" e& P7 b: D! ^1 r- X$ F) _0 v0 W3 @
  54. {
    $ ^0 e- Y  f1 c; B% n! m: p/ z& W" T1 I
  55. Error_Handler();
    / H1 K. v* b1 c2 h4 B6 u. q
  56. }9 L. Y/ ^' w' x1 A" w& Y, q  |
  57. HAL_Delay(3000); //延时 3s. 单位为 SysTick 定时中断周期
      u# K. c, w% [8 |! y( F

  58. 5 [  k% p2 i7 h$ e$ B9 N( a3 W
  59. /***** 写使能操作(需要在块擦除之前,使外扩存储器处于写使能状态) *****/) H$ n) m1 x6 t4 B4 b9 I1 f$ V
  60. sCommand.Instruction = 0x06; //写使能 命令码  r7 {( ~8 W; E: Z  T1 s) T: u' r
  61. sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; //命令线宽
    6 l, h+ s6 m! F! G" _& j
  62. sCommand.AddressMode = QSPI_ADDRESS_NONE; //地址线宽。无地址阶段" h- u( m6 ^& v' e6 z4 D. ?3 `2 l7 j
  63. sCommand.DataMode = QSPI_DATA_NONE; //数据线宽。无数据阶段' Q) k8 U" G1 A9 {
  64. sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无复用字节阶段
    : N6 u. a% F3 {" \
  65. sCommand.DummyCycles = 0; //无 Dummy 阶段
    & }& \6 y' ^1 A
  66. //配置发送命令2 f- N  O$ i" x2 C( f
  67. if (HAL_QSPI_Command(&hqspi, &sCommand, 5000) != HAL_OK)+ }! h7 e4 s# f- N
  68. {
    - l- j+ u: _$ R5 F& l
  69. Error_Handler();
    * Z: W1 G. @1 V6 Q; {- `2 l  A: Y% h+ P
  70. }. A) j; L. _4 \8 f+ w) e2 w8 y" P
  71. $ t, a0 ]; O; Q7 F- m- b5 N8 K
  72. /***** 四线快速写操作 *****/
    3 i5 S$ g/ N) y* {
  73. sCommand.Instruction = 0x32; //四线快速写 命令码
    " W, N4 r- W9 M% o5 E" D1 K
  74. sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; //命令线宽
    : _/ y0 g8 b1 ~) V
  75. sCommand.AddressMode = QSPI_ADDRESS_1_LINE; //地址线宽5 r5 Z0 K& }. ]  e3 S- B3 p& C4 ~
  76. sCommand.AddressSize = QSPI_ADDRESS_24_BITS; //地址长度: p3 T" i; q& u, v& I, m
  77. sCommand.Address = 0; //写入起始地址, W' p4 m% p- c+ K7 B& q
  78. sCommand.DataMode = QSPI_DATA_4_LINES; //数据线宽
    # y" M, T! \" ^. I
  79. sCommand.NbData = 10; //写入数据长度0 s1 q4 u0 i( F* f6 F' F2 x; c- u
  80. sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无复用字节阶段
    , q* V  v3 A9 t% \. B. V% B
  81. sCommand.DummyCycles = 0; //无 Dummy 阶段# _2 g. F- ~' B! }& `/ m" V! t+ A
  82. //配置命令(在有数据阶段时,命令在后续发送/接收 API 调用时发送)
    0 S/ o& e; y: l$ U2 ^. b( e
  83. if (HAL_QSPI_Command(&hqspi, &sCommand, 5000) != HAL_OK)
    $ q/ M" q" H$ s1 A& }, }
  84. {; a$ a. Y$ U. S
  85. Error_Handler();
    & U- m! k  c) T' f3 C
  86. }# r4 y/ D" k% [* F2 c* E
  87. //执行 QSPI 接收
    - l) h( S* h7 J
  88. if (HAL_QSPI_Transmit(&hqspi, TxBuf ,5000) != HAL_OK)
    ' j% G- I: O! \! P% E( @5 d/ {  g1 p
  89. {/ U$ o* x4 w$ x* _: `* m- ?, I
  90. Error_Handler();
    2 n" ^. F& c& ~) P
  91. }
    ! B: C  K  ~; K4 r. T; ^" j- J$ a
  92. HAL_Delay(5); //延时 5ms. 单位为 SysTick 定时中断周期
    # N! o9 h' r% s8 b
  93. 7 V! i/ S: D1 `! J
  94. /***** 四线快速读操作 *****/
    7 k0 u6 k' i+ X) Q% J( t5 M
  95. sCommand.Instruction = 0x6B; //四线快速读 命令码( }! r. e. n+ U& K
  96. sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; //命令线宽4 ?  K6 K' r0 @& K: X% z$ Y
  97. sCommand.AddressMode = QSPI_ADDRESS_1_LINE; //地址线宽
    3 d% J- Z/ e) i! J
  98. sCommand.AddressSize = QSPI_ADDRESS_24_BITS; //地址长度
    % {+ P6 a; u' v$ Q5 o$ M0 ~3 l" d. o
  99. sCommand.Address = 0; //起始地址5 f6 a( B$ F, U0 C5 {; g- Q
  100. sCommand.DataMode = QSPI_DATA_4_LINES; //数据线宽2 d0 c2 l9 d; T: F4 F  F% L
  101. sCommand.NbData = 10; //读取数据长度" I' `! ]* g& D
  102. sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; //无复用字节阶段- b5 R5 r7 a& l3 D" P
  103. sCommand.DummyCycles = 8; //Dummy 阶段。N25Q128A13EF840F
    ) F/ @5 [( d) C: ~1 B
  104. Dummy cycles 默认为 15
    4 H# z; d: E7 N, l* [) ^
  105. //配置命令(在有数据阶段时,命令在后续发送/接收 API 调用时发送)
    * o$ m* o6 x% \; u4 {4 J7 W
  106. if (HAL_QSPI_Command(&hqspi, &sCommand, 5000) != HAL_OK)$ \) j7 y/ ^1 p0 ^" Z9 o+ J$ ]. E
  107. {
    + T7 c6 ]- H- c" I# t0 \
  108. Error_Handler();; S6 {) K: R- D% `) G7 W; c
  109. }. y2 v* \  _# X0 L5 c/ ?
  110. //执行 QSPI 接收8 m/ \; p. e$ K8 p: p# H4 c
  111. if (HAL_QSPI_Receive(&hqspi, RxBuf,5000) != HAL_OK)
    8 x6 b4 s6 V* n/ \% h+ U6 x6 f  _
  112. {: X: u+ m) I9 R% A
  113. Error_Handler();$ X. b- C: ~- L
  114. }; r, a/ R1 X8 @  q% B) X( g
  115. /* USER CODE END 2 */
复制代码

9 Z% f& i9 l. }  ^" M* C! ]
3 \( r3 O- d! f$ [/ o6 E# w) N' F四 小结" }+ \: A. }: i) c3 j
STM32 的 QuadSPI 接口灵活可配,对于命令阶段、地址阶段、复用字节阶段、Dummy 阶段和数据阶段都可以进行配置。基于这种灵活性,能够实现市面上 SPI、Dual IO、Quad IO 的串行 Flash 支持。但出于简化考虑,QSPI 支持的中断访问及DMA 访问等更多功能没有在本文进行介绍,更多实现可以参考 ST 提供的 Cube 软件包中的 QSPI 例程。另外,不同厂家的串行 Flash 命令及操作实现略有差异,具体以采用的 Flash 文档描述为准。7 l1 x! `5 U/ f$ b

, P8 x) {( `/ W. ^8 Q/ f
8 v7 l  n/ V- Z5 {3 m4 c5 g. }/ d  `$ D8 T& o" h
/ X' m. ]$ [" i4 l' y

+ t$ H- s2 A( t' b0 ?) Q2 J
; r/ V) }. E& k; e3 _4 x2 g) P1 o( u
4 {8 j$ x) x/ q7 q
收藏 1 评论0 发布时间:2022-2-22 18:48

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版