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

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

[复制链接]
STMCU小助手 发布时间:2024-3-21 17:58
一、引言
# I& M: N( _' ]7 d/ I! |在嵌入式应用系统中,越来越多的应用需要扩展外部 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。8 E0 x9 w3 p5 r5 B; O% h5 ~

5 e7 E5 e1 ]4 ~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 的方法。 ( C. Z5 O# e" S- P# U
! v; Z8 K0 O* c! Q
二、Flash Loader 的开发过程! @' @4 x* l0 u1 w" U+ E5 `
参考 ST 在 X-CUBE-DISPLAY 3.0.0 所提供的 Flash Loader 工程,外部 Flash Loader 的开发过程主要包括以下 3 步。
3 g- A1 A. S4 g) a: A- c(1)更新 Dev_Inf.c 中的存储器芯片信息。
" l. Y. D( I9 R& V: B' c(2)重写 Loader_Src.c 中的相关接口函数。
; y8 j7 v7 [0 Z# ?! w5 j& f(3)更改输出文件名。* u# K7 f* {$ Q/ p
4 d6 |. {$ D/ v9 R: P
项目配置好后编译整个 Flash Loader 项目,将生成一个 ELF 文件,文件的扩展名取决于所使用的编译器,Keil 的为.axf,EWARM 的为.out,STM32CubeIDE 的为.elf,通过编译后处理指令更改为 stldr 扩展名的文件,将该 stldr 文件复制到 “bin/ExternalLoader”目录下就可以被 STM32CubeProgrammer 使用了。
7 r$ ~( w3 D  E$ L8 z, w5 z4 C$ R8 m9 @0 O, x6 F
2.1. Dev_Inf.c 介绍
" e# X1 ^7 X5 q5 r& ~此文件中定义的 StorageInfo 结构提供有关外部存储器的信息。用户在制作自己的 Flash Loader 时,需要根据 Flash 的参数来更新相关信息。
8 g* z. a) T4 R4 `; d9 J  T; @) ^  {5 C
2.2. Loader_Src.c file
5 L7 h+ p, F& X6 ?该文件包含了制作外部 Flash Loader 所需的接口函数,主要包含初始化,擦除,写入以及读出等操作。其中 Init,Write, SectorErase 这些函数是必需的,不能被省略。除了这些函数之外,您还可以重写 Read,Verify,MassErase 函数。
" [' G3 }; X$ _2 F: u5 f$ g% M2 ^* M: n
2.2.1. Init
+ D9 P* y, c- i: HInit 初始化连接到外部存储器的 GPIO 引脚以及初始化 IP 所用的时钟。; d  S3 U) D( C8 C/ ^
如果成功,则返回 1,如果失败,则返回 0。 * T+ K$ ]$ O7 ?! a4 o. W
int Init (void). n8 O+ `* x4 y. S
+ l3 y- J4 v1 z9 f1 O
2.2.2. Write ( |& v/ H* G3 C
Write 函数将在 RAM 定义的缓冲区写入到外部存储器。
6 i% |1 [. i% _! f9 p, E如果成功,则返回 1,如果失败,则返回 0。 1 S5 k9 T) {7 I. M
int Write (uint32_t Address, uint32_t Size, uint8_t* buffer)
" G) ?- {1 ^  U' `- T. i
5 {9 s! c4 }' y
2.2.3. SectorErase
. D  W* M" h0 l; V4 B8 l# C擦除内存指定的扇区。其中起始地址等于要擦除的第一个扇区的地址,结束地址等于要擦除的结束扇区的地址。
/ L- B/ I" S( C6 I% j- L5 o2 u如果成功,则返回 1,如果失败,则返回 0。
5 {8 v9 G0 ^& l: Oint SectorErase (uint32_t StartAddress, uint32_t EndAddress)
0 v  Y7 q$ q& J2 v3 q) A4 u* F+ T% h7 P& Y* k6 D7 E) s' _# U
2.2.4. Read 功能
$ i& [$ F  o2 q2 ~# u9 W2 hRead 函数将存储器指定地址的数据读取到内存中的缓冲区中。
# l/ ?+ N- `  J如果成功,则返回 1,如果失败,则返回 0 * K" X$ t& y0 q" L# v- w/ R6 R  E
int Read (uint32_t Address, uint32_t Size, uint16_t* buffer), ]8 j# U' M& b: S6 w; ~& U- C
. v6 Q% a& ~! C- u8 c
2.2.5. Verify ) F" ]4 h! n4 {
功能当选择“边编程边验证”模式时调用验证函数。此功能检查编程的内存是否与 RAM 中定义的缓冲区相对应。# m1 y' B% b0 N6 F7 R

  o1 y4 k8 |3 e- F6 Y
2.2.6. MassErase 功能
0 c# F: }, j6 I: W# b8 S( }: VMassErase 功能会擦除全部内存。" N- B/ ^6 Z9 l8 x+ e7 S( ^. ~* ~
如果成功,则返回 1,如果失败,则返回 0。
9 d" r8 m- }# j7 ~' eint MassErase (void)5 [# ~, G6 e4 o5 `9 C4 a
+ }) {8 i# W, b2 V, x; E' c" u
2.2.7. Checksum 功能
; y: @8 D4 v( `0 b描述的所有函数在操作成功时返回 1,在失败时返回 0。( z; h. p3 |7 T# c* E$ @

$ i) N+ p% U+ y9 n9 L# ?& [  u
三、利用 X-Cube-Display API 生成 Flash Loader 的方法

6 j# u! S$ X" S; ]) X) p这里参考 X-CUBE-DISPLAY\3.0.0\Projects\NUCLEO-WB55RG\Applications 目录下的 GFX01M2_FlashLoader 工程的方法,来移植一个 NUCLEO-G474+GFX01M2 的 Flash Loader,这是一个 SPI 接口的 NOR FLASH,芯片型号 MX25L6433F。( z5 g1 z% g( l' P* j
我们打开 STM32CubeMX,MCU 选择 STM32G474RET6,首先配置时钟,其次这里用到外设有 SPI,还需要对 SPI 进行配置,查看 X-NUCLEO-GFX01M2 和 NUCLEOSTM32G474 原理图,外部 Flash 用到了 SPI2,GPIO 引脚用到了 PB13, PB14, PB15, PA8。SPI2 相关配置参数如下图所示。
+ D5 q! K+ @3 r& L: Q) u- g2 Z$ f6 o: Y3 p. x, _* G: O( M
1.png

8 E+ f. f: l- G; c
% F# D7 m9 B: z/ t0 [! W7 N- Z

( N4 k  n9 O# n. A. Z

% Y! ~+ F4 Y0 F, ?$ y0 i
▲ 图1. SPI 参数配置
4 c6 T  z2 w' h" V1 Q
- A. ?- M+ A$ }# L4 V; k

0 x+ K' Q+ x0 M" sSPI2 外设相关参数配置结束后,点击 X-CUBE-DISPLAY 标签,为相关的 IO 接口配置对应的引脚和外设。
/ J; K, F6 ]3 L  P0 C$ s: J图片
" ]9 H- A: l2 m; F! M. J5 i
4 t) G) {$ c/ F% W: _8 S% y

- h9 x! }0 S( D* ^
2.png

$ y1 W" b* u& z# g
- {6 U. [0 @8 k
8 @0 C0 o+ I0 m/ `+ V, t
▲ 图2. X-CUBE-DISPLAY IO 接口配置
" t$ r. T/ Y1 s( {4 @
. o- c) F& @2 s4 c1 H7 b4 L( b
& w1 |2 \  j& K3 p6 X" O; }6 Q% }: e
相关参数配置好后,点击 Project Manager,给工程重新命名,由于 Flash Loader 不需要 main 函数,选中配置的 “Do not generate main()”,这样生成的代码就不会有 main 函数。然后点击生成代码按钮生成代码。
* \% L/ m9 H/ i0 h3 U3 `2 A# l8 _* i
; V+ o* H+ G4 a0 s) M, T

$ E" _" C* Z+ z5 W+ q
3.png
* S5 s& L+ L* o, P
4 o& L4 V/ S& A* B% H! w* D# C; T
! d& m5 m- ~( o/ i1 H4 n! S
▲ 图3. Project Manager 修改
* W1 e( V& `* e
/ K! i) O+ b; X
1 A4 p: }$ B2 u* _
生成的代码还需要添加 Dev_Inf.c、Loader_Src.c、Dev_Inf.h、Loader_Src.h,将这个代码添加到 Core 文件夹下的 Inc 和 Src 文件夹,为了方便不同编译器生成的代码能够自动加载这几个文件,复制.extSettings 文件到该工程文件夹,该文件会为工程新建一个 Loader 文件组,然后再重新生成代码。生成的代码用 VSCode 打开,在 main.c 函数中新增 MX_Init()函数,函数主要的功能是复位外设和初始化 GPIO。
* i# d! L. y( o% b9 |/ g8 c9 n7 ~* l& Y- h6 Y  r# c' f3 E# p

4 g+ q# `, D$ a; H
4.png
0 M7 ~2 B# ?; `; ?. U" G$ O0 P
▲ 图4. 添加 MX_Init()函数
! K3 f" I! m0 p
关于 Dev_Inc.c 和 Loader_Src.c 文件中的函数,这里就不再做一一说明,大家可以对照附件查看,下面主要介绍下不同编译器的工程属性配置。! A( c& G" u) S; P* R

% u/ h2 p# s' n" S2 d; Z% l2 o9 s
3.1. STM32CubeIDE 工程配置
# x8 w$ L; g) o* g- ]* @STM32CubeIDE 的配置修改包括从工程中去除 startup_stm32g474retx.s,修改 Linker 文件,修改启动函数入口,添加后处理生成 stldr 文件。 2 f2 v! Q; I! W2 k+ R1 _

  ^& Z$ P+ y; y2 V/ [1 ~: C0 }# _2 H
+ X4 Q# [6 d. Z
5.png
, S4 L8 V$ c  u4 ^6 H- j0 G

% Z1 T; `6 [" M! |
; ?5 A) i& \1 G2 r7 F3 c9 u  ^
▲ 图5. STM32CubeIDE 中将 startup_stm32g474retx.s 从工程中去除

# @- r3 {7 b+ a  {8 _4 |" _9 q, c5 \9 F7 V* k

5 i/ w" ?2 V0 E8 C' \: U修改 Linker 的配置,通过“Properties”打开设置页,将 Linker 文件修改为 STM32_FLASH.ld。; M: F3 w' K3 k9 H$ F7 F; o3 G

, A1 N- v: o) p
' E% d" R  U5 }! X  e
6.png
& e8 w5 `* p3 i; |; A4 p
+ o1 g6 v8 s! O) W
0 q+ k8 @1 |5 p* G9 {+ d# u$ W7 {4 x
▲ 图6. STM32CubeIDE 修改 Linker 文件
) @6 e! B0 C# [. r1 M+ \0 V1 V
6 I( d; S6 M' x3 O. t9 O- k
通过 “Settings” -> “Build Steps” 配置页中,在 “Post-build steps” 处添加指令 :cmd.exe /c copy /Y "$(BUILD_ARTIFACT)" "..\MX25L6433F_GFX01M2_STM32G4.stldr",编译后生成 stldr 文件。
$ q5 o+ E: i2 G; @$ r- S: {. ?8 R( P7 m* v8 z- o

5 e. c. I. P* g( A
7.png
# a- v, _, P" h3 X' C+ w  W6 q
▲ 图7. 在 STM32CubeIDE 中添加后处理语句
, L4 v6 H/ X' D5 P2 c6 m& @

' w" a; M5 @  E当这些配置好后,重新 Build 工程,这样就会产生所需要的 Flash Loader。0 x* @& `( h. g9 B% G' b; H
  ?; z" b! s3 u  w( Y5 r' J
3.2. KEIL 工程配置
0 k: ?2 |7 B+ {与 STM32CubeIDE 配置过程类似,KEIL 的配置过程主要包括以下操作。在 Target 标签页,Arm Compiler 选择“Use default compiler version 6”,如下图所示。' a, W! {" O# y3 g" E; N$ u3 K) A8 E5 a

5 ]8 [+ s: _9 G
0 t4 P8 w: x8 X- ~" V
8.png

% l  ^( g% S' ]

$ O& x3 s3 K2 R- ^; I$ N9 u) q
% E3 u6 |' ]4 G7 j
▲ 图8. 更改 Arm Complier
8 A$ d) X% s' ^" I% t6 M- J" e
在 startup_stm32g474xx.s 的文件属性中,去除勾选“Include in Target Build”和 “Always Build”,这样这个文件就不会被编译和包含在这个工程中。
! G* ?% c. U, d/ V6 Q. P/ Y+ F9 k% t. F5 F( r2 O3 B) W
" }$ a9 L- d8 W# D0 p: \
9.png

2 f5 n; I0 N( t3 b3 [. e
5 C5 C  R* o( m. q+ v! l

: a, A2 j0 M: a3 q1 H
▲ 图9. 在 KEIL 中将 startup_stm32g474retx.s 从工程中去除
' m7 T% X: V, k

! S- Y* j0 ^3 E$ \6 H

5 Z& D* w# F  K) K! a$ J0 ^在属性界面,切换到 Linker 界面,去掉“Use Memory Layout from Target Dialog”勾选,修改链接文件,将链接文件更换为 stm32_loader.sct,同时注意在 Misccontrols 添加“--paged --pagesize 0x10--diag_suppress L6305” 。
% s' w" [# B9 }% ]
& Y2 T7 }- [+ D( u) \9 L3 j2 W& j

' w. [6 n! e% l
10.png
3 L! E6 C/ S4 L2 y% b" I
▲ 图10. KEIL 中修改链接文件

0 f) L/ e4 D" J! d  B

1 i* P1 J9 f9 F" I与 STM32CubeIDE 配置类似,添加后处理语句“cmd.exe /C copy /Y "!L" "..\MDK-ARM\MX25L6433F_GFX01M2_STM32G4.stldr"”。
5 [$ Q/ B5 _) j( ^2 k  q: o5 R" q/ {8 ~0 C0 E

4 V8 |+ n/ G. E5 I/ D: }
11.png
1 W3 |8 F6 @! x0 G# e0 t, y3 q; s
▲ 图11. KEIL 中添加后处理语句

% k1 ]1 B+ M7 Z: q/ _2 M

6 I3 c$ N( y7 W- x

% u2 x$ o2 e" g' }( g; @/ L, ^这些配置好后,重新编译代码,会在 MDK-ARM 文件夹下生成 stldr 文件。/ @) r: e' g4 }4 X8 l9 j3 U

) \" F0 I) a/ a

* @/ t* ]( Y: d$ C/ Q. w3.3. IAR 工程配置  Y4 M( N& U. }
IAR 工程配置与 STM32CubeIDE 和 KEIL 的过程类似。
- a/ j8 @$ \. f' t
3 m9 F+ X" p4 A" L: \0 n

; o6 _8 t4 V" h! j2 R1 l
12.png

& }2 S8 b5 }( o( ?" T9 ?9 V4 d
. y+ Y/ }5 {5 L; ?: a8 A

# N8 b( R2 T9 |  O: ]: z) z
▲ 图12. IAR 中将 startup_stm32g474xx.s 从工程中去除

9 g; k3 B( |3 q0 K' r! r$ j0 M% v) u' D) N% Y, ]( {1 B
( f8 E) v: b! r0 z+ T  O' X
13.png
! k; _( e" x4 h2 c

" C& o, F- S* p. L% B0 v& L
▲ 图13. IAR 中修改链接文件
6 `7 _" B0 A) @( _+ h8 {/ R% h. D3 w

" S. ~6 |9 e2 ^* W* L: o9 S) D' e

- U  t2 }$ ]# c6 t' x+ x5 S. }: [

! A( O3 k, }, ~9 s/ p0 i
14.png
( j. ^, j7 v' H3 b$ D7 [# M( A8 _$ i

# _9 |1 d4 S' L+ z: Q( ^
▲ 图14. IAR 中更改入口函数

; m# x& r' r# g1 X  a: v* i

; F9 D9 s2 n" M9 g( z$ D

3 \1 q" }6 e% {1 {

2 m6 H3 o' n$ z3 m6 i: p! F/ D
15.png

) H: Z6 p, I" z4 v" C, s& ]$ I8 F; k( y) G
▲ 图15. IAR 中添加后处理函数

9 M% E! W: d2 A7 i2 J
/ d/ h4 Z; |" ^

- N+ u& S; n9 d7 K" D. O9 e7 G
这些配置好后,重新编译代码,会生成 stldr 文件。$ N5 v, V. i6 K- I; l% `2 v3 D

+ ~! B, R) O. y( E& q
四、小结0 F# ]8 @5 z$ o
本文结合 X-Cube-DISPLAY 3.0 软件包中的示例,介绍了利用 X-CUBE-DISPLAY API 进行 Flash Loader 的方法,如果用户选择的 Flash 是 MX25L6433F 这款 Flash,那么可 以参照此方法,来快速开发自己的 Flash Loader,如果所选的 Flash 不是 MX25L6433F,也可以参照此方法,重新编写对应存储器的驱动来开发对应的 Flash Loader。
/ F- Y4 R5 W* v! b2 m. }% r1 m& W4 B
: k4 f- f: s. w6 `2 W6 [4 r
9 S! D/ b( X& k! z/ `$ [
转载自: STM32
  n0 F' d& ]/ p$ j如有侵权请联系删除0 T4 d4 [' Y: j: Q! t3 Q

3 P7 l4 W, x8 F

& M1 N  y9 e8 w( ]* n+ ~( B
$ n/ t% O6 j% a  P+ k. @5 {# r' p
收藏 评论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 手机版