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

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

[复制链接]
STMCU小助手 发布时间:2024-3-21 17:58
一、引言
$ B, [+ Z. {( y6 J/ b6 F" I* 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。
3 k2 Q6 F+ ?) O$ `8 N2 [2 g8 z; _5 x6 P: \) Y  {
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 的方法。
% \3 D, y6 {, {; U; O, E+ L: z3 J  S% a
二、Flash Loader 的开发过程
4 [+ p3 I% |) A2 O* q参考 ST 在 X-CUBE-DISPLAY 3.0.0 所提供的 Flash Loader 工程,外部 Flash Loader 的开发过程主要包括以下 3 步。% D; _- ~6 V2 I4 W) R2 M
(1)更新 Dev_Inf.c 中的存储器芯片信息。
# a- R& o; P! n: q! D% n(2)重写 Loader_Src.c 中的相关接口函数。1 ~) C8 Z4 @+ U& Q1 {6 J- K  n
(3)更改输出文件名。
' d" W+ P: B" g
$ s* l1 V* T- r( C9 w项目配置好后编译整个 Flash Loader 项目,将生成一个 ELF 文件,文件的扩展名取决于所使用的编译器,Keil 的为.axf,EWARM 的为.out,STM32CubeIDE 的为.elf,通过编译后处理指令更改为 stldr 扩展名的文件,将该 stldr 文件复制到 “bin/ExternalLoader”目录下就可以被 STM32CubeProgrammer 使用了。
* [' T# K1 [# A1 u+ _; g1 C+ ^2 v
8 ?6 H. }% b' N& L! `' U
2.1. Dev_Inf.c 介绍3 t6 o2 ^' H6 D/ Y
此文件中定义的 StorageInfo 结构提供有关外部存储器的信息。用户在制作自己的 Flash Loader 时,需要根据 Flash 的参数来更新相关信息。
, U  w6 W* V5 U+ ~7 X# ^0 a& A
$ T0 F$ ]  S8 B- d: n9 C: G2 E% K) P6 e
2.2. Loader_Src.c file+ B) q/ T$ \( Z+ z
该文件包含了制作外部 Flash Loader 所需的接口函数,主要包含初始化,擦除,写入以及读出等操作。其中 Init,Write, SectorErase 这些函数是必需的,不能被省略。除了这些函数之外,您还可以重写 Read,Verify,MassErase 函数。
  @+ _3 U5 v- i; E8 ~
% H. p  e9 l- _, C' I9 j
2.2.1. Init
2 u" B! h4 |4 v. a! W, E" @Init 初始化连接到外部存储器的 GPIO 引脚以及初始化 IP 所用的时钟。. ?2 p$ ]5 u4 s$ x) W% f( I
如果成功,则返回 1,如果失败,则返回 0。
: }' e7 k2 m; K' Vint Init (void)- r! ?7 v$ v. ?0 n; u" V

: k  ^; f9 V' F* d2 P6 O
2.2.2. Write : Q! Y) T7 }! U1 g  E
Write 函数将在 RAM 定义的缓冲区写入到外部存储器。7 f3 K8 h% t" J; ?; X6 [
如果成功,则返回 1,如果失败,则返回 0。
% [) T' v; |. h! oint Write (uint32_t Address, uint32_t Size, uint8_t* buffer)! H6 y1 @$ w. _7 R: F- k
, C$ E% A  q7 D4 J
2.2.3. SectorErase
, g0 l. l4 h' n: I9 O擦除内存指定的扇区。其中起始地址等于要擦除的第一个扇区的地址,结束地址等于要擦除的结束扇区的地址。
/ V; v2 d( H0 S4 o. m7 {如果成功,则返回 1,如果失败,则返回 0。0 t$ C! ?$ Q* y7 L: V; B( ^0 ]7 y/ [# W
int SectorErase (uint32_t StartAddress, uint32_t EndAddress)( t9 }0 t1 S8 ^# B

" A+ r) W1 s( U  q: }: Y: y
2.2.4. Read 功能
( o, Z1 [% E* W- M% x5 ORead 函数将存储器指定地址的数据读取到内存中的缓冲区中。
' N% Y( w+ C, E/ D( F0 ^( R. d! H如果成功,则返回 1,如果失败,则返回 0 ) v! T- K9 \- K! I" R; I' @
int Read (uint32_t Address, uint32_t Size, uint16_t* buffer): X8 ?( I2 b9 k$ D  h  W- {

( ]- H( ~- v$ S* Q! z
2.2.5. Verify
7 C4 a( Z2 p2 L3 I% a! C功能当选择“边编程边验证”模式时调用验证函数。此功能检查编程的内存是否与 RAM 中定义的缓冲区相对应。
* F, r' }- C' l4 c  a; v* R' }3 a+ @: w
2.2.6. MassErase 功能
# z! U2 c! s$ u' jMassErase 功能会擦除全部内存。9 x( y8 `2 z& J
如果成功,则返回 1,如果失败,则返回 0。 - i+ A# J4 m9 P
int MassErase (void)( B0 h2 E7 [6 ]# g% u4 W0 d
  ]. B0 w% V* P
2.2.7. Checksum 功能
2 {: B# a$ W& J  ?) l5 m& \' l0 Z描述的所有函数在操作成功时返回 1,在失败时返回 0。
3 i' r5 o, m* S9 q" l- U7 o, e! o$ C# V  I5 B' ^+ H+ m
三、利用 X-Cube-Display API 生成 Flash Loader 的方法

+ \# f, \* U& v- H这里参考 X-CUBE-DISPLAY\3.0.0\Projects\NUCLEO-WB55RG\Applications 目录下的 GFX01M2_FlashLoader 工程的方法,来移植一个 NUCLEO-G474+GFX01M2 的 Flash Loader,这是一个 SPI 接口的 NOR FLASH,芯片型号 MX25L6433F。
% j0 U6 f% y% D) g/ }# a我们打开 STM32CubeMX,MCU 选择 STM32G474RET6,首先配置时钟,其次这里用到外设有 SPI,还需要对 SPI 进行配置,查看 X-NUCLEO-GFX01M2 和 NUCLEOSTM32G474 原理图,外部 Flash 用到了 SPI2,GPIO 引脚用到了 PB13, PB14, PB15, PA8。SPI2 相关配置参数如下图所示。
8 n1 l' J: L# c$ L3 @! ], m- I/ g
2 p: d0 K0 H* m& ~% o: H# S
1.png

4 F  u% V$ `% N

: F6 g8 v7 o7 g6 ?# o. q( w. F1 @/ _

, K" `+ p/ k* o
9 ~' U, ]! w. L, H
▲ 图1. SPI 参数配置
# T% r, c0 Q0 I5 D

! r! L) p+ \2 L

  W3 m  U+ P" r$ HSPI2 外设相关参数配置结束后,点击 X-CUBE-DISPLAY 标签,为相关的 IO 接口配置对应的引脚和外设。 " O: s2 j  @$ I# ^
图片7 G$ j+ ]% L# O2 l( k5 M

, E/ H* H8 R9 {8 u& d" E

' L- w9 M+ {, B4 B; ^4 |! ~
2.png

% r& B. r( ~! e+ A: B# A6 j7 b
5 c, x4 p, P' V% A

7 U& F$ S. x; D& |) I
▲ 图2. X-CUBE-DISPLAY IO 接口配置

; {' A  m# o" M. O& r5 g
5 Z% ?- Y8 Z, f( ]7 l. [* P
; _7 d! P8 l: N' O6 |8 _+ p
相关参数配置好后,点击 Project Manager,给工程重新命名,由于 Flash Loader 不需要 main 函数,选中配置的 “Do not generate main()”,这样生成的代码就不会有 main 函数。然后点击生成代码按钮生成代码。
3 ^- _# H! r) I; z/ l( s' w* z6 D, _: B5 R" U" {

8 q' s% A& t" b
3.png
, d9 g( {% ^; \5 f2 H% y

0 M7 B- n# ]3 L
) I3 [" f% h2 M) x
▲ 图3. Project Manager 修改

/ C) P& L  D7 `, u4 w4 g) u5 P$ H/ r8 O8 e$ l/ b+ H3 W

' R8 `: s$ R  J2 w生成的代码还需要添加 Dev_Inf.c、Loader_Src.c、Dev_Inf.h、Loader_Src.h,将这个代码添加到 Core 文件夹下的 Inc 和 Src 文件夹,为了方便不同编译器生成的代码能够自动加载这几个文件,复制.extSettings 文件到该工程文件夹,该文件会为工程新建一个 Loader 文件组,然后再重新生成代码。生成的代码用 VSCode 打开,在 main.c 函数中新增 MX_Init()函数,函数主要的功能是复位外设和初始化 GPIO。$ A8 X) V  D! I2 |% i) I: @% A4 ^
  J/ o( ?* {- y) ?0 l+ O( @
6 u  C# n' L) Z+ H- T
4.png

4 a' J: e) t  E4 z* K- d
▲ 图4. 添加 MX_Init()函数
# s5 j* ?* r$ a7 L. n
关于 Dev_Inc.c 和 Loader_Src.c 文件中的函数,这里就不再做一一说明,大家可以对照附件查看,下面主要介绍下不同编译器的工程属性配置。
6 X6 o) j. W" p/ W/ W; s. }( q3 V, G  \1 B
3.1. STM32CubeIDE 工程配置
8 S# D8 ?) A/ H  E. }2 vSTM32CubeIDE 的配置修改包括从工程中去除 startup_stm32g474retx.s,修改 Linker 文件,修改启动函数入口,添加后处理生成 stldr 文件。
% `% U1 N7 s* `0 s
* `' A# N6 {* s

5 l' o2 {' \8 Y$ }+ h
5.png

8 y+ E  J  ^7 S

0 z* E! C, n$ C
$ a2 ^  m! k. s- v
▲ 图5. STM32CubeIDE 中将 startup_stm32g474retx.s 从工程中去除
2 a1 l  ^" g' J6 F2 R& ?
1 U8 W2 k  C( L1 a6 F' S+ S# ~
+ K& R3 w' y) O+ }% \' Q+ B3 J! z
修改 Linker 的配置,通过“Properties”打开设置页,将 Linker 文件修改为 STM32_FLASH.ld。
+ n( M+ m6 m9 c3 T" Q5 r4 `+ _% K0 G9 _" ?

3 M' O5 i6 q1 S7 W- p! {. q/ V% b
6.png

8 p; V; k* v  U" K) u- ]# V

* i: S' S0 ^2 w+ I' ^

$ f3 @/ v/ h5 D0 x
▲ 图6. STM32CubeIDE 修改 Linker 文件

5 L% i# \8 N4 A8 j0 z9 {. \# n' [1 l9 x4 u" p
通过 “Settings” -> “Build Steps” 配置页中,在 “Post-build steps” 处添加指令 :cmd.exe /c copy /Y "$(BUILD_ARTIFACT)" "..\MX25L6433F_GFX01M2_STM32G4.stldr",编译后生成 stldr 文件。8 a8 m+ S$ F) V! n& S

6 {, K8 M% Y7 {( Q8 u
9 H) S& I. s, P( C  b
7.png

& a) [+ R: M9 e9 J
▲ 图7. 在 STM32CubeIDE 中添加后处理语句
3 e0 g$ N+ \$ C; O  J% I8 {! D! x

, t* v7 z, o: p7 D9 \* r& q当这些配置好后,重新 Build 工程,这样就会产生所需要的 Flash Loader。4 s+ v. t" |) ?1 P( o# [
  R) {! f6 |# h8 i# ]) S
3.2. KEIL 工程配置& t3 Q2 n5 a( l! B
与 STM32CubeIDE 配置过程类似,KEIL 的配置过程主要包括以下操作。在 Target 标签页,Arm Compiler 选择“Use default compiler version 6”,如下图所示。
* S" [1 i' ]$ X/ }! B$ j3 e+ `. C! }0 c" w  }& a
- b, _1 l3 m& B0 ]# _/ x7 L/ ~
8.png
) ~1 S" i9 R2 S' |
! k5 e# a, K, Q! @" F6 n3 Z3 p
( Z  |, |1 A5 K% E" q4 M0 l0 `" l
▲ 图8. 更改 Arm Complier
1 z" D: }1 @. G3 {
在 startup_stm32g474xx.s 的文件属性中,去除勾选“Include in Target Build”和 “Always Build”,这样这个文件就不会被编译和包含在这个工程中。' Q9 i. N! E6 k) L& }  D

! D1 Z; e2 j1 `) a2 f5 w7 G

$ u$ n4 ~$ J- K. m: ^) \8 _+ m
9.png

" x% g+ @2 q  T  V/ @$ d

. v# G' B7 K! h
) ?1 n! \3 d+ e$ b! ~
▲ 图9. 在 KEIL 中将 startup_stm32g474retx.s 从工程中去除
9 W; ~- ~& r1 J) D3 o

) ^6 E1 T7 O  T' r9 Y
  H7 J% M% Q- c" f7 X/ R& Y
在属性界面,切换到 Linker 界面,去掉“Use Memory Layout from Target Dialog”勾选,修改链接文件,将链接文件更换为 stm32_loader.sct,同时注意在 Misccontrols 添加“--paged --pagesize 0x10--diag_suppress L6305” 。
4 t7 U) h1 S4 [% O+ C$ F- J3 Q1 ~5 Y. h' O
  K( U) n) Y" U+ u5 d/ n
10.png
$ p% {$ v  H& z/ L. j5 \
▲ 图10. KEIL 中修改链接文件
6 n$ A6 g8 j9 y$ q/ G

9 s/ A* V, j, e+ Z+ e2 {" a- w. x与 STM32CubeIDE 配置类似,添加后处理语句“cmd.exe /C copy /Y "!L" "..\MDK-ARM\MX25L6433F_GFX01M2_STM32G4.stldr"”。) j" e; @) ?% H! `1 O

8 Z2 J+ y8 N4 y

) o$ g* Q4 x% g; q% j
11.png

/ s) F  |/ C  ^( ?
▲ 图11. KEIL 中添加后处理语句

6 ?1 E6 s8 s# P4 T$ `
* Y% h) @- x3 m* g9 y! \, E

9 P+ H* \4 Y/ ?这些配置好后,重新编译代码,会在 MDK-ARM 文件夹下生成 stldr 文件。
" `' g3 G% M: a& k2 ~9 [# L6 N2 w4 O  V8 p6 G% J

8 p- ~) f: H# Z! {3.3. IAR 工程配置! j! E& s2 d9 W2 `% J5 M) _
IAR 工程配置与 STM32CubeIDE 和 KEIL 的过程类似。
1 [, @1 R. B- y! e1 h) N6 S, b: a  f( c4 l& ?2 D
+ L8 z0 _/ \% F
12.png
: L1 }  r8 a$ i: B
! K9 Y. ]* |) V+ d1 Z4 v% j# W

; v9 q" b) W' K6 \5 I
▲ 图12. IAR 中将 startup_stm32g474xx.s 从工程中去除

, R! w. X: H& |! _( r* V8 X: F! e' _. P8 t2 L3 t( L2 N4 R. a
; w9 ^( x4 ]. {) C6 {
13.png
3 A. \* m- o# |( j; E4 X2 A

! _* H" c( ?3 @3 |& V, H
▲ 图13. IAR 中修改链接文件

/ w* B+ d/ b/ t- J

/ M5 ?* C; v0 o0 J4 ]
0 j1 \* j# w- B$ M

! F& d2 o  _' O' ^3 @9 S
14.png

8 D. r6 F" I( R! M( l7 _& m9 Y& W# O" x9 o, ~% s
▲ 图14. IAR 中更改入口函数

/ s2 b- C# w* w3 p8 D, h3 h
$ n) u6 p2 r$ A/ `( x6 V7 ?
% n# q: y; @* r) S1 v" L
* {$ ~' u- w% W6 o/ F0 F6 t
15.png

3 ]6 X( ~7 f) B+ v* N
: V( s9 f- {6 x5 V; _- }- }! P' }
▲ 图15. IAR 中添加后处理函数
, F7 ]! K/ ?% q* H
; j: |& @% f1 ~  n- Y$ g

) j$ ]- h7 Z8 h
这些配置好后,重新编译代码,会生成 stldr 文件。* R" d. V7 R: Z: L+ t! R0 j

! O; G9 J4 r* w3 C% g) C8 ^
四、小结
7 E% D. w7 r) d% w0 {- z本文结合 X-Cube-DISPLAY 3.0 软件包中的示例,介绍了利用 X-CUBE-DISPLAY API 进行 Flash Loader 的方法,如果用户选择的 Flash 是 MX25L6433F 这款 Flash,那么可 以参照此方法,来快速开发自己的 Flash Loader,如果所选的 Flash 不是 MX25L6433F,也可以参照此方法,重新编写对应存储器的驱动来开发对应的 Flash Loader。4 I  Q( t8 N3 c+ }

% [3 E1 }( L( s
6 v1 k# W$ D2 @8 ]- @, X: _
转载自: STM32
2 u: {& E$ j. B; J; F8 `. I如有侵权请联系删除) z! M: ?( M' @/ a: Z+ l5 ^( Q
' I  W$ W& K* m( D

. k: Z7 p  u- u. D9 c* v/ S+ ~' }. M8 U( p" f' E7 s
收藏 评论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 手机版