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

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

[复制链接]
STMCU小助手 发布时间:2024-3-21 17:58
一、引言
9 i! q  o( o  |; p( K% v/ Q在嵌入式应用系统中,越来越多的应用需要扩展外部 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。
! i- |4 @- ^5 Z, K7 S* Z, @* P3 C0 |9 D" D& U
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 的方法。
+ B7 l8 E, q6 k8 i2 q* R3 x. K7 Q: W9 _; s7 ?6 p
二、Flash Loader 的开发过程
& j5 K: s' ?5 M参考 ST 在 X-CUBE-DISPLAY 3.0.0 所提供的 Flash Loader 工程,外部 Flash Loader 的开发过程主要包括以下 3 步。& X$ B; p, k; U1 `& [
(1)更新 Dev_Inf.c 中的存储器芯片信息。3 |9 B" H  m, J* m2 v7 F  d0 g
(2)重写 Loader_Src.c 中的相关接口函数。
" T/ q1 P) E* T/ s+ b) Q(3)更改输出文件名。
, Z/ o6 H' E6 g3 A
5 f2 T3 ?* a" o- |; R项目配置好后编译整个 Flash Loader 项目,将生成一个 ELF 文件,文件的扩展名取决于所使用的编译器,Keil 的为.axf,EWARM 的为.out,STM32CubeIDE 的为.elf,通过编译后处理指令更改为 stldr 扩展名的文件,将该 stldr 文件复制到 “bin/ExternalLoader”目录下就可以被 STM32CubeProgrammer 使用了。8 ?7 a9 c5 t  h7 e

! p2 w6 I5 F3 d1 F5 S0 W! h
2.1. Dev_Inf.c 介绍
  s8 |* C" x7 G  M此文件中定义的 StorageInfo 结构提供有关外部存储器的信息。用户在制作自己的 Flash Loader 时,需要根据 Flash 的参数来更新相关信息。. y1 o  Z# q, v7 {% D- {7 x

$ v, s) q1 i8 f& A' r
2.2. Loader_Src.c file
0 [+ ?7 u4 A8 J4 S该文件包含了制作外部 Flash Loader 所需的接口函数,主要包含初始化,擦除,写入以及读出等操作。其中 Init,Write, SectorErase 这些函数是必需的,不能被省略。除了这些函数之外,您还可以重写 Read,Verify,MassErase 函数。
; u( V, P+ e4 V5 l
( C+ m. d0 F4 u( _# o3 b2 _
2.2.1. Init
! h9 H8 o9 b8 b/ ]Init 初始化连接到外部存储器的 GPIO 引脚以及初始化 IP 所用的时钟。5 U) A8 M' U, C  D( ]1 F3 C4 Y/ w' l
如果成功,则返回 1,如果失败,则返回 0。
: n7 C8 B7 w  p; z9 Zint Init (void)
& D4 w. C$ q  W" d: ?7 `" q/ {& _
2.2.2. Write
) k: ^3 _/ {2 l& S* u1 L1 }- qWrite 函数将在 RAM 定义的缓冲区写入到外部存储器。" v  _+ F3 b; i" |
如果成功,则返回 1,如果失败,则返回 0。
: {  @- z1 W% q( _. {: ~' }, kint Write (uint32_t Address, uint32_t Size, uint8_t* buffer)* }( h. a2 r7 W+ X. S& z( H
1 y/ A$ p6 T: q, C+ H  S5 e
2.2.3. SectorErase
5 L; Z) y/ i# \+ F5 j2 Y) c擦除内存指定的扇区。其中起始地址等于要擦除的第一个扇区的地址,结束地址等于要擦除的结束扇区的地址。
" K* f0 w7 \1 D! q如果成功,则返回 1,如果失败,则返回 0。0 W  O: _9 V' e9 }
int SectorErase (uint32_t StartAddress, uint32_t EndAddress)
+ e% y+ h/ L% D2 L7 T0 h% G' t1 J) v7 p
2.2.4. Read 功能
& m7 w8 r) P& `* F5 PRead 函数将存储器指定地址的数据读取到内存中的缓冲区中。0 x0 z# z( m) `% r8 j% S( F7 }
如果成功,则返回 1,如果失败,则返回 0
- m. I9 B! e7 {) g. w9 Tint Read (uint32_t Address, uint32_t Size, uint16_t* buffer)
( d/ I$ r( W' K) S6 u2 N7 d! C5 ?5 V
2.2.5. Verify
9 p' ?# U! D9 I4 X2 n8 R功能当选择“边编程边验证”模式时调用验证函数。此功能检查编程的内存是否与 RAM 中定义的缓冲区相对应。, T/ q/ ]7 R/ s7 W) t
" o3 ?# D; |3 b5 U$ U, l6 a
2.2.6. MassErase 功能 " G9 ~, I* n4 ~* d0 N
MassErase 功能会擦除全部内存。
" H9 o3 E7 F+ J) {& \: u- ]如果成功,则返回 1,如果失败,则返回 0。
0 j1 m% N0 }% F" V$ p6 Nint MassErase (void)
8 g& n1 M. i6 P" s) \
  _0 J" Y4 W* ~' q9 p+ I
2.2.7. Checksum 功能8 k; i: ]- B" \4 }
描述的所有函数在操作成功时返回 1,在失败时返回 0。
$ M' L/ t' B( r  c8 g. T0 R
( X9 C# F& y% C3 \2 B
三、利用 X-Cube-Display API 生成 Flash Loader 的方法
# R+ ]7 _; i( [8 J% f! b
这里参考 X-CUBE-DISPLAY\3.0.0\Projects\NUCLEO-WB55RG\Applications 目录下的 GFX01M2_FlashLoader 工程的方法,来移植一个 NUCLEO-G474+GFX01M2 的 Flash Loader,这是一个 SPI 接口的 NOR FLASH,芯片型号 MX25L6433F。& h* r$ g- f. `  w1 g+ H) C
我们打开 STM32CubeMX,MCU 选择 STM32G474RET6,首先配置时钟,其次这里用到外设有 SPI,还需要对 SPI 进行配置,查看 X-NUCLEO-GFX01M2 和 NUCLEOSTM32G474 原理图,外部 Flash 用到了 SPI2,GPIO 引脚用到了 PB13, PB14, PB15, PA8。SPI2 相关配置参数如下图所示。' y/ G8 d8 n/ h: K/ Z
- B9 F) d2 F) q& n4 i: ]' c
1.png

4 O$ O2 b; F  y; `
. X, u& @+ b! X) l; |

- Y, w/ D6 [( U1 h6 G: Q

  l0 R7 b7 Q* t1 j# D
▲ 图1. SPI 参数配置

! [; g8 N- H  y
, k, i' \/ H' v3 y
  y4 o7 a' z' U4 u% @- \" R
SPI2 外设相关参数配置结束后,点击 X-CUBE-DISPLAY 标签,为相关的 IO 接口配置对应的引脚和外设。 - V3 k: a* L9 v6 A8 _2 k' {
图片
$ O  ]# d4 C, k, ?$ C; F0 h; t( I# P1 Q5 X! Y% L2 T
7 C! ^( D7 F3 C* U; Q4 N0 Y
2.png

; B. a9 L' q: D5 w* A1 |$ W4 `: N& e

* s4 f% R, E6 |# U# C. A

4 T4 `5 y$ m  o- c% D
▲ 图2. X-CUBE-DISPLAY IO 接口配置
9 D+ j# b; n0 J

- h" b3 K3 ?* G  D
' {! b  u9 N6 r7 p8 b2 W* P$ s3 D
相关参数配置好后,点击 Project Manager,给工程重新命名,由于 Flash Loader 不需要 main 函数,选中配置的 “Do not generate main()”,这样生成的代码就不会有 main 函数。然后点击生成代码按钮生成代码。( \, q# z. W6 F9 d, K

0 n* _* J) |: [2 v& ]7 i  _
( L0 d, Y& [6 Z9 T/ s+ H
3.png

  p& H3 o; k( |. _0 c$ T1 ]& Q4 m

/ |6 r! [8 [0 ~* H  Q" ^

2 g3 ~( @0 X1 Y1 Z! s  I5 J
▲ 图3. Project Manager 修改

9 q* ^% c, G* Q+ x. g* `
& q2 j4 S3 Y( u4 `
$ E! @! ^1 Z$ _, }  ]/ W
生成的代码还需要添加 Dev_Inf.c、Loader_Src.c、Dev_Inf.h、Loader_Src.h,将这个代码添加到 Core 文件夹下的 Inc 和 Src 文件夹,为了方便不同编译器生成的代码能够自动加载这几个文件,复制.extSettings 文件到该工程文件夹,该文件会为工程新建一个 Loader 文件组,然后再重新生成代码。生成的代码用 VSCode 打开,在 main.c 函数中新增 MX_Init()函数,函数主要的功能是复位外设和初始化 GPIO。  @; m; C% O1 \- y( b, h

1 c. g$ T! d; p& @# X# F
) M5 k' f! J6 Y" h
4.png
) H' i' ^( q1 b# h' k
▲ 图4. 添加 MX_Init()函数

& o3 n2 u$ u2 X
关于 Dev_Inc.c 和 Loader_Src.c 文件中的函数,这里就不再做一一说明,大家可以对照附件查看,下面主要介绍下不同编译器的工程属性配置。
0 u$ F8 H; U* g) s. M
0 a3 i6 q# _9 z5 x  Y" o
3.1. STM32CubeIDE 工程配置
4 }; K% z5 F: A1 s6 `7 v! K3 DSTM32CubeIDE 的配置修改包括从工程中去除 startup_stm32g474retx.s,修改 Linker 文件,修改启动函数入口,添加后处理生成 stldr 文件。
' s& L8 ~' x2 a9 F; M
& ~( o6 m2 s3 Q0 M7 O& O# L

; W; Q9 j: g/ b% e8 v$ f
5.png
7 }' k$ }) K% V
2 D: \) [8 b# T  Q. g

) g5 E. g& v" [5 F/ g- j
▲ 图5. STM32CubeIDE 中将 startup_stm32g474retx.s 从工程中去除

! Y8 u. O3 m/ f5 q. _* v
" t# T; [2 \6 `7 i+ n  Y
2 C7 K1 H$ }" U/ A
修改 Linker 的配置,通过“Properties”打开设置页,将 Linker 文件修改为 STM32_FLASH.ld。
3 n% t9 }# q. j2 ?2 H3 p( f6 H- b/ Q- I9 e. k, Q) D

+ H( P' }5 `9 B1 K: V4 m
6.png
0 c9 m1 A) ^2 Q) Z& s( ]/ [# H6 r0 m

  `9 _! _1 ~6 A; M2 W+ V& G

; K! y! `9 V. h$ Q2 q- k" w
▲ 图6. STM32CubeIDE 修改 Linker 文件

1 A0 v" r5 B) Q$ Z. k/ A
3 q2 L! U/ `1 S/ N- q6 Y
通过 “Settings” -> “Build Steps” 配置页中,在 “Post-build steps” 处添加指令 :cmd.exe /c copy /Y "$(BUILD_ARTIFACT)" "..\MX25L6433F_GFX01M2_STM32G4.stldr",编译后生成 stldr 文件。; }5 d) o& Y  `! @' n; o* A9 t8 t

; ^4 `/ O2 G: Z# u0 M& ]8 J& F
( N6 V: e! X* I) p# d
7.png
3 _) |& A. k2 N4 J% z9 j
▲ 图7. 在 STM32CubeIDE 中添加后处理语句
+ L  u- P7 ?! e* x6 C% {8 f( {
3 _4 N' i7 T- X3 Z+ Y* k7 I
当这些配置好后,重新 Build 工程,这样就会产生所需要的 Flash Loader。
; r; A9 M9 p$ B- N0 i. n: y! k
/ H. E3 e0 D3 O9 X
3.2. KEIL 工程配置- {/ ?. @( t- v! U/ A/ j$ J# g
与 STM32CubeIDE 配置过程类似,KEIL 的配置过程主要包括以下操作。在 Target 标签页,Arm Compiler 选择“Use default compiler version 6”,如下图所示。
+ M& L1 p: _% x% l4 [( k8 C5 I: `( H1 H. F1 f: m: H
2 X8 ?* E* b8 M! `
8.png

) i+ _  b' b: \2 M0 ]$ ]+ r2 }4 _

6 ~' p# Y& W' Y% Z' D1 j( g

2 X+ g( n* {9 C1 e
▲ 图8. 更改 Arm Complier

$ j, P! ^* q. [" J  ?- }在 startup_stm32g474xx.s 的文件属性中,去除勾选“Include in Target Build”和 “Always Build”,这样这个文件就不会被编译和包含在这个工程中。
( `$ e9 K! V  ^# N7 ~
6 |" @, p( u: [& N: t
: i& Y0 v7 s/ r3 G+ Y+ R
9.png

9 _$ n. E6 W3 K

1 N$ c% U) R9 t
5 ?& T, Q9 D5 C1 ^- ~
▲ 图9. 在 KEIL 中将 startup_stm32g474retx.s 从工程中去除
: [3 Z8 c/ M5 H0 ?; F- M# }
' f1 h  {& c- K6 D. R3 r: q

: J' h) M) x, I6 d; p0 N8 t! ^( B, z在属性界面,切换到 Linker 界面,去掉“Use Memory Layout from Target Dialog”勾选,修改链接文件,将链接文件更换为 stm32_loader.sct,同时注意在 Misccontrols 添加“--paged --pagesize 0x10--diag_suppress L6305” 。
$ V. o0 V  h3 A  o- I9 m# G; Z: j! e
' o/ q- T  C8 }! Y

5 A2 Q1 O- n1 t  P
10.png

3 Q* }/ L* P- U, c& K
▲ 图10. KEIL 中修改链接文件
5 k- L- G1 p% E  S" k6 n; B$ e
" D3 V/ y* `5 h1 j
与 STM32CubeIDE 配置类似,添加后处理语句“cmd.exe /C copy /Y "!L" "..\MDK-ARM\MX25L6433F_GFX01M2_STM32G4.stldr"”。
7 f& o0 z7 t8 q! k3 ]7 _. \$ u( b" D& C/ _: x7 ]! Y

* M! {) Q2 X; R+ @$ r/ I) [
11.png
, C& ~9 i* P, D' @7 K+ [0 D
▲ 图11. KEIL 中添加后处理语句

# O9 q2 ?! f  R, @- O

. V+ U+ ~& B7 A/ c' V) D! _

: N5 ]! N5 S! h# K5 \这些配置好后,重新编译代码,会在 MDK-ARM 文件夹下生成 stldr 文件。- K" G  b5 m" u+ F! W; ~. O
( E5 d% h3 Z' L6 w
# S- t) u: u! a9 H$ g; j* g! {4 j
3.3. IAR 工程配置  t3 T3 o7 ^, V, t, h" R
IAR 工程配置与 STM32CubeIDE 和 KEIL 的过程类似。 # w! @. a, Z1 K' J/ o# k
$ \: k. }; F4 B. P% h1 [/ s
; `1 m1 p/ P  t" `8 m8 f  U
12.png
+ x0 [6 W( H2 Y& Z% G; i

: U) v8 F4 D* Z1 I* O- _
1 M- \: ^2 D1 t, H  Y
▲ 图12. IAR 中将 startup_stm32g474xx.s 从工程中去除
! A2 Y. g) Y( O# W

$ G9 t0 u: G) K- O7 p' Z& }- c; C/ t4 T" {9 l% ~8 k5 Y
13.png
/ |4 `* H( A  [8 |4 M

% ^4 e, L7 p( H* c5 e+ G6 l9 ~
▲ 图13. IAR 中修改链接文件
; r: _- O8 p& Y3 j9 I
$ [- l3 j+ \6 m! b
1 Z* E, C% u8 C* p

$ s0 h6 `: I5 F( F$ E$ x0 Q
14.png

2 o; h1 z: i, s( a' W" n! t, F/ \3 _0 B" P! s# M
▲ 图14. IAR 中更改入口函数
0 W8 W- o8 Y" t" {
: E5 C% F% A. T6 R% N
6 z) _8 N- V% u9 k, U( F3 t

1 J1 \9 t) O/ o9 G
15.png

5 n) m- S$ ^8 t
7 q0 F7 |+ @5 u$ g8 Y" P- S9 m
▲ 图15. IAR 中添加后处理函数
% O- P/ S7 C5 ^2 h' w1 s* U' O
; P8 j; r4 i& \% }% ]& C4 n

( j2 r1 }6 \; F0 x
这些配置好后,重新编译代码,会生成 stldr 文件。
" r: e3 m0 I$ C7 e
2 k* b' g: Q; h$ Q) T( ~  P  S* O
四、小结
" q9 _1 q- a5 H9 Y( s6 W本文结合 X-Cube-DISPLAY 3.0 软件包中的示例,介绍了利用 X-CUBE-DISPLAY API 进行 Flash Loader 的方法,如果用户选择的 Flash 是 MX25L6433F 这款 Flash,那么可 以参照此方法,来快速开发自己的 Flash Loader,如果所选的 Flash 不是 MX25L6433F,也可以参照此方法,重新编写对应存储器的驱动来开发对应的 Flash Loader。0 K) R3 x2 A% }5 O. Q; t

( e$ A7 r, Q% c1 l

8 U$ D& p) P0 d2 V转载自: STM32- g9 z' m! e0 r
如有侵权请联系删除  F* `' o% k0 [, u

4 D. J0 z& _$ G6 @: X( f& z2 ^" N
" v! B' b  F4 _  x* J

, K  _# ~% ~1 ~% c
收藏 评论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 手机版