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

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

[复制链接]
STMCU小助手 发布时间:2024-3-21 17:58
一、引言
8 y( M# U& Y  z在嵌入式应用系统中,越来越多的应用需要扩展外部 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。
7 `5 P) F; x- ~+ [2 ?( u8 Y1 h9 [# |
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 的方法。 8 _; l9 s( M" s: z6 y
8 U* P/ m* `: ?# t
二、Flash Loader 的开发过程
3 U$ q, o+ V3 T% U+ X9 ^参考 ST 在 X-CUBE-DISPLAY 3.0.0 所提供的 Flash Loader 工程,外部 Flash Loader 的开发过程主要包括以下 3 步。1 Z$ g. g+ T4 K4 s5 Q% ^
(1)更新 Dev_Inf.c 中的存储器芯片信息。
9 C7 `8 \5 C: |/ H(2)重写 Loader_Src.c 中的相关接口函数。' a9 P& R# {2 {2 }
(3)更改输出文件名。5 T9 Z& K% F0 y# Y$ [  v
2 z% Y+ E, @: G  a/ z. l" y
项目配置好后编译整个 Flash Loader 项目,将生成一个 ELF 文件,文件的扩展名取决于所使用的编译器,Keil 的为.axf,EWARM 的为.out,STM32CubeIDE 的为.elf,通过编译后处理指令更改为 stldr 扩展名的文件,将该 stldr 文件复制到 “bin/ExternalLoader”目录下就可以被 STM32CubeProgrammer 使用了。& L6 C3 P2 r& P' I, o& f* D
% E4 w0 J0 U( a9 p9 @, _" v
2.1. Dev_Inf.c 介绍
7 E% ?# c9 D6 G1 l! B! n此文件中定义的 StorageInfo 结构提供有关外部存储器的信息。用户在制作自己的 Flash Loader 时,需要根据 Flash 的参数来更新相关信息。. U9 t0 J8 H: ~

. X; X( A3 P# F! t
2.2. Loader_Src.c file7 H5 X/ Y' a- G, P  i% X0 m$ ~' w& G
该文件包含了制作外部 Flash Loader 所需的接口函数,主要包含初始化,擦除,写入以及读出等操作。其中 Init,Write, SectorErase 这些函数是必需的,不能被省略。除了这些函数之外,您还可以重写 Read,Verify,MassErase 函数。  G# j. P! p+ W3 g8 }

, r9 \& I$ P. a2 u5 q2 Q/ V
2.2.1. Init
$ E% J3 v- i, b2 }8 ^5 V% dInit 初始化连接到外部存储器的 GPIO 引脚以及初始化 IP 所用的时钟。
1 S0 }# }6 l1 B3 p/ m; I- C  W# F如果成功,则返回 1,如果失败,则返回 0。 / W. b' A* ^' x7 N% e$ B
int Init (void)
/ j3 ?0 A  ~7 t7 b  D* q; q& K9 ]% D$ I$ R. n! @
2.2.2. Write % q$ {$ w% ?, c7 g. Z0 y# |$ \
Write 函数将在 RAM 定义的缓冲区写入到外部存储器。5 b3 s( g$ y; S: A2 q$ s1 x
如果成功,则返回 1,如果失败,则返回 0。
1 l  Q2 G# y( s( T; O5 wint Write (uint32_t Address, uint32_t Size, uint8_t* buffer)4 X) n6 ]0 M/ R7 Z

7 S; Y6 R4 \7 d7 O$ _% E5 h; x
2.2.3. SectorErase
. x! K4 ]+ }& I. y# S3 `  t. Y5 \擦除内存指定的扇区。其中起始地址等于要擦除的第一个扇区的地址,结束地址等于要擦除的结束扇区的地址。. |+ ~$ K# Q1 ?  q7 S% @5 y
如果成功,则返回 1,如果失败,则返回 0。+ ^* I9 O% e* y9 V* ?, l) G5 c
int SectorErase (uint32_t StartAddress, uint32_t EndAddress)  V: l6 Q  B$ ~  X2 E4 P+ S. M3 n
. L4 X9 h9 K( A" ?3 g7 }% b
2.2.4. Read 功能 ; `. d$ Y/ p+ c6 G; s4 `* K. w
Read 函数将存储器指定地址的数据读取到内存中的缓冲区中。
! E( K3 h$ {5 H. b1 @7 m$ _如果成功,则返回 1,如果失败,则返回 0 6 A- J5 L4 {: n* ^7 l9 {
int Read (uint32_t Address, uint32_t Size, uint16_t* buffer)
& z, X# W+ a/ V9 w' _. ]* ~. X2 O6 Z; ~6 ~, j2 b7 s
2.2.5. Verify 6 S3 M3 {% C  b0 d" Q+ c
功能当选择“边编程边验证”模式时调用验证函数。此功能检查编程的内存是否与 RAM 中定义的缓冲区相对应。
) {# n  i3 o8 T) V& d
# x0 H& z. w8 F/ Y% v) t
2.2.6. MassErase 功能
4 p5 \& H- b$ o1 A/ t5 x, LMassErase 功能会擦除全部内存。
' ]" C- g! N* \( w如果成功,则返回 1,如果失败,则返回 0。
6 B1 C8 ~( H* Dint MassErase (void)
' _  T/ X2 d7 H' k
2 t3 B: e5 i  f. Y
2.2.7. Checksum 功能
! j. {; ]) N# W. {  s$ d7 I# z描述的所有函数在操作成功时返回 1,在失败时返回 0。
1 B& g% B% O( J8 B2 `+ F6 F" V& u
+ w1 V& V; F* _3 M. c
三、利用 X-Cube-Display API 生成 Flash Loader 的方法
1 H9 ?* P, S% r: y/ f
这里参考 X-CUBE-DISPLAY\3.0.0\Projects\NUCLEO-WB55RG\Applications 目录下的 GFX01M2_FlashLoader 工程的方法,来移植一个 NUCLEO-G474+GFX01M2 的 Flash Loader,这是一个 SPI 接口的 NOR FLASH,芯片型号 MX25L6433F。6 ^& e  h6 |; C1 k: n- q% |
我们打开 STM32CubeMX,MCU 选择 STM32G474RET6,首先配置时钟,其次这里用到外设有 SPI,还需要对 SPI 进行配置,查看 X-NUCLEO-GFX01M2 和 NUCLEOSTM32G474 原理图,外部 Flash 用到了 SPI2,GPIO 引脚用到了 PB13, PB14, PB15, PA8。SPI2 相关配置参数如下图所示。
2 w' E4 |7 k! {, ]  g& @( |. k  {) n) h# @/ e* `
1.png

" D6 j# [6 D: X0 k, S0 K

* x: c' x. B1 V' L: [. _! _" i

# Q+ |1 e' n5 R. b
0 C$ Y0 {' J: _* X& N2 X
▲ 图1. SPI 参数配置

$ C8 i) Q# N/ s+ I* ?3 L9 D
) {. C+ O  z# h* D. u% l4 D

& }8 R% P) L& r! {! h! d" BSPI2 外设相关参数配置结束后,点击 X-CUBE-DISPLAY 标签,为相关的 IO 接口配置对应的引脚和外设。 ; i9 R5 T; T( ?8 T
图片: G8 j6 B' X& P
% J3 [4 M! f/ E; Q3 Y5 @

1 r" ^* V8 w- e/ J
2.png
9 L" C. g& G! o, h& z# G' [" N
: d% B, P8 z" C! D0 r$ E

3 e% |( y( {! {- i3 r/ n
▲ 图2. X-CUBE-DISPLAY IO 接口配置
4 `" K5 r; b. [. ]" d
# ?4 x* O* `! y
9 J9 n. X7 [# N) y% K; f' I
相关参数配置好后,点击 Project Manager,给工程重新命名,由于 Flash Loader 不需要 main 函数,选中配置的 “Do not generate main()”,这样生成的代码就不会有 main 函数。然后点击生成代码按钮生成代码。
% p" P( }' Q5 h$ Z$ N, w5 [) V$ }
2 ]2 V, {; J, w* _" _
0 h" @; Q- g+ f' D; K7 R
3.png
9 x# S6 x, h5 {9 L2 @+ C
# ~$ `+ D( C( W/ K
, Q+ G/ U+ d# r  U* |
▲ 图3. Project Manager 修改
6 R- `) J5 A- Q

/ d. w% Y' ?! t. y9 \+ D( N
  I" L+ N; G3 f; H6 h
生成的代码还需要添加 Dev_Inf.c、Loader_Src.c、Dev_Inf.h、Loader_Src.h,将这个代码添加到 Core 文件夹下的 Inc 和 Src 文件夹,为了方便不同编译器生成的代码能够自动加载这几个文件,复制.extSettings 文件到该工程文件夹,该文件会为工程新建一个 Loader 文件组,然后再重新生成代码。生成的代码用 VSCode 打开,在 main.c 函数中新增 MX_Init()函数,函数主要的功能是复位外设和初始化 GPIO。
/ S. {5 e' ~3 |1 L4 E
: B0 H5 N4 l# E/ I* Q( e& F! ]+ a9 A% w  b" f
4.png

' t4 g+ s8 a" [  ~
▲ 图4. 添加 MX_Init()函数
% H5 J# u" s( x* \9 {0 V
关于 Dev_Inc.c 和 Loader_Src.c 文件中的函数,这里就不再做一一说明,大家可以对照附件查看,下面主要介绍下不同编译器的工程属性配置。
* v/ b4 N  @9 k1 A9 ^
- o3 E( \& B" V' R, r8 }
3.1. STM32CubeIDE 工程配置
# e' k5 L) B2 ]$ W; C9 _STM32CubeIDE 的配置修改包括从工程中去除 startup_stm32g474retx.s,修改 Linker 文件,修改启动函数入口,添加后处理生成 stldr 文件。 * v3 M- z4 W7 p. Z
0 n! N2 C4 W  O! {  q% K( A4 Y

& l+ X+ X; E& a' l; t
5.png

( I* P6 [# m0 X2 U

, w6 O) q0 N: `4 [+ c9 c: |

& u- K: j7 q' l0 n9 ?
▲ 图5. STM32CubeIDE 中将 startup_stm32g474retx.s 从工程中去除
" \5 M; F# X/ Y& D+ f$ q

5 Q. ~* V% f( x, `

9 ?2 b5 g+ P1 d" Y2 ]- y修改 Linker 的配置,通过“Properties”打开设置页,将 Linker 文件修改为 STM32_FLASH.ld。
& y( y, Z( I' H8 L0 ]+ [  {' i. W: w9 i

; E; \9 v: [( X1 E7 a
6.png
, t6 k& U3 j8 n9 e; g
" d( [' C6 U) `' E! R

/ o0 O- W, ^. P9 A# l8 @/ U$ i- |7 F
▲ 图6. STM32CubeIDE 修改 Linker 文件
' H& L  f' K# ~$ u
/ S7 W; m5 V5 J- e. B1 l7 E  z
通过 “Settings” -> “Build Steps” 配置页中,在 “Post-build steps” 处添加指令 :cmd.exe /c copy /Y "$(BUILD_ARTIFACT)" "..\MX25L6433F_GFX01M2_STM32G4.stldr",编译后生成 stldr 文件。% Y" X! d# C7 D4 @) C) E+ R

0 ^- `5 S3 b6 N. p% N' \2 b0 Z' W  c, g8 `2 R2 R+ v  I
7.png
" t$ n5 z# @$ F& O; g6 K
▲ 图7. 在 STM32CubeIDE 中添加后处理语句
& q- R* D' k" i# a# i" F6 B0 V" @
4 a3 n# V8 v- u8 o
当这些配置好后,重新 Build 工程,这样就会产生所需要的 Flash Loader。$ z: V5 o; P2 _3 n6 x/ D

. `0 H7 U5 s8 n) R1 n$ ?
3.2. KEIL 工程配置8 e$ _/ M' {" R* D1 ^. T
与 STM32CubeIDE 配置过程类似,KEIL 的配置过程主要包括以下操作。在 Target 标签页,Arm Compiler 选择“Use default compiler version 6”,如下图所示。& e* L. ?2 K) |

3 O: j. x) g! V; ~
1 O; X. p! {" f/ _9 R) `
8.png
- K- J6 Z7 _1 ]

! w" ]: D' \' A6 C. B
" E2 u6 R) _( I) a+ {6 V* D0 A$ B
▲ 图8. 更改 Arm Complier

$ _* x! u3 Y  o  b0 X' b9 l在 startup_stm32g474xx.s 的文件属性中,去除勾选“Include in Target Build”和 “Always Build”,这样这个文件就不会被编译和包含在这个工程中。7 ^) T2 A% }7 G) X
0 p8 Q) Q6 \( n: [3 m! H
. Z$ ]7 o  t+ `5 W  R
9.png

! z4 [& k( H1 Z8 }' M+ L6 z

0 P& O+ _* p& \. Y- \# S" l  y& F& Q

1 K! D! V1 B9 g9 C  U' x; G! Y
▲ 图9. 在 KEIL 中将 startup_stm32g474retx.s 从工程中去除

2 O. X+ S% w* M2 h2 {3 D' o( f: y: A* b, K& e

# D9 k8 \$ D% ~$ A# a8 i+ {4 y在属性界面,切换到 Linker 界面,去掉“Use Memory Layout from Target Dialog”勾选,修改链接文件,将链接文件更换为 stm32_loader.sct,同时注意在 Misccontrols 添加“--paged --pagesize 0x10--diag_suppress L6305” 。
, T# N8 n# }6 u
! e& y& {, u/ T" q5 E
5 }$ ]4 z% Y" s
10.png

7 Z( b; M/ o$ m$ D/ z( c# _; A+ u) C! u
▲ 图10. KEIL 中修改链接文件
7 O  }1 t5 l2 X( W' o

5 B4 t1 M! p1 d! c, F2 h与 STM32CubeIDE 配置类似,添加后处理语句“cmd.exe /C copy /Y "!L" "..\MDK-ARM\MX25L6433F_GFX01M2_STM32G4.stldr"”。
; P/ N1 z- d5 D/ [" i. T" K" h* m, o: j8 j  E' U! H! S+ B. z

! B0 q- t4 ]/ k4 o/ S
11.png
  U! f9 U; a" @/ k0 ~( K6 y
▲ 图11. KEIL 中添加后处理语句

4 \, \) M1 {6 U) w8 `+ b

# d& E3 q4 ^2 _1 y% N4 H7 Q% f+ y

" m* i+ v7 {  {4 w这些配置好后,重新编译代码,会在 MDK-ARM 文件夹下生成 stldr 文件。3 o& T2 n, }+ S" d' _

* Z3 X% ?4 F: c" V
1 }+ ~" j3 H1 F7 x8 H6 d: ~! B
3.3. IAR 工程配置( z0 d' q, ~2 t& g
IAR 工程配置与 STM32CubeIDE 和 KEIL 的过程类似。 $ S5 ?  m+ M! U* Y0 D

  {7 f# Q/ e( V7 b" f2 m" A

' {( J! P. v3 x$ [
12.png

& k# A! n; ?  I- a
! V. d+ `" }4 ?* c% K

: k; k+ C7 ^2 K) S! z& d
▲ 图12. IAR 中将 startup_stm32g474xx.s 从工程中去除

4 S- g9 H" {! i; L- e5 ~( _$ P7 X9 ^3 v

8 |' f1 L8 _) c) H+ x3 D
13.png
8 {6 u% ?( r$ r# ?
; Y8 h+ E6 d" t6 z
▲ 图13. IAR 中修改链接文件
9 [) n: O3 ]* y9 V$ k- g
! ~$ V: X: p; d4 F+ i: o& x

) o1 J  _  J6 I! T% q
% _( E9 K( Y  a5 j+ b
14.png

% g1 |# i% G0 D, v* D
9 p/ s# G6 J3 R5 P
▲ 图14. IAR 中更改入口函数

, p' a- z; D$ n
+ i/ b0 b4 N4 d# \$ m
$ K, p  }+ O2 @) y
4 y) [4 k& f/ n6 A5 Q
15.png
+ {) V% J- C/ S) T! q$ d
' r' x( e" L' e: F, x# g+ O
▲ 图15. IAR 中添加后处理函数

/ Y, X' t+ H4 Q# z6 X
; ]  w: ]% l) u( b# h6 Q* T
% h) i3 \  w& T+ r
这些配置好后,重新编译代码,会生成 stldr 文件。
. v4 [, k3 s, W5 B1 E) x& i0 U( A5 U. c' e) _2 H6 z
四、小结* ?  O. A; P! M; B3 W
本文结合 X-Cube-DISPLAY 3.0 软件包中的示例,介绍了利用 X-CUBE-DISPLAY API 进行 Flash Loader 的方法,如果用户选择的 Flash 是 MX25L6433F 这款 Flash,那么可 以参照此方法,来快速开发自己的 Flash Loader,如果所选的 Flash 不是 MX25L6433F,也可以参照此方法,重新编写对应存储器的驱动来开发对应的 Flash Loader。
. l! N0 ^6 Y  p; w/ t* v" w  Y( d' Q6 g$ ?* a
  Z' X; l; O2 Y1 E9 @8 Z
转载自: STM32
: }, I) g  j* b4 d; ~如有侵权请联系删除
0 W6 @* }+ t. G3 ^6 {' G6 w: D+ Q
* [4 u/ Y# l  Y1 L& F2 Z* V4 `
+ l+ |+ b3 |9 z8 D# z, J" V

9 J! O' U: U0 e% S2 P% {: q
收藏 评论1 发布时间:2024-3-21 17:58

举报

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

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

所属标签

相似分享

官网相关资源

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