一、引言; G7 `$ i! v' \( A 在嵌入式应用系统中,越来越多的应用需要扩展外部 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。: c p( S/ I: s! V" E : e0 N' V: G7 Z; { 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 的方法。 7 p; N3 j7 P" ?5 o) j( P4 b6 a4 n 二、Flash Loader 的开发过程 参考 ST 在 X-CUBE-DISPLAY 3.0.0 所提供的 Flash Loader 工程,外部 Flash Loader 的开发过程主要包括以下 3 步。 (1)更新 Dev_Inf.c 中的存储器芯片信息。" I m8 }9 ?9 l, p0 {+ z: t (2)重写 Loader_Src.c 中的相关接口函数。# k: G$ ?7 F8 g% q6 t (3)更改输出文件名。 3 }5 W; k h! V# n& m" ~( H 项目配置好后编译整个 Flash Loader 项目,将生成一个 ELF 文件,文件的扩展名取决于所使用的编译器,Keil 的为.axf,EWARM 的为.out,STM32CubeIDE 的为.elf,通过编译后处理指令更改为 stldr 扩展名的文件,将该 stldr 文件复制到 “bin/ExternalLoader”目录下就可以被 STM32CubeProgrammer 使用了。3 `7 a, q- ~8 c3 E( ? * S2 [8 t/ j3 Q. `" u 2.1. Dev_Inf.c 介绍 此文件中定义的 StorageInfo 结构提供有关外部存储器的信息。用户在制作自己的 Flash Loader 时,需要根据 Flash 的参数来更新相关信息。 2.2. Loader_Src.c file% N9 G' r2 A: `# }5 e& r& |2 I 该文件包含了制作外部 Flash Loader 所需的接口函数,主要包含初始化,擦除,写入以及读出等操作。其中 Init,Write, SectorErase 这些函数是必需的,不能被省略。除了这些函数之外,您还可以重写 Read,Verify,MassErase 函数。 ( N# d1 [7 B) u, T$ Q7 w+ ~' A 2.2.1. Init 4 \$ A, Z* Z \. [ Init 初始化连接到外部存储器的 GPIO 引脚以及初始化 IP 所用的时钟。3 u. T" `) ~7 _ 如果成功,则返回 1,如果失败,则返回 0。 $ K% s! r8 u# c int Init (void) 2.2.2. Write * N2 V, T8 n' j3 t5 w" G2 Q; A Write 函数将在 RAM 定义的缓冲区写入到外部存储器。9 U) r% z6 } b- d 如果成功,则返回 1,如果失败,则返回 0。 int Write (uint32_t Address, uint32_t Size, uint8_t* buffer) $ E* i4 q& a& ] `$ b: w 2.2.3. SectorErase 擦除内存指定的扇区。其中起始地址等于要擦除的第一个扇区的地址,结束地址等于要擦除的结束扇区的地址。 如果成功,则返回 1,如果失败,则返回 0。 int SectorErase (uint32_t StartAddress, uint32_t EndAddress); i2 c5 F2 }9 V 2.2.4. Read 功能 ' `9 M/ Y6 E1 v; t6 K( ~* E Read 函数将存储器指定地址的数据读取到内存中的缓冲区中。 如果成功,则返回 1,如果失败,则返回 0 int Read (uint32_t Address, uint32_t Size, uint16_t* buffer) 2.2.5. Verify * L& |6 T7 @% f6 b, _4 w 功能当选择“边编程边验证”模式时调用验证函数。此功能检查编程的内存是否与 RAM 中定义的缓冲区相对应。 % e: S+ L% [7 S: o 2.2.6. MassErase 功能 , Q9 Y" x* s2 D MassErase 功能会擦除全部内存。6 M, m+ \3 @' |) G$ j, i 如果成功,则返回 1,如果失败,则返回 0。 2 H' b1 s) s" w: H1 m3 h5 _ int MassErase (void) [7 |5 m3 I1 N3 j0 {- i- _. \ " x- b# V' h. L" |+ p7 e 2.2.7. Checksum 功能0 P4 h$ H1 }$ ? L 描述的所有函数在操作成功时返回 1,在失败时返回 0。 # S6 n# i6 F! h8 A8 z 三、利用 X-Cube-Display API 生成 Flash Loader 的方法 这里参考 X-CUBE-DISPLAY\3.0.0\Projects\NUCLEO-WB55RG\Applications 目录下的 GFX01M2_FlashLoader 工程的方法,来移植一个 NUCLEO-G474+GFX01M2 的 Flash Loader,这是一个 SPI 接口的 NOR FLASH,芯片型号 MX25L6433F。 我们打开 STM32CubeMX,MCU 选择 STM32G474RET6,首先配置时钟,其次这里用到外设有 SPI,还需要对 SPI 进行配置,查看 X-NUCLEO-GFX01M2 和 NUCLEOSTM32G474 原理图,外部 Flash 用到了 SPI2,GPIO 引脚用到了 PB13, PB14, PB15, PA8。SPI2 相关配置参数如下图所示。 1 r5 F' ~" N) l4 D1 L5 _+ e8 j ▲ 图1. SPI 参数配置 0 v# Q5 R Q a3 b5 H4 L SPI2 外设相关参数配置结束后,点击 X-CUBE-DISPLAY 标签,为相关的 IO 接口配置对应的引脚和外设。 图片, [* a( k2 O, p" C% ^9 D ' x3 P8 ^' X: Z- q; ~$ ^ # s: l( P. G- {( y" m ) P/ w5 U1 x+ g7 n2 Q0 N j▲ 图2. X-CUBE-DISPLAY IO 接口配置 9 J$ ], ?0 W- v: f3 x) X 相关参数配置好后,点击 Project Manager,给工程重新命名,由于 Flash Loader 不需要 main 函数,选中配置的 “Do not generate main()”,这样生成的代码就不会有 main 函数。然后点击生成代码按钮生成代码。 3 A/ H. l% }( [7 _8 F 2 P: X& h* b* i G : N0 F) t* Y# f+ j) |( Y % H3 c# T0 g, ]6 R▲ 图3. Project Manager 修改 生成的代码还需要添加 Dev_Inf.c、Loader_Src.c、Dev_Inf.h、Loader_Src.h,将这个代码添加到 Core 文件夹下的 Inc 和 Src 文件夹,为了方便不同编译器生成的代码能够自动加载这几个文件,复制.extSettings 文件到该工程文件夹,该文件会为工程新建一个 Loader 文件组,然后再重新生成代码。生成的代码用 VSCode 打开,在 main.c 函数中新增 MX_Init()函数,函数主要的功能是复位外设和初始化 GPIO。 / @. Q6 S1 u0 d8 l ▲ 图4. 添加 MX_Init()函数 关于 Dev_Inc.c 和 Loader_Src.c 文件中的函数,这里就不再做一一说明,大家可以对照附件查看,下面主要介绍下不同编译器的工程属性配置。, F/ z' R t& L7 T4 l. v3 F 2 J8 F+ q$ y2 G/ t: T s+ j4 \ 3.1. STM32CubeIDE 工程配置 STM32CubeIDE 的配置修改包括从工程中去除 startup_stm32g474retx.s,修改 Linker 文件,修改启动函数入口,添加后处理生成 stldr 文件。 8 \* R( y- Z+ l! }2 h7 R ( g5 F3 R4 T) ~6 Z' U8 b" U# s ▲ 图5. STM32CubeIDE 中将 startup_stm32g474retx.s 从工程中去除 修改 Linker 的配置,通过“Properties”打开设置页,将 Linker 文件修改为 STM32_FLASH.ld。: x/ A( X% H, i2 s& B # V. S1 m, y! ^5 L % r' e$ {9 X, Z; x- M & w; P2 W- e& q7 f5 J" e' ? ▲ 图6. STM32CubeIDE 修改 Linker 文件 Y5 s; [& P1 m2 H8 ^6 g8 ^9 Z% `& C: }6 I 通过 “Settings” -> “Build Steps” 配置页中,在 “Post-build steps” 处添加指令 :cmd.exe /c copy /Y "$(BUILD_ARTIFACT)" "..\MX25L6433F_GFX01M2_STM32G4.stldr",编译后生成 stldr 文件。 & e$ I! _" r* k& ~. ^ 3 x0 A0 E1 Q8 m/ B; x. f ▲ 图7. 在 STM32CubeIDE 中添加后处理语句 当这些配置好后,重新 Build 工程,这样就会产生所需要的 Flash Loader。: u! I; ]6 q, u- J( G 1 H% A( N! l; j$ @/ _7 f( M' y 3.2. KEIL 工程配置. W3 N- i* p1 a. E( v: M0 H% l 与 STM32CubeIDE 配置过程类似,KEIL 的配置过程主要包括以下操作。在 Target 标签页,Arm Compiler 选择“Use default compiler version 6”,如下图所示。8 I1 T4 j& p; u" r( @! @' O : w: i1 t) C: b0 ]# O% i ▲ 图8. 更改 Arm Complier 在 startup_stm32g474xx.s 的文件属性中,去除勾选“Include in Target Build”和 “Always Build”,这样这个文件就不会被编译和包含在这个工程中。 1 w$ N j$ v* ~4 a : M9 Q l5 N/ r9 W ▲ 图9. 在 KEIL 中将 startup_stm32g474retx.s 从工程中去除 7 |4 n+ K# I5 u' N) x 在属性界面,切换到 Linker 界面,去掉“Use Memory Layout from Target Dialog”勾选,修改链接文件,将链接文件更换为 stm32_loader.sct,同时注意在 Misccontrols 添加“--paged --pagesize 0x10--diag_suppress L6305” 。6 {. |% x" o/ y! ]0 R3 Q% l 4 H5 ~2 H; P7 n: o' o ▲ 图10. KEIL 中修改链接文件 ! B& e5 y: D! a/ q: { a, m: S: _: f/ u: }$ b: f0 B" e 与 STM32CubeIDE 配置类似,添加后处理语句“cmd.exe /C copy /Y "!L" "..\MDK-ARM\MX25L6433F_GFX01M2_STM32G4.stldr"”。) R: ?1 ^6 u& l E9 ~: P. k+ F5 K, }8 N! { + }, m# s& ]# y1 ~3 D$ l/ G+ A * e9 U1 @4 V |9 B5 ~+ c. X ▲ 图11. KEIL 中添加后处理语句 + F o4 ~6 j4 [: E- Q7 [; J; I/ v. {% z) U$ l, l! B) l. g 6 p6 p' O2 u) W \1 L8 K 这些配置好后,重新编译代码,会在 MDK-ARM 文件夹下生成 stldr 文件。# R0 B0 h# A* E 2 ^" G H, B# H+ e5 y. a x& `9 Q" {4 m5 I& o, r 3.3. IAR 工程配置2 l, m1 B" g3 l IAR 工程配置与 STM32CubeIDE 和 KEIL 的过程类似。 ▲ 图12. IAR 中将 startup_stm32g474xx.s 从工程中去除 ▲ 图13. IAR 中修改链接文件 # j* f: Z4 c. N7 \( j- u6 K7 W ▲ 图14. IAR 中更改入口函数 3 B6 x4 m/ Z) J& b: }▲ 图15. IAR 中添加后处理函数 7 ~/ h1 R4 e- s. b! O1 D) w" C5 W* l9 D9 {6 b$ F* i: V 这些配置好后,重新编译代码,会生成 stldr 文件。 四、小结 本文结合 X-Cube-DISPLAY 3.0 软件包中的示例,介绍了利用 X-CUBE-DISPLAY API 进行 Flash Loader 的方法,如果用户选择的 Flash 是 MX25L6433F 这款 Flash,那么可 以参照此方法,来快速开发自己的 Flash Loader,如果所选的 Flash 不是 MX25L6433F,也可以参照此方法,重新编写对应存储器的驱动来开发对应的 Flash Loader。) ?" X$ `9 U+ U. z O7 D 9 N& g4 |6 \7 ~+ s% k p / r6 U: D4 N2 h v8 F/ d 转载自: STM32 如有侵权请联系删除 & x8 I* N, O" }; q 9 M! g0 L1 X6 W; Z |
STM32 ISP IQTune:真正零门槛的免费ISP调整软件
【经验分享】基于STM32使用HAL库实现USB组合设备CDC+MSC
2024意法半导体工业峰会:赋能智能电源和智能工业,构筑可持续未来
ST推出灵活、面向未来的智能电表通信解决方案,助力能源转型
意法半导体 x Qu-Bit Electronix:推动新一轮的数字声音合成革命
从STM32 MPU产品看嵌入式系统中微处理器的新变化
【Hot!】STM32全系列开发板都支持Arduino开发,你知道吗?
【经验分享】STM32 HAL库移植FreeModbus详细步骤
【STM32H7S78-DK评测】XIP模板问题处理与电机控制
【经验分享】STM32驱动RC522读卡完整资料分享,包含原理图、PCB、驱动工程文件
你好,关于IAR制作stldr文件有详细的教程吗?比如最后用的是什么指令?