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

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

[复制链接]
STMCU小助手 发布时间:2024-3-21 17:58
一、引言* _- \8 F1 A" J) X
在嵌入式应用系统中,越来越多的应用需要扩展外部 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。
0 {1 J5 y' p2 h) g' `# J
% N7 D/ X' ^- a( Z6 oST 的 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 的方法。 3 E  [* A6 d) ~% e! ]- L' Z

! C2 n# H$ e# ?3 Q
二、Flash Loader 的开发过程
4 f, [: [5 K( s- B6 v' y参考 ST 在 X-CUBE-DISPLAY 3.0.0 所提供的 Flash Loader 工程,外部 Flash Loader 的开发过程主要包括以下 3 步。
  d/ _' P% i2 M. B(1)更新 Dev_Inf.c 中的存储器芯片信息。
# C) D9 q* d$ }- Q; J* m' ~  V+ u(2)重写 Loader_Src.c 中的相关接口函数。7 G5 M+ j) c9 e
(3)更改输出文件名。
. v& Q2 k! e/ ^1 L2 r5 f& i, L7 F: }7 o
项目配置好后编译整个 Flash Loader 项目,将生成一个 ELF 文件,文件的扩展名取决于所使用的编译器,Keil 的为.axf,EWARM 的为.out,STM32CubeIDE 的为.elf,通过编译后处理指令更改为 stldr 扩展名的文件,将该 stldr 文件复制到 “bin/ExternalLoader”目录下就可以被 STM32CubeProgrammer 使用了。
$ Q$ @1 N6 M) h2 ~# M, L2 N6 N8 n4 @) D, M8 G
2.1. Dev_Inf.c 介绍
; @0 s! P3 d: E9 c; R此文件中定义的 StorageInfo 结构提供有关外部存储器的信息。用户在制作自己的 Flash Loader 时,需要根据 Flash 的参数来更新相关信息。% A; X& N3 N0 X1 A: d
" g; Z0 Z# J! @5 R7 v( n
2.2. Loader_Src.c file
+ R) I4 y9 |7 b8 g' Q该文件包含了制作外部 Flash Loader 所需的接口函数,主要包含初始化,擦除,写入以及读出等操作。其中 Init,Write, SectorErase 这些函数是必需的,不能被省略。除了这些函数之外,您还可以重写 Read,Verify,MassErase 函数。8 g  u3 ^& I2 R( h

( N/ g8 P7 t2 T8 Y7 e, G! G6 i
2.2.1. Init
1 n; @4 s  W( @: m; sInit 初始化连接到外部存储器的 GPIO 引脚以及初始化 IP 所用的时钟。
, Y/ \9 _' L4 j! B9 c6 f) S如果成功,则返回 1,如果失败,则返回 0。
7 q* p. e( K4 uint Init (void)
' U+ H0 f' f6 r1 g& [
+ O' J1 f' a: |: f. V) x& x
2.2.2. Write - x; z/ {- V$ t4 ?% [3 T
Write 函数将在 RAM 定义的缓冲区写入到外部存储器。
, M/ M! S9 t4 b! Y如果成功,则返回 1,如果失败,则返回 0。 5 M7 L, l1 K2 u$ w% C: s. s! e
int Write (uint32_t Address, uint32_t Size, uint8_t* buffer)& @/ C* j1 o- ], h

6 D# H/ n/ @8 s  X
2.2.3. SectorErase
8 W+ h5 _: @6 B8 G擦除内存指定的扇区。其中起始地址等于要擦除的第一个扇区的地址,结束地址等于要擦除的结束扇区的地址。, U  ?6 T$ ?: ^" \5 t6 j
如果成功,则返回 1,如果失败,则返回 0。
; O, Z5 j- B/ n; E/ R# k6 b# n* {int SectorErase (uint32_t StartAddress, uint32_t EndAddress)
* r3 L% J: K. ]8 K; B/ D
/ c* P. E7 o4 _8 [, O! J9 \
2.2.4. Read 功能 3 N$ u3 E  l" v
Read 函数将存储器指定地址的数据读取到内存中的缓冲区中。
" K7 m3 m4 b- H: J如果成功,则返回 1,如果失败,则返回 0 3 j$ f0 s; K  |- Z+ c3 G2 @) d9 J* s, }
int Read (uint32_t Address, uint32_t Size, uint16_t* buffer)
, H  J! Z* P4 |) |6 U! f% ]2 X: }5 B+ ?* d
2.2.5. Verify 3 b" D; q5 P5 J! P* Z
功能当选择“边编程边验证”模式时调用验证函数。此功能检查编程的内存是否与 RAM 中定义的缓冲区相对应。
  \; F% p  i' U- a! M+ K% {. G5 g( l2 ]" s7 N& b1 Q: M3 a* p
2.2.6. MassErase 功能 # S/ M5 }3 n  r) f3 w
MassErase 功能会擦除全部内存。. a% y! r- I/ g( ^. U& L& X
如果成功,则返回 1,如果失败,则返回 0。
5 s3 ?1 t# J9 i9 ?7 ^int MassErase (void)
/ e  I* @7 J" }. g# F1 g* ^: Y6 P  ]! ~! ]' A$ ^8 i. H
2.2.7. Checksum 功能
/ N( D5 O0 l) h) f5 e; d/ L描述的所有函数在操作成功时返回 1,在失败时返回 0。' B+ B" v' K  v" ]7 U0 f
7 U8 [7 Y9 ]; p# ~* D& h$ ?
三、利用 X-Cube-Display API 生成 Flash Loader 的方法

, G) x( R9 y: z+ [  F这里参考 X-CUBE-DISPLAY\3.0.0\Projects\NUCLEO-WB55RG\Applications 目录下的 GFX01M2_FlashLoader 工程的方法,来移植一个 NUCLEO-G474+GFX01M2 的 Flash Loader,这是一个 SPI 接口的 NOR FLASH,芯片型号 MX25L6433F。
8 n# F' V) n. S5 u3 T我们打开 STM32CubeMX,MCU 选择 STM32G474RET6,首先配置时钟,其次这里用到外设有 SPI,还需要对 SPI 进行配置,查看 X-NUCLEO-GFX01M2 和 NUCLEOSTM32G474 原理图,外部 Flash 用到了 SPI2,GPIO 引脚用到了 PB13, PB14, PB15, PA8。SPI2 相关配置参数如下图所示。9 P0 x. P, o3 T5 n

" ~* `$ a6 p8 d
1.png

$ Z/ T2 E5 R/ d) K0 q
# d( a5 e9 e% C$ }5 p; u

0 _% c! N' S5 I/ @3 r4 i9 T' J
9 n! f5 J1 J1 g1 M  O: H, v: A) P- z) f
▲ 图1. SPI 参数配置

% @4 i) ?2 m7 U2 J2 Y
( w& F, o7 o, ]; p& t8 B
) E, q, Y. V; F
SPI2 外设相关参数配置结束后,点击 X-CUBE-DISPLAY 标签,为相关的 IO 接口配置对应的引脚和外设。
3 p, z7 L$ q4 l图片  O* Y. f1 Q4 N" z

# y' ~0 I& J3 Q9 j: L

" P% N9 Y; N' ]$ P+ E
2.png

: f1 u9 P( L) z2 }, m1 \$ A! N

9 e1 L) Q" I; F* F  ~+ O

7 g$ b3 W' L& ~$ [
▲ 图2. X-CUBE-DISPLAY IO 接口配置

- j3 d5 m2 X& I) q/ D# e. a# o; k: ~5 s5 ]! `( V2 A( n5 x3 _

  p: K1 [3 f6 ~0 D: O相关参数配置好后,点击 Project Manager,给工程重新命名,由于 Flash Loader 不需要 main 函数,选中配置的 “Do not generate main()”,这样生成的代码就不会有 main 函数。然后点击生成代码按钮生成代码。
0 @; T6 e9 c* u7 d5 E9 h: r  m, J6 K/ }- p% M8 z

2 a9 Q' @- b' d, K" w0 Y  {
3.png
3 L1 x  X' P- F' o" e

: H7 s+ T  i& D1 X" S3 f
7 a# d- I* x. U$ a; a
▲ 图3. Project Manager 修改
" O: C$ S9 _% N0 X

8 b  N: s, {1 T0 ~: }

" V6 |3 b6 H- R1 N! }5 x生成的代码还需要添加 Dev_Inf.c、Loader_Src.c、Dev_Inf.h、Loader_Src.h,将这个代码添加到 Core 文件夹下的 Inc 和 Src 文件夹,为了方便不同编译器生成的代码能够自动加载这几个文件,复制.extSettings 文件到该工程文件夹,该文件会为工程新建一个 Loader 文件组,然后再重新生成代码。生成的代码用 VSCode 打开,在 main.c 函数中新增 MX_Init()函数,函数主要的功能是复位外设和初始化 GPIO。
" p( I1 h- _" ?3 e$ L& n7 H4 ]3 i1 o: j
) K; U/ r) a6 |4 H! K
4.png

8 a# U# c' y! s, f
▲ 图4. 添加 MX_Init()函数
! J3 s) k( Q  m' W5 S8 M2 K
关于 Dev_Inc.c 和 Loader_Src.c 文件中的函数,这里就不再做一一说明,大家可以对照附件查看,下面主要介绍下不同编译器的工程属性配置。: n% {# i3 M& |2 Q

) H" i; i' p" M. M7 B  J% O
3.1. STM32CubeIDE 工程配置   s, t3 i. m0 R& U0 L
STM32CubeIDE 的配置修改包括从工程中去除 startup_stm32g474retx.s,修改 Linker 文件,修改启动函数入口,添加后处理生成 stldr 文件。
7 K( s) i* y$ v* `' C6 `6 ]% l4 \: P9 M; S$ |4 j/ e. k

$ t! H. F0 z# ]$ w9 J
5.png
/ ^  s' R. H& u/ J" F; Z8 v

6 K% n% w/ v" @3 z* F% I
+ p$ Q4 ?+ N# F  Q5 J# F
▲ 图5. STM32CubeIDE 中将 startup_stm32g474retx.s 从工程中去除

' y( }1 U+ G2 u& ?  k" J8 e# g! D1 J; q& ?! X
0 @2 B, _; H# Z( h
修改 Linker 的配置,通过“Properties”打开设置页,将 Linker 文件修改为 STM32_FLASH.ld。/ }8 Q8 G" d: u& u$ n) R

' {( |+ F4 a5 }! k( z% |. G

# ^5 T( v4 b6 Z: g: H8 d5 F
6.png
- f. _0 a* @8 l' O2 u* x4 A. B

/ x6 n5 c  W4 Y& M: ^

& f- s6 p5 k5 d* k4 W; L$ U9 d
▲ 图6. STM32CubeIDE 修改 Linker 文件
% E5 }' i6 s! \9 C3 e7 h
' H8 c: K% D: T) m' z5 v
通过 “Settings” -> “Build Steps” 配置页中,在 “Post-build steps” 处添加指令 :cmd.exe /c copy /Y "$(BUILD_ARTIFACT)" "..\MX25L6433F_GFX01M2_STM32G4.stldr",编译后生成 stldr 文件。
6 o3 V9 ?6 D" D& [, ^0 z/ {5 u6 s' Y* G

& X1 \5 r. e8 [' g1 a8 Z& D' u
7.png

% L5 h4 D+ Q( M: Q. T0 h$ K  Q, s
▲ 图7. 在 STM32CubeIDE 中添加后处理语句

4 Q# ], S9 F# r  F; H/ G% h
- e1 z. `2 y' Y6 \. n, X6 T) s$ \% v
当这些配置好后,重新 Build 工程,这样就会产生所需要的 Flash Loader。
1 t* i' H/ B( f$ T/ p, @2 {7 }4 t3 y
3.2. KEIL 工程配置
/ p+ n9 Q- k) q+ S! L6 R与 STM32CubeIDE 配置过程类似,KEIL 的配置过程主要包括以下操作。在 Target 标签页,Arm Compiler 选择“Use default compiler version 6”,如下图所示。0 [% a! m- s" e+ c
# \4 w* }' k/ l5 k! W, e
9 e# h$ E" |) p1 n  a. ]! ]
8.png
' e9 P5 g5 M" R- M6 V' y; C, L

' B% H. ?/ H, i
3 A$ j8 h2 J. \8 N/ @* K
▲ 图8. 更改 Arm Complier
5 v: L! z' s) i& p$ ~2 a4 v
在 startup_stm32g474xx.s 的文件属性中,去除勾选“Include in Target Build”和 “Always Build”,这样这个文件就不会被编译和包含在这个工程中。
( K) y6 |* S/ a  Y
2 m- s( q/ u7 B$ u; ~3 A* [
* b8 {- C4 b  M
9.png
, F) O. s7 e" T$ R

7 d/ `/ h: N; x) ~" s: m7 ]' h
2 b0 n- z4 H3 ~* F, h* s
▲ 图9. 在 KEIL 中将 startup_stm32g474retx.s 从工程中去除

# |9 u9 u$ L& j7 u) B  u+ }3 [- y% d+ \& P2 y
; t- A7 y0 j( C
在属性界面,切换到 Linker 界面,去掉“Use Memory Layout from Target Dialog”勾选,修改链接文件,将链接文件更换为 stm32_loader.sct,同时注意在 Misccontrols 添加“--paged --pagesize 0x10--diag_suppress L6305” 。
# T$ K6 G$ f1 l! S% N# C1 A% w( C: @; Y9 m' @, E

( S+ l! v+ F5 z# P. X
10.png

3 O# O, R2 l6 m: `! u5 x4 p
▲ 图10. KEIL 中修改链接文件
1 q4 C% O; ?  m, J( }# D4 J2 i3 [

. e" \# S- U! F/ m- e3 W- w与 STM32CubeIDE 配置类似,添加后处理语句“cmd.exe /C copy /Y "!L" "..\MDK-ARM\MX25L6433F_GFX01M2_STM32G4.stldr"”。* D; ~" S  x+ q* M) }3 i. K
$ O6 T; F9 ~; D# y, n" O) t* e

4 K7 ~+ A2 E9 e  o5 }) c6 B
11.png

/ N5 R* K7 U/ s  z4 P8 B
▲ 图11. KEIL 中添加后处理语句

1 s* b* _7 q8 a5 L) I& S/ S  n: h+ C  X

/ X' \1 f8 t( [+ ~, r5 w) ?
# b: v7 ]1 [5 s6 [( b+ u
这些配置好后,重新编译代码,会在 MDK-ARM 文件夹下生成 stldr 文件。2 L6 |) ]( f4 F2 M4 j3 u% i

$ Z4 t; M, O1 K% |4 A

' g* l  ?% d9 g" {, b3.3. IAR 工程配置  l- h4 q4 H8 j, R* Y1 r0 `
IAR 工程配置与 STM32CubeIDE 和 KEIL 的过程类似。
  k- ?" c; u* m3 J+ C
! l0 ]  ~# U  y% s
0 t. Z! h2 B5 L5 q" M1 H( h) y
12.png

/ ]$ F( Z9 e, X' B

- e, f$ d0 ]! V" n& m; s6 m5 b6 R

3 A2 x* B" E, R$ z0 I
▲ 图12. IAR 中将 startup_stm32g474xx.s 从工程中去除

) K: t5 c& o8 M; n/ u0 F+ w0 s/ j
: M& P8 h0 }3 N6 d) l% A2 t! s4 u, _) M" ^
13.png

% I4 B4 F+ h) r* B3 f" f9 w6 N+ r/ H5 e6 X5 @: L! s
▲ 图13. IAR 中修改链接文件
  V5 r! _& D+ v. M. W0 R

( Z) X9 V# n- H- t) i+ V
- a. B0 c" n" `$ k, t6 o0 t
3 P1 ]# _. u. M( @! L" u* z
14.png
* M: ^- K1 Q3 h: S1 K7 V
) u4 R4 r. }+ I+ o$ b: S
▲ 图14. IAR 中更改入口函数

2 h' f- ]# F$ j8 j# W8 [7 U
$ q: X" I8 h' |( n0 J3 L7 g
  }/ |% X; x0 |& G- r
3 Z+ O0 @" p6 m8 |& e9 k
15.png
3 J7 g. H: Y' U$ \
4 w9 c0 H/ r5 j: Q# W
▲ 图15. IAR 中添加后处理函数

. k$ V' W8 c6 N6 H" j

. E' @/ P  ~9 p, u8 I
1 |- X! z) e5 \- z
这些配置好后,重新编译代码,会生成 stldr 文件。
6 }! a7 y- s4 b; l
5 \" D5 _$ a2 J+ e# L
四、小结# t! S$ y% r+ D; s) I6 W
本文结合 X-Cube-DISPLAY 3.0 软件包中的示例,介绍了利用 X-CUBE-DISPLAY API 进行 Flash Loader 的方法,如果用户选择的 Flash 是 MX25L6433F 这款 Flash,那么可 以参照此方法,来快速开发自己的 Flash Loader,如果所选的 Flash 不是 MX25L6433F,也可以参照此方法,重新编写对应存储器的驱动来开发对应的 Flash Loader。* [% d2 b, T& c

- P7 P* }0 l4 b1 [
1 @. E* E( ^0 S& |9 f! N$ B- r
转载自: STM32: F- f$ t  w3 I2 Q+ Z/ Z
如有侵权请联系删除
: k2 ]/ M9 a) Q/ W
) d* i! X$ r+ W) w. r
! a" h. E9 F1 q/ v! a7 Q" j: \
4 u# b6 s9 u( U3 T0 k  F
收藏 评论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 手机版