83.1 初学者重要提示
& f0 R0 p& N4 Z 操作本章配套例子前务必先将QSPI Flash的下载算法放到MDK安装目录。5 e: F3 {( W4 j" N& L6 B( F( ?) B
本章节与第28章的时间关键代码在ITCM执行的设置思路是一样的,可以让大家对本章节的方法有个更全面的认识。, g5 }. o' u7 I" z
6 p8 q5 u% r6 G8 T1 \, j g83.2 内部Flash和QSPI Flash混合执行程序的优势
1 {: c3 p: b0 ]/ A. W3 P$ G) f4 K现在大家使用H750或H743在外置QSPI Flash执行程序,都倾向于制作个BOOT,再制作一个运行在外置QSPI Flash的APP程序。即本教程第82章讲解的内容。- M" n# B9 r$ J5 S2 Q9 O- y& \
0 M7 V( ?7 H# V2 n @0 b, p
本章要实现的这种方式对于我们想外置QSPI Flash运行程序,在调试测试阶段更加方便,甚至是项目使用,可以性能最大化。+ W( _0 x6 C5 _+ a$ {$ e
) p, h1 u g h8 R0 n5 Z
83.3 下载算法存放位置9 Y; J! [; m$ [& V9 S$ k# q
编译例子:V7-060_QSPI Flash的MDK下载算法制作,生成的算法文件位于此路径下:
% r6 p- m# Y7 y6 ^; A" E5 I3 `# E( r6 c! l1 ?. e# ^: X* B/ }& }6 g- O: E
" W6 I# q3 j. Z$ q& W
: e8 j; `6 n- ?/ A
生成算法文件后,需要大家将其存到到MDK安装目录,有两个位置可以存放,任选其一,推荐第2种:
# y% m) x1 N9 A9 e" O- T) `2 e
: F* z. ^% G8 Y/ s" ~. e Y 第1种:存放到MDK的STM32H7软包安装目录里面:\Keil\STM32H7xx_DFP\2.6.0\CMSIS\Flash(软包版本不同,数值2.6.0不同)。8 H$ `0 P5 w3 W
第2种:MDK的安装目录 \ARM\Flash里面。
, A' ^7 l) h" ]6 V9 ?# X
* ~: r- E+ H2 Q/ s G, F0 ~" o* U u4 j
1 z+ b+ |) ]% [' B8 B83.4 内部Flash和QSPI Flash混合执行程序说明# s0 } c6 O7 k
混合程序的设置注意以下两点即可。
7 Q& g6 i2 T, ~4 A1 [# ^+ v- O7 I8 x
83.4.1 初始化QSPI Flash并设置内存映射模式+ b# {0 S/ K) v
在bsp.c文件中初始在bsp.c文件中初始QSPI Flash并设置为内存映射模式。注意,配置好时钟后,优先初始化QSPI Flash并设置为内存映射模式:
- w! D- e: `3 r1 B% Q9 C, \9 b. J2 _" E
- /*/ K) D d5 a' F- v
- *********************************************************************************************************& U' h! `& F2 }: l8 } @4 e& k
- * 函 数 名: bsp_Init
0 T4 D5 T0 s5 b; ?; t - * 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次+ ^0 O/ K7 L" ~6 }" s$ Z
- * 形 参:无2 I1 S8 a; ?, v
- * 返 回 值: 无0 s6 q: Q3 q) t! y
- *********************************************************************************************************2 G5 n% V% f; v8 D1 c* k" M$ R
- */* |4 J1 m# U! p6 _% y# k' g
- void bsp_Init(void)
/ \, H+ o4 s+ a" b7 D: B5 A - {0 X- W$ I5 {- N9 w
- /* 配置MPU */- O# L+ `- K- t$ h4 U' W
- MPU_Config();7 a- d0 S) U) B2 N, C
4 s6 l# {( {' K" D$ R) j! F- /* 使能L1 Cache */3 S4 M, J( {$ ~3 x1 |+ e; T
- CPU_CACHE_Enable();
K0 M7 V M/ W( r7 e - ( \: D7 i: Q. b
- /*
5 V$ d5 G& c; A6 d - STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟:
& r8 k7 d7 U- R. B, n2 h% a - - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
/ F3 G0 \2 X! k ?: V8 @4 ] - - 设置NVIV优先级分组为4。/ A) }$ ]1 f# l8 F
- */7 l1 ]/ r. G$ |) i8 Q/ Y5 r1 X
- HAL_Init();
6 o2 w1 @" j! Y& m, u
& I* n8 q, c5 L8 T: z- /* , d$ R0 N# I7 r p- |
- 配置系统时钟到400MHz
4 w7 ^2 s. K1 Z! L% h; I - - 切换使用HSE。
, v' A; i/ G# B" X/ E+ N* J" X - - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。5 }, {; M0 _9 e0 s$ Q" B4 _# q
- */
& H; }8 D9 R( u8 i% ?: e - SystemClock_Config();
2 J" x% k- q" w" T
0 O2 }) ?+ {4 C- /* , i$ _# t6 l, g, |5 ?
- Event Recorder:. B7 P* h$ ]" g' z
- - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。% w, T/ }7 r; \, |* s) @; a
- - 默认不开启,如果要使能此选项,务必看V7开发板用户手册第8章2 s) a/ p& w6 l! B
- */
! e8 x* [/ G9 x8 T3 C - #if Enable_EventRecorder == 1 8 J+ ?4 L+ ?2 A
- /* 初始化EventRecorder并开启 */5 m# I9 n' H" l( f
- EventRecorderInitialize(EventRecordAll, 1U);$ |; L! s6 v4 s1 P' S4 b
- EventRecorderStart();# @/ T+ l9 G; I1 g Y) J/ B7 z7 v
- #endif) T- A$ q/ B, ]& C2 X z* [3 q
4 v6 ~5 v, U1 }0 }: m3 `' ~) Z: B- /* 针对不同的应用程序,添加需要的底层驱动模块初始化函数 */9 D, @ `. u* E4 j1 t5 m# t
- bsp_InitQSPI_W25Q256(); /* 配置SPI总线 */
$ w4 p) F9 B# m6 G4 i - QSPI_MemoryMapped();
; R' [6 ~) h) R! | - 1 K- ]) b- ]: g8 N3 z) I4 J' Y
- bsp_InitDWT(); /* 初始化DWT时钟周期计数器 */
5 ^ [( a6 Q8 k4 i8 S2 y - bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */! ?3 @ T- t6 B9 U
- bsp_InitTimer(); /* 初始化滴答定时器 */
) j. A. H1 C! I4 d; Y - bsp_InitUart(); /* 初始化串口 */
: }7 l* @# r/ v. P. x7 E - bsp_InitExtIO(); /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */ 9 p& Y$ \1 H/ M" e, Q8 C# n
- bsp_InitLed(); /* 初始化LED */ $ b3 r: V& r- Q9 W' E% I
- bsp_InitExtSDRAM(); /* 初始化SDRAM */$ w( T v. U6 H' j! }9 |
7 i! L' P$ @) g! @- bsp_InitI2C(); /* 初始化I2C总线 */
: ]2 H; M9 w2 E% A+ k - TOUCH_InitHard(); /* 初始化触摸芯片,LCD面板型号的检查也在此函数,所以要在函数LCD_InitHard前调用 */
' s4 |( y6 Y- h, a' l0 R# a& |$ P - LCD_InitHard(); /* 初始化LCD */
, i) e: B: z# e4 L0 m; M - }
复制代码
3 ~9 T5 d7 W5 a5 R; N83.4.2 设置运行在内部Flash和QSPI Flash的程序
! H1 Y+ y3 p2 T6 c; R% A由于我们要把QSPI Flash初始化并设置为内存映射模式后才可以使用QSPI Flash运行程序,所以要在QSPI Flash运行程序之前的所有操作都在内部Flash里面实现,主要是滴答定时器,RCC,QSPI和HAL库等相关配置。其它所有程序都可以在外部QSPI Flash执行:" p E/ d4 h, [' K$ i
- ?' `, l. r# {8 K7 A
- b$ C( K# }+ i& _ c: w0 Y# }6 ?, l7 _. h K% F [4 a% J
83.5 内部Flash和QSPI Flash程序调试下载配置+ j; ^" g( U2 W- `" j2 j
将下面两个地方配置后,就可以像使用内部Flash一样使用QSPI Flash进行调试了。并且这种方式可以方便的调试程序,内部Flash和外部Flash都做调试。- s4 }8 l# |9 ^. X! u0 Z( C
9 j7 s3 }: V" ]' S# p. b+ Z5 _) [
83.5.1 下载配置
4 o, c3 l, R' h$ M注意这里一定要够大,否则会提示算法文件无法加载:- V4 B0 Y" O% }3 M7 d5 {$ q/ z
$ a. g5 ]- k T; r0 o
8 C9 I' G( l( O+ F( L( x
0 D' C# F" y. k+ ]: r! H我们这里是将其加到DTCM中,即首地址为0x20000000,大家也可以存储到任意其它RAM地址,只要空间还够加载算法文件即可。推荐使用AXI SRAM(地址0x24000000),因为这块RAM空间足够大。- A' D' D9 R' Q$ u4 f3 b8 j
% n9 d0 y% t) _# i t! M: P如果要下载程序到内部Flash和外部QSPI Flash里面,需要做如下配置,两个下载算法都要添加进来:2 X: J4 {" B2 w( m: n% r
- {5 \2 G$ H' N6 ]' m
7 b7 J; n# T$ m; ~+ w: b, g, M/ T- r- g- X6 H
83.5.2 调试配置
% Z, K" v( n# Y9 n( E- c注意这里一定要够大,否则会提示算法文件无法加载:
9 q6 u% M: k: c* Y! s; S
- d2 x! f# Y) F1 K1 y2 N! U* _
$ C$ x. t/ y/ v! Y) j! w9 N" `$ @4 A* D& ^
我们这里是将其加到DTCM中,即首地址为0x20000000,大家也可以存储到任意其它RAM地址,只要空间还够加载算法文件即可。9 h# h) Q3 G& i* c" b1 U
1 s$ q- R3 p. D/ X1 |如果要做调试下载,需要做如下配置:% N. ^5 j4 V$ L; Q/ X
6 P& k6 p2 T6 P3 x) ^5 P0 k! ?
$ O' b: j. h5 v# f: ]9 G' v& e
, j4 l; J7 x( i: Z
83.5.3 程序调试效果& _: ~1 J r1 o0 J& ~0 X" }% o
调试效果如下:" I1 _6 O8 o% g$ s5 N
! \ S8 I9 O. {6 a! {1 V: k$ z$ x' m
/ L9 K) Q$ g, |, g$ E; V. P& M
U3 `/ h8 D8 G! A# b
83.6 实验例程说明
9 _! e( }% g3 z$ M: }# s- C' _本章节配套例子:V7-064_内部Flash和QSPI Flash都运行程序的混合方式,无需单独制作BOOT和APP(强烈推荐)
}0 A( ?' |4 _+ f. u: L, O% [
9 l' q8 q! [3 s: A
! X! z7 i! R( u2 L, s7 Z% u- m- K, @1 R1 V6 k# i" k) o7 M
编译此程序弹出的警告不用管,可以选择屏蔽此警告:; m7 v7 i: Q- C* ?9 f, Z ]8 B
/ ]$ M5 R4 Y/ ?% L2 D+ P* Q& ^1 n
# w& f3 g5 ^0 u! i1 k' P$ @0 C
. I( X* _, c0 y- x83.7 总结: T" j' L/ L* V4 } c
本章节就为大家讲解这么,为了熟练掌握,大家可以尝试自己实现一个内部Flash和外部Flash混合运行的程序。/ n# q, L3 z$ c6 G5 P9 J
' X. E, Q* I5 d9 q& ~
& d/ g3 G' Z& q% i+ c6 Z9 P
3 a/ E: [; U4 ?- a
|