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

基于STM32生成外部Flash Loader的方法经验分享

[复制链接]
STMCU小助手 发布时间:2024-3-21 17:58
一、引言; G7 `$ i! v' \( A
在嵌入式应用系统中,越来越多的应用需要扩展外部 Flash 来满足存储需求,例如 GUI 的应用,需要将视频、图片、字体等素材存储在外部 Flash。对于 SPI、FMC、 FSMC、QSPI、OCTOSPI、SDMMC 等接口存储器,需要一个 Flash Loader,把资源下载到外部 Flash。在 STM32CubeProgrammer 安装目录的“bin/ExternalLoader”目录下,ST 提供了官方开发板对应的 Flash Loader,也就是 stldr 文件。但官方提供的 Flash Loader 数量有限,不能完全满足用户需求,需要用户根据自己的 MCU 型号、Flash 类型,开发自己的 Flash Loader。: c  p( S/ I: s! V" E
: e0 N' V: G7 Z; {
ST 的 X-Cube-DISPLAY 是 STM32Cube 扩展包,3.0 版本提供了 SPI/QSPI 接口的 MX25L6433F 的 Flash Loader 的源码工程,用户可以基于此进行自己 Flash Loader 的开发。本文档就是根据 X-CUBE-DISPLAY 3.0 所提供的 Flash Loader 工程,以 NUCLEO-STM32G474+GFX01M2 开发板为例,介绍了 STM32CubeIDE、KEIL、IAR 等不同编译器利用 X-CUBE-DISPLAY 所提供的 API 来生成外部 Flash Loader 的方法。
7 H3 ~1 G' @$ s: W1 s7 p; N3 j7 P" ?5 o) j( P4 b6 a4 n
二、Flash Loader 的开发过程
+ U( U# l# {- E+ E7 I5 O, q2 z参考 ST 在 X-CUBE-DISPLAY 3.0.0 所提供的 Flash Loader 工程,外部 Flash Loader 的开发过程主要包括以下 3 步。
  j! `* |: G7 U. V5 i(1)更新 Dev_Inf.c 中的存储器芯片信息。" I  m8 }9 ?9 l, p0 {+ z: t
(2)重写 Loader_Src.c 中的相关接口函数。# k: G$ ?7 F8 g% q6 t
(3)更改输出文件名。
* P  d8 k, c3 P/ |$ @! g. G3 }5 W; k  h! V# n& m" ~( H
项目配置好后编译整个 Flash Loader 项目,将生成一个 ELF 文件,文件的扩展名取决于所使用的编译器,Keil 的为.axf,EWARM 的为.out,STM32CubeIDE 的为.elf,通过编译后处理指令更改为 stldr 扩展名的文件,将该 stldr 文件复制到 “bin/ExternalLoader”目录下就可以被 STM32CubeProgrammer 使用了。3 `7 a, q- ~8 c3 E( ?
* S2 [8 t/ j3 Q. `" u
2.1. Dev_Inf.c 介绍
7 T' \% d0 ?. \% C; C此文件中定义的 StorageInfo 结构提供有关外部存储器的信息。用户在制作自己的 Flash Loader 时,需要根据 Flash 的参数来更新相关信息。
, L, i3 n: S7 \% v1 `; o; X4 |7 Y
  o  ]. e5 U$ S8 I1 X8 M5 |
2.2. Loader_Src.c file% N9 G' r2 A: `# }5 e& r& |2 I
该文件包含了制作外部 Flash Loader 所需的接口函数,主要包含初始化,擦除,写入以及读出等操作。其中 Init,Write, SectorErase 这些函数是必需的,不能被省略。除了这些函数之外,您还可以重写 Read,Verify,MassErase 函数。
# W  k9 |/ f# m- j( N# d1 [7 B) u, T$ Q7 w+ ~' A
2.2.1. Init 4 \$ A, Z* Z  \. [
Init 初始化连接到外部存储器的 GPIO 引脚以及初始化 IP 所用的时钟。3 u. T" `) ~7 _
如果成功,则返回 1,如果失败,则返回 0。 $ K% s! r8 u# c
int Init (void)
4 Z3 I9 q# d% L  h, w  m/ V$ C
6 c5 ]7 q0 ~( q0 {4 L- @
2.2.2. Write * N2 V, T8 n' j3 t5 w" G2 Q; A
Write 函数将在 RAM 定义的缓冲区写入到外部存储器。9 U) r% z6 }  b- d
如果成功,则返回 1,如果失败,则返回 0。
6 `  K5 Q$ N6 S/ |int Write (uint32_t Address, uint32_t Size, uint8_t* buffer)
  A. O- j8 V5 G: H- M* w( I$ E* i4 q& a& ]  `$ b: w
2.2.3. SectorErase
+ C9 q/ x1 D* d6 F8 r/ C9 l擦除内存指定的扇区。其中起始地址等于要擦除的第一个扇区的地址,结束地址等于要擦除的结束扇区的地址。
9 ]. r: d3 K& T8 e如果成功,则返回 1,如果失败,则返回 0。
) T( c+ l, N! G5 u4 `1 ^4 ~0 kint SectorErase (uint32_t StartAddress, uint32_t EndAddress); i2 c5 F2 }9 V

; z) x, n. _; {
2.2.4. Read 功能 ' `9 M/ Y6 E1 v; t6 K( ~* E
Read 函数将存储器指定地址的数据读取到内存中的缓冲区中。
; M$ J' f% Y' E6 ?; T  [3 o! t  W# ^如果成功,则返回 1,如果失败,则返回 0
% w5 h' {: j- k3 zint Read (uint32_t Address, uint32_t Size, uint16_t* buffer)
8 K- b  A  f/ y
) ]' H- q+ _& K# t! Y! A
2.2.5. Verify * L& |6 T7 @% f6 b, _4 w
功能当选择“边编程边验证”模式时调用验证函数。此功能检查编程的内存是否与 RAM 中定义的缓冲区相对应。
. ^0 z- a# ~  W% M- L7 `; {% e: S+ L% [7 S: o
2.2.6. MassErase 功能 , Q9 Y" x* s2 D
MassErase 功能会擦除全部内存。6 M, m+ \3 @' |) G$ j, i
如果成功,则返回 1,如果失败,则返回 0。 2 H' b1 s) s" w: H1 m3 h5 _
int MassErase (void)  [7 |5 m3 I1 N3 j0 {- i- _. \
" x- b# V' h. L" |+ p7 e
2.2.7. Checksum 功能0 P4 h$ H1 }$ ?  L
描述的所有函数在操作成功时返回 1,在失败时返回 0。
8 T% z' s! t' o% J/ ~" z+ O' B# S6 n# i6 F! h8 A8 z
三、利用 X-Cube-Display API 生成 Flash Loader 的方法

. C; z2 N1 q0 p: s* I- C" G这里参考 X-CUBE-DISPLAY\3.0.0\Projects\NUCLEO-WB55RG\Applications 目录下的 GFX01M2_FlashLoader 工程的方法,来移植一个 NUCLEO-G474+GFX01M2 的 Flash Loader,这是一个 SPI 接口的 NOR FLASH,芯片型号 MX25L6433F。
8 {" f( p9 y/ }, g  q# `我们打开 STM32CubeMX,MCU 选择 STM32G474RET6,首先配置时钟,其次这里用到外设有 SPI,还需要对 SPI 进行配置,查看 X-NUCLEO-GFX01M2 和 NUCLEOSTM32G474 原理图,外部 Flash 用到了 SPI2,GPIO 引脚用到了 PB13, PB14, PB15, PA8。SPI2 相关配置参数如下图所示。
6 e0 t6 m' [9 p" J# k/ I
4 ^) d' s0 q) I4 X' W: l
1.png

5 \" E/ C* f. y  R' R
1 r5 F' ~" N) l4 D1 L5 _+ e8 j

/ R$ V. a- J/ t

; v- n6 ]) V0 |" U0 J# I6 I
▲ 图1. SPI 参数配置

( r1 w3 r9 m8 {3 ~0 v# Q5 R  Q  a3 b5 H4 L

1 R4 C6 `2 x1 P7 fSPI2 外设相关参数配置结束后,点击 X-CUBE-DISPLAY 标签,为相关的 IO 接口配置对应的引脚和外设。
) z1 o% U2 R; m4 U图片, [* a( k2 O, p" C% ^9 D
' x3 P8 ^' X: Z- q; ~$ ^

5 E2 E5 U9 ~, C1 z
2.png

% J7 y2 p: w4 z0 z
# s: l( P. G- {( y" m
) P/ w5 U1 x+ g7 n2 Q0 N  j
▲ 图2. X-CUBE-DISPLAY IO 接口配置

$ O) z: g8 i, p  @  e3 h  ~, n9 J$ ], ?0 W- v: f3 x) X

" f: ~1 d" `: a相关参数配置好后,点击 Project Manager,给工程重新命名,由于 Flash Loader 不需要 main 函数,选中配置的 “Do not generate main()”,这样生成的代码就不会有 main 函数。然后点击生成代码按钮生成代码。
8 x7 ^; R" u. k: O) H0 u+ O* a3 A/ H. l% }( [7 _8 F
2 P: X& h* b* i  G
3.png
5 P* e" e+ v- f2 |- g/ j
: N0 F) t* Y# f+ j) |( Y
% H3 c# T0 g, ]6 R
▲ 图3. Project Manager 修改

2 H8 ]% V2 s1 @
% s2 Y% K$ u. O3 u

& {$ z0 N% i; L$ o1 h0 G+ g生成的代码还需要添加 Dev_Inf.c、Loader_Src.c、Dev_Inf.h、Loader_Src.h,将这个代码添加到 Core 文件夹下的 Inc 和 Src 文件夹,为了方便不同编译器生成的代码能够自动加载这几个文件,复制.extSettings 文件到该工程文件夹,该文件会为工程新建一个 Loader 文件组,然后再重新生成代码。生成的代码用 VSCode 打开,在 main.c 函数中新增 MX_Init()函数,函数主要的功能是复位外设和初始化 GPIO。
" `: }- W; ~) A4 p8 ~, {
' q0 ~' F9 m. ?1 r/ @. Q6 S1 u0 d8 l
4.png

* V1 y: P& H. t; j  f; q7 C. v9 L
▲ 图4. 添加 MX_Init()函数

; N8 i7 X3 G8 C+ F9 v
关于 Dev_Inc.c 和 Loader_Src.c 文件中的函数,这里就不再做一一说明,大家可以对照附件查看,下面主要介绍下不同编译器的工程属性配置。, F/ z' R  t& L7 T4 l. v3 F
2 J8 F+ q$ y2 G/ t: T  s+ j4 \
3.1. STM32CubeIDE 工程配置
+ S) f, i: k# }. b; ?2 HSTM32CubeIDE 的配置修改包括从工程中去除 startup_stm32g474retx.s,修改 Linker 文件,修改启动函数入口,添加后处理生成 stldr 文件。 8 \* R( y- Z+ l! }2 h7 R

! _* a& [# ]# ^/ @* a
( g5 F3 R4 T) ~6 Z' U8 b" U# s
5.png
6 |9 Q; e% p# s- F0 n

! W8 y5 I, S3 ]; [4 {; D" x

9 I' R% Z3 E' B
▲ 图5. STM32CubeIDE 中将 startup_stm32g474retx.s 从工程中去除

3 L2 @) u4 m  b1 _1 q5 I
7 ]1 k4 g4 E  ~: I+ c: z( U

6 l1 M8 k0 F$ Z: c7 S$ S) C/ a修改 Linker 的配置,通过“Properties”打开设置页,将 Linker 文件修改为 STM32_FLASH.ld。: x/ A( X% H, i2 s& B
# V. S1 m, y! ^5 L
% r' e$ {9 X, Z; x- M
6.png
( b; I- }2 F( Z/ B5 u" [4 F
& w; P2 W- e& q7 f5 J" e' ?

# G. `7 T/ |! J2 T$ f
▲ 图6. STM32CubeIDE 修改 Linker 文件
  Y5 s; [& P1 m2 H8 ^
6 g8 ^9 Z% `& C: }6 I
通过 “Settings” -> “Build Steps” 配置页中,在 “Post-build steps” 处添加指令 :cmd.exe /c copy /Y "$(BUILD_ARTIFACT)" "..\MX25L6433F_GFX01M2_STM32G4.stldr",编译后生成 stldr 文件。
+ Z) J0 S' [# _$ T& C& e$ I! _" r* k& ~. ^
3 x0 A0 E1 Q8 m/ B; x. f
7.png

2 R7 G) `3 e, t5 C3 h: a
▲ 图7. 在 STM32CubeIDE 中添加后处理语句

9 ]. L0 L* b3 Q! V  x% o3 ~

8 B0 B' Y8 c& m) A+ a当这些配置好后,重新 Build 工程,这样就会产生所需要的 Flash Loader。: u! I; ]6 q, u- J( G
1 H% A( N! l; j$ @/ _7 f( M' y
3.2. KEIL 工程配置. W3 N- i* p1 a. E( v: M0 H% l
与 STM32CubeIDE 配置过程类似,KEIL 的配置过程主要包括以下操作。在 Target 标签页,Arm Compiler 选择“Use default compiler version 6”,如下图所示。8 I1 T4 j& p; u" r( @! @' O

- P+ s1 M- w! j3 J7 ~: u# V* v) a
: w: i1 t) C: b0 ]# O% i
8.png
3 O. G+ B  d) N7 |9 Y8 ]

4 X+ h7 y/ L7 {+ ?, g7 z) i+ f

% B/ p8 x  F+ x  q+ h
▲ 图8. 更改 Arm Complier

* _0 n# y" ]) {# X% A0 ?0 u在 startup_stm32g474xx.s 的文件属性中,去除勾选“Include in Target Build”和 “Always Build”,这样这个文件就不会被编译和包含在这个工程中。
- H) @, C% h% B# {! T0 P: c1 w$ N  j$ v* ~4 a
: M9 Q  l5 N/ r9 W
9.png
2 p, W4 D) S5 ?) E0 ]

! [) F# D. t3 r/ i
) ~& k" k) d/ \) C6 i% i3 W( i' B
▲ 图9. 在 KEIL 中将 startup_stm32g474retx.s 从工程中去除

7 r: h+ E2 z& J" d/ u* [- h
9 g# ^; {; z7 x( r; h6 ^, F
7 |4 n+ K# I5 u' N) x
在属性界面,切换到 Linker 界面,去掉“Use Memory Layout from Target Dialog”勾选,修改链接文件,将链接文件更换为 stm32_loader.sct,同时注意在 Misccontrols 添加“--paged --pagesize 0x10--diag_suppress L6305” 。6 {. |% x" o/ y! ]0 R3 Q% l

2 ^- I1 g5 n1 w4 k; }+ b" V
4 H5 ~2 H; P7 n: o' o
10.png
! c# A5 a( ~& M" ?2 m
▲ 图10. KEIL 中修改链接文件
! B& e5 y: D! a/ q: {  a, m: S: _
: f/ u: }$ b: f0 B" e
与 STM32CubeIDE 配置类似,添加后处理语句“cmd.exe /C copy /Y "!L" "..\MDK-ARM\MX25L6433F_GFX01M2_STM32G4.stldr"”。) R: ?1 ^6 u& l  E9 ~: P. k+ F5 K, }8 N! {
+ }, m# s& ]# y1 ~3 D$ l/ G+ A
* e9 U1 @4 V  |9 B5 ~+ c. X
11.png
4 |) F- f* T2 M% t/ z1 ~2 U: l2 u- N4 J
▲ 图11. KEIL 中添加后处理语句
+ F  o4 ~6 j4 [: E- Q7 [; J
; I/ v. {% z) U$ l, l! B) l. g
6 p6 p' O2 u) W  \1 L8 K
这些配置好后,重新编译代码,会在 MDK-ARM 文件夹下生成 stldr 文件。# R0 B0 h# A* E
2 ^" G  H, B# H+ e5 y. a
  x& `9 Q" {4 m5 I& o, r
3.3. IAR 工程配置2 l, m1 B" g3 l
IAR 工程配置与 STM32CubeIDE 和 KEIL 的过程类似。
2 @  w) Z  ]2 S3 F$ W) ^
6 R2 }7 m3 ~/ @2 I

* W5 X3 ?* D* ^* r) U# x4 E2 W; Q
12.png
( j- T( h) W% a' f; C, A

5 y* G4 c  J" k* @6 O

+ i# u% L  ]8 t0 q
▲ 图12. IAR 中将 startup_stm32g474xx.s 从工程中去除

; }5 P2 T1 c+ H9 Z  l/ w
# Y. t7 D+ K* N/ t7 Z
- f( y7 |. ^. v: b
13.png

% Q" l. Y0 ^1 Q. H, T4 H" n; Q
7 p. c5 m8 `# |/ t
▲ 图13. IAR 中修改链接文件

+ \2 w. ^) s; M: f: P  l

; {; }0 x) n. ^3 p4 v1 N& K# S

' H- g# l* D6 T2 C% ~! L. [

* h4 ]7 S' b( D
14.png

2 T$ z. i: V; Z2 D, H: K4 x" T# j* f: Z4 c. N7 \( j- u6 K7 W
▲ 图14. IAR 中更改入口函数
3 B6 x4 m/ Z) J& b: }

9 k2 s" D" F3 n% D

" E( w7 Q! G' `% V1 L' V

& [1 _" U$ N! S  r! x
15.png
2 k: u6 f0 g7 X$ f$ q% ]

# X: l# F7 l. F+ e
▲ 图15. IAR 中添加后处理函数
7 ~/ h1 R4 e- s. b! O1 D) w" C

+ t. \% x- q" U8 U) u2 e3 v5 W* l9 D9 {6 b$ F* i: V
这些配置好后,重新编译代码,会生成 stldr 文件。
; ^) T$ Z9 n/ ]) `. @' B) }
5 A7 w7 O" t) ?
四、小结
2 f$ r4 L0 i6 ^" r4 J5 G$ {本文结合 X-Cube-DISPLAY 3.0 软件包中的示例,介绍了利用 X-CUBE-DISPLAY API 进行 Flash Loader 的方法,如果用户选择的 Flash 是 MX25L6433F 这款 Flash,那么可 以参照此方法,来快速开发自己的 Flash Loader,如果所选的 Flash 不是 MX25L6433F,也可以参照此方法,重新编写对应存储器的驱动来开发对应的 Flash Loader。) ?" X$ `9 U+ U. z  O7 D
9 N& g4 |6 \7 ~+ s% k  p
/ r6 U: D4 N2 h  v8 F/ d
转载自: STM32
. e; A- S+ W. |3 q7 C如有侵权请联系删除
0 C, l2 I1 b0 m& x8 I* N, O" }; q
9 M! g0 L1 X6 W; Z

2 H. @) [$ w9 L5 |+ N4 f
收藏 评论1 发布时间:2024-3-21 17:58

举报

1个回答
Cheng、 回答时间:2024-4-12 15:13:08

你好,关于IAR制作stldr文件有详细的教程吗?比如最后用的是什么指令?

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版