83.1 初学者重要提示9 B! x' ^! ^( F' g" |0 ?3 y x6 U
QSPI Flash的相关知识点可以看第78章和79章。
9 ]% p+ r" _. D: h% {+ r 操作本章配套例子前务必先将QSPI Flash的下载算法放到MDK安装目录。4 u. {+ e7 x; c" T
本章节与第28章的时间关键代码在ITCM执行的设置思路是一样的,可以让大家对本章节的方法有个更全面的认识。0 a; a5 y0 @8 j* `, p W
83.2 内部Flash和QSPI Flash混合执行程序的优势$ Q0 X2 T9 g' V. W. E
现在大家使用H750或H743在外置QSPI Flash执行程序,都倾向于制作个BOOT,再制作一个运行在外置QSPI Flash的APP程序。即本教程第82章讲解的内容。" E: g: A. Q. X0 Y# v; Z
/ ?! [, U5 a5 ^5 z3 I% n6 \: P7 Y本章要实现的这种方式对于我们想外置QSPI Flash运行程序,在调试测试阶段更加方便,甚至是项目使用,可以性能最大化。
- F+ k& B9 ?9 v* X) D5 m5 W- V7 r1 C) W
& Z5 }: w1 U4 N* s# n83.3 下载算法存放位置- w9 T/ k2 h1 R( E2 ?+ t2 ~
编译例子:V7-060_QSPI Flash的MDK下载算法制作,生成的算法文件位于此路径下:
. I) K! r3 [* z+ W( a* W# J& v/ m1 P" e4 M
4 X$ w3 |5 V* ~0 [8 b, P6 g! y; O$ y2 E8 A
生成算法文件后,需要大家将其存到到MDK安装目录,有两个位置可以存放,任选其一,推荐第2种:
4 b" G7 T2 n0 q" Z7 ^3 F/ _# L& O h- A) P
第1种:存放到MDK的STM32H7软包安装目录里面:\Keil\STM32H7xx_DFP\2.6.0\CMSIS\Flash(软包版本不同,数值2.6.0不同)。& z2 l9 y; }3 D$ y f# w
第2种:MDK的安装目录 \ARM\Flash里面。
$ J4 Q- V1 p+ l
, o9 Y: [" q) `- U$ d( i4 D$ l7 A! Z+ U0 r
83.4 内部Flash和QSPI Flash混合执行程序说明3 a* }2 w. C- a% I1 Y1 r+ V$ p
混合程序的设置注意以下两点即可。9 Z9 {3 @ F# E' s4 T
6 \6 w( G% R& {' {4 C. w
83.4.1 初始化QSPI Flash并设置内存映射模式8 P' { e, x( z
在bsp.c文件中初始在bsp.c文件中初始QSPI Flash并设置为内存映射模式。注意,配置好时钟后,优先初始化QSPI Flash并设置为内存映射模式:
* L& Y% l: U6 T" N: n x2 V
7 L. e3 A5 q6 x% l+ c9 c- /*
) k1 v6 r# R" D - *********************************************************************************************************
. e" ~2 @3 Y7 C# d: Z - * 函 数 名: bsp_Init
, I0 A" i5 D9 x& E: E7 o. B& x - * 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次, @/ h1 X" T1 G, h# s! _; ]
- * 形 参:无* ^0 O% l, e# }; H, D
- * 返 回 值: 无$ l+ l1 \! i U; b
- *********************************************************************************************************) W+ i! a* ^ _+ J# x& n
- */
5 e( G3 \1 J0 ~. I - void bsp_Init(void)
" g+ A4 b& `( m+ U( E& U - {; g7 x! |! R/ e5 T1 b/ N
- /* 配置MPU */
! `/ L$ t2 Z! V: g; i! }. m" X - MPU_Config();# S# x6 `1 w9 Q7 j- N& {' ~
2 U+ I9 E$ g. E- /* 使能L1 Cache */
* ~0 }4 g8 {, e - CPU_CACHE_Enable();
' O1 M8 I( Z9 q - ( Y3 u, i! C6 O* P3 ^+ n
- /* 8 D$ l9 U% f* v% L
- STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟:5 ~9 ^+ j) q0 |" b0 i
- - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
) U) K9 r! A7 n+ c' [5 T5 t - - 设置NVIV优先级分组为4。
5 h; s0 Y3 u/ ?$ K9 m- F/ s - */' ]. L8 Q+ M& s& d+ O2 s
- HAL_Init();2 k A$ [- @( \+ B# c7 z3 z/ ~6 e2 f
0 W& c5 {* D. a+ W& ^4 ?- /* " I0 j k' C; `; l, s; ?" l
- 配置系统时钟到400MHz
3 g8 R2 c! Q! g0 T7 H8 C d: Z - - 切换使用HSE。
9 r1 y. g- A6 f+ u0 \% Q) N! Y - - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。5 d$ F: z, o, S" V
- */
4 e9 n" K/ a0 R. g; n - SystemClock_Config();
, [9 u0 p l" l" O3 T - 3 d. ~* w; b( V- y$ D9 }( g8 W4 I
- /*
) l. U% q8 U0 n - Event Recorder:9 P& x# \$ X) f3 f: f+ e% a
- - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。3 B$ O9 d5 ~. C6 Y
- - 默认不开启,如果要使能此选项,务必看V7开发板用户手册第8章0 ~7 R* Z7 \6 e. Z4 a4 p: O
- */
# O+ C! v2 n) a n4 N: w, Z - #if Enable_EventRecorder == 1 . `3 Q" t/ t3 S3 X8 B5 f* _1 ]
- /* 初始化EventRecorder并开启 */; z' b* y- G8 ?4 o: D l* U
- EventRecorderInitialize(EventRecordAll, 1U);
^" w+ c& ~4 P, ]' h) d- o |! @ - EventRecorderStart();" k5 e# b, L. C- k/ `
- #endif
9 \# q- o* G4 V/ N) r - ! O9 b$ |6 K8 W4 i Q* ]+ l" ~+ T
- /* 针对不同的应用程序,添加需要的底层驱动模块初始化函数 */
) r. ?* Q% n! z5 O - bsp_InitQSPI_W25Q256(); /* 配置SPI总线 */
& z) E8 r( A3 c# s3 ^ - QSPI_MemoryMapped();
4 d$ V. @0 B$ ?/ \; m - " T- L* r# c. {, A0 r
- bsp_InitDWT(); /* 初始化DWT时钟周期计数器 */
+ ^) E1 w# N L1 _8 y8 p! x4 @ - bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */
) p% n9 Q X: J! d1 D$ o - bsp_InitTimer(); /* 初始化滴答定时器 */, c l- V" v! Y- }: D. ?
- bsp_InitUart(); /* 初始化串口 */) f# y! Q- R+ ~) e2 C+ A+ |# c5 A% N
- bsp_InitExtIO(); /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */
' f& M5 x/ E$ `6 ?4 j% T+ N6 k - bsp_InitLed(); /* 初始化LED */
- G+ x9 o" p* z/ v/ D - bsp_InitExtSDRAM(); /* 初始化SDRAM */
; E. q, V# j4 R7 [( ~7 F8 d+ L" K
3 y4 B t, H( ^1 S) X* F0 f9 p- bsp_InitI2C(); /* 初始化I2C总线 */% Y* v7 Q, e8 P" }5 p6 E3 a5 Q
- TOUCH_InitHard(); /* 初始化触摸芯片,LCD面板型号的检查也在此函数,所以要在函数LCD_InitHard前调用 */
1 p; c2 n- `2 l2 r, P9 ?) x - LCD_InitHard(); /* 初始化LCD */
3 d3 w# q0 B, [8 N - }
复制代码
( K# w1 E9 e2 I! n83.4.2 设置运行在内部Flash和QSPI Flash的程序* o& \6 i* l& x# B# [
由于我们要把QSPI Flash初始化并设置为内存映射模式后才可以使用QSPI Flash运行程序,所以要在QSPI Flash运行程序之前的所有操作都在内部Flash里面实现,主要是滴答定时器,RCC,QSPI和HAL库等相关配置。其它所有程序都可以在外部QSPI Flash执行:
L! \ ?4 P: J& v
( `1 W0 {- y7 |+ g/ [7 l! U- v/ j
$ Y+ U6 i) V' Z r, \) @7 \$ ?2 P8 U* p4 _
+ D7 v$ u# u* P! P7 _+ C
83.5 内部Flash和QSPI Flash程序调试下载配置; b7 ?1 v( X) Z, }8 z. ]
将下面两个地方配置后,就可以像使用内部Flash一样使用QSPI Flash进行调试了。并且这种方式可以方便的调试程序,内部Flash和外部Flash都做调试。
1 w5 \$ x6 j$ `0 E. d* k7 X; m
0 G! E$ c4 ?& Q& @% t- q6 [; X# }83.5.1 下载配置: a' N: h) G* s3 J& B1 E2 Q) P
注意这里一定要够大,否则会提示算法文件无法加载:( A- n) M5 P9 ]6 V
5 {% T! @5 ~) [3 h% [. s, _
+ G1 w# b1 o, O* Q$ b' e8 U
0 \1 g' ?6 N5 D3 [5 a. d我们这里是将其加到DTCM中,即首地址为0x20000000,大家也可以存储到任意其它RAM地址,只要空间还够加载算法文件即可。推荐使用AXI SRAM(地址0x24000000),因为这块RAM空间足够大。
W) Q& D( q$ X Z+ ?# Y* G! E- U; y& Y' n
如果要下载程序到内部Flash和外部QSPI Flash里面,需要做如下配置,两个下载算法都要添加进来:% n0 z5 Y/ {9 ?% ?7 m2 D
7 u: ]2 B- j5 w: z
9 y6 _% B( g: \) \- d" ]" y S& Y8 n' [4 x; j" H( R( t
83.5.2 调试配置
2 k. M# J, M+ q* v* j& B注意这里一定要够大,否则会提示算法文件无法加载:4 L4 h& O- g$ f* @4 r" f
8 ~- }, ^4 P- e6 f
0 B* x! W- L* a& R8 y' Z" X7 P) P
9 @5 N( G4 S/ |! w我们这里是将其加到DTCM中,即首地址为0x20000000,大家也可以存储到任意其它RAM地址,只要空间还够加载算法文件即可。% v! j1 x/ K6 _) o4 I& X
3 M' d8 i/ P, O, m5 W d如果要做调试下载,需要做如下配置:
8 Z# C0 y' n+ O0 G8 K: Q% _' w" z# b" T# F' q
5 c) ]6 _: E$ G( g6 x
. V1 [4 f5 h$ Q
83.5.3 程序调试效果# H4 e# X4 n0 r6 l5 X. @
调试效果如下:
% {* W- y) C( c( l) p: M9 S$ o( i
! {4 X7 p' n" ]& z9 P* i0 E; y8 }' Z7 n; E1 `
8 T6 L; u& d3 v( [( c0 N' N5 C# ]
83.6 实验例程说明
4 T+ _6 n- L _. C本章节配套例子:V7-064_内部Flash和QSPI Flash都运行程序的混合方式,无需单独制作BOOT和APP(强烈推荐)
" z2 g8 R0 u/ r5 q/ \/ V" b1 {6 H2 x5 e6 w9 f: |
编译此程序弹出的警告不用管,可以选择屏蔽此警告:
% w+ }- ]2 y1 W8 K1 s& S ]
% o$ _( H- }, ^$ `1 {
& }* g$ x% O" Q; b3 L2 o( [2 J1 E5 @2 v2 [" \
83.7 总结
8 o* }3 Z N. i9 {本章节就为大家讲解这么,为了熟练掌握,大家可以尝试自己实现一个内部Flash和外部Flash混合运行的程序。/ E6 h6 F5 B' f$ w% T$ Z* m; p
. A) r; G7 a7 w+ r
) M$ c# V) V4 X1 a0 v
' P j: f" @/ m6 U* X
|