1.IAR 下载配置
1 j4 u9 |+ _$ q3 W5 ^& Z4 W本次使用的硬件环境为MUCLEO-L476开发板,官方下载的软件包中打开IAR的工程文件,IAR的下载配置如下:8 D4 @8 w: P/ t! J3 R* i
默认配置是使用IAR 系统默认配置文件,我们勾选上Oveerride default .board file文件。
( b- ]& n4 J L L! _从下载配置中看IAR环境下载使用的是flash loader 进行下载,使用的配置文件为 IAR 安装路径下的此文件$TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32L4xxxG.board 官方的帮助文档中对flash loader 的描述如下,从如下描述中可知,flash loader 是运行在目标系统(MUCLEO-L476开发板)的一段实现特定flash 操作的接口函数集合,IAR 通过C-SPY将flash loader 加载到目标系统(MUCLEO-L476开发板)RAM中运行,完成目标falsh 的更新任务。
3 c8 b9 w E" L7 ~& q/ }The flash loader) T" b6 o! `3 S! Y; T
A flash loader is usually a rather small program which can program one or more flash memories.; L( j0 m0 j3 U- e$ o* R2 S
The flash loader consists of a small set of functions, mainly for erasing or writing designated
, B2 u; U4 \& _5 yportions of the flash memory. C-SPY downloads this program into RAM (it must be linked to an" h0 q, b' e1 Q
address in RAM). To run the program, C-SPY sets the PC to one of the functions in the flash
4 ?! c d% \) g- ~loader, writes data and directives for that function into a RAM buffer, and starts execution.
. Y5 s f3 q, b6 p+ f8 h" @When the function returns, execution will hit a breakpoint. C-SPY will then know that the% k$ _+ X$ B; D% p6 Y
function has finished and can proceed to make further K+ L6 m+ Y2 D9 B/ {
从如下图片能更清晰的看出flash loader 的工作流程:
2 B" O& A5 N$ V3 _ Z% \$ h
- 通过 C-SPY 将 flash loader 程序加载到目标系统预留的RAM区域。
- 通过 C-SPY 将需要下载测程序加载到目标系统预留的RAM区域,如果可执行程序比较大预留的RAM空间可能不能一次完全放下可以分割成多次传输。
- 将 IMAGE 镜像通过 flash loader 将 IMAGE 镜像下载至flash.
- 镜像下载完成后可以释放预留的RAM空间,至此已经完成下载。
6 F( z- n0 w! R + B$ d( k& _" w4 {* S& I' [) s3 a
2. *.board 文件格式说明此*.board 配置文件的总入口,*.board 文件是什么文件,从IAR的帮助文档摘出如下说明,.board 文件是flash loader 下载镜像的配置文件被IAR 的C-SPY debug 对象引用。 " x) e4 a7 U: s, j7 S7 K
| Ext. | Type of file" s" t9 ?# S& E. p, `
| Output from | Input to | | board | Configuration file for flash loader | Text editor | C-SPY |
$ G) u2 t/ l6 E0 e+ v
$TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32L4xxxG.board文件内容如下: - <?xml version="1.0" encoding="iso-8859-1"?>2 a0 J, s3 ]9 v
- : a/ w& Y4 Q6 g0 [
- <flash_board>( \8 m* k5 @& N+ J0 L. `0 r
- <pass>
# X. t# c, W% n; V+ k. t - <loader>$TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32L4xxxG.flash</loader>& a H: ?: G" N0 O
- <range>CODE 0x08000000 0x080FFFFF</range>
, ` i( u' b" b! | h: _ - </pass>
: D9 w! K0 x$ P; g P - </flash_board>
复制代码
/ S& K6 X) x7 {+ Y2 l: P. m从如上xml 的配置指定了,flash 的配置说明及FLASH的范围: 5 T6 q8 j2 z8 v' X) m' n
3. *.flash 文件格式说明 从配置选项可以看出,此.board主要的配置信息是告诉flash loader 要根据Flash STM32L4xxxG.flash 文件的配置下载镜像,此.flash 的文件是什么文件呢,从iar 的文件说明可知,.flash 文件也是C-SPY加载的文件,主要定义了flash 的相关属性配置。 - p, F; n E3 u$ e4 ]& V3 X* E
| Ext. | Type of file | Output from | Input to | | flash | Configuration file for flash loader | Text editor | C-SPY | 3 @% G+ [' k# w3 ?
- <?xml version="1.0" encoding="iso-8859-1"?>& v' ]0 Q- w$ ?; r" m- X1 g, z
- 8 w: i9 _7 Z3 P" A
- <flash_device>) r1 u! y4 z: r/ Y
- <exe>$TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32L4xxxRAM48K_DUALBANK.out</exe>
% ?# g6 O6 z; l+ U! b7 I' J+ q - <page>8</page>
5 m5 n+ Z& H' |7 f# u1 F' ?* B - <block>512 0x800</block>) e1 P+ @/ \5 I6 @: m6 b
- <flash_base>0x08000000</flash_base>
- V/ u+ k7 T. Q2 B @5 }' E - <macro>$TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32L4xxx.mac</macro>5 H( u! d9 e* o. R4 J. B8 E4 w
- <online>1</online>
& T) l! A: y; v6 [ - <aggregate>1</aggregate> $ l, }1 R, @8 e1 X9 Y0 U k* I
- <args_doc>"--skip_erase" -Don't erase blocks that read empty.</args_doc>6 B, v a3 U- e( o5 x4 T5 L* r
- </flash_device>
复制代码如下是上述 xml 文件的配置项说明: To accommodate a large range of different flash memories, C-SPY uses a few concepts which8 o" B- ?( |1 v
detail the characteristics of flash memories.
/ ]8 ~% _8 D/ u L* s7 N. g! u8 _1 [Page
: G1 ?& ]0 D% rA page is the smallest writable unit of the flash memory. Many flash
: W7 \( |, W4 T' dmemories cannot write less than for example 128 or 256 bytes in a
: j7 b; t( S* z! K& Y1 ysingle write operation. C-SPY will never request the flash loader to write
2 @8 d& w1 a8 [( lanything smaller than a page, and uses padding if necessary to fill out a! @0 i$ g# U4 X8 ^
page. Of course, some flash memories have no such restrictions and can
; Y: H( b+ z9 \% W% qspecify a page size of 1 byte.; b1 G- I1 ^( {
Block
% ?1 x3 i, `! W N! v4 V0 x# [6 @A block is the smallest erasable unit of the flash memory. For example,( K, P$ S3 r- @- d9 `5 J P
a flash memory with a 256-byte page size could still require that flash- g( M) |0 p) t- e0 K
memory should be erased in 4-Kbyte chunks. The block size must+ E8 j0 W/ Y+ ]' g3 g; n+ v$ U
always be a multiple of the page size. A flash memory can consist of
7 C0 ]8 d# W7 C1 I5 r( ?1 Xseveral blocks of different sizes. It can also lack such restrictions, in, h+ Q+ `: c) O
which case the block size would be the same as the page size.0 b. M1 }9 _9 @% Y3 I. R% t- J
Base address
6 G& Y2 Q2 `/ `4 W7 r. [0 NThis is the start address of the flash memory, when it is written. Some
/ R% e. } i% J- N5 bflash memories are simply memory mapped into a fixed address range
% l' `1 Y3 F* D- a+ C, f$ Wand the base address is then the start of that range. Other flash memories
/ g" e8 f6 L0 nare mapped into different addresses when being programmed and when& R5 a, x7 G. V# b
the application is later executing. The base address is then the address
1 m' q6 Z j- L! [9 Cwhere these memories are mapped when being programmed. Yet other& p8 E) s- H1 K( c% L/ v8 d5 R
flash memories are not memory mapped at all, but work more like h5 q5 v: s* I' O' G- G! g+ Z
external disk-like devices. The base address is then simply the preferred3 x: @" u: H6 R& p J+ z) K/ O: a
address to be used for the start of the memory when it is being- e6 a2 [8 z n
programmed.
+ c( f7 n5 K9 ]* nFrom the C-SPY perspective, a flash memory starts at a given address and consists of a sequence
5 C1 k0 `& b; Y8 k3 xof blocks (possibly of different sizes), each of which consists of a number of pages. The9 [3 Y9 ^1 E$ m
sequence can also contain gaps.
7 J8 Z& A. J$ H7 _ G- [从上述配置文件解析: STM32L476 的 page 为8byte,共有512 个block 每个 block 大小为2k,总大小为1M,base 地址为0x0800 0000。 4 k2 ^3 |, u5 c2 F$ S
FLASH main features( g. W/ I& W' j* N, f5 g( ?0 a- Q
• Up to 1 Mbyte of Flash memory with dual bank architecture supporting read-while-write8 f, B _! l# O X
capability (RWW).
: T. O3 h7 V. E& \# [ D• Memory organization: 2 banks (Bank 1 and Bank 2)4 Q2 b$ V) e# Q/ f3 {) o7 X
– main memory: 512 Kbyte per bank
( A& j6 y o, `" @– information block: 32 Kbyte per bank
! z7 w ~/ d+ |+ N. g% W3 X3 F• 72-bit wide data read (64 bits plus 8 ECC bits)3 C2 Y C; b) F0 h
• 72-bit wide data write (64 bits plus 8 ECC bits). y9 P/ h' b$ {0 {7 r/ D$ g3 \& s
• Page erase (2 Kbyte), bank erase and mass erase (both banks) 6 Q5 [& l2 y2 n( [% h0 s8 O
从上述描述可以看出flash 的最小读写单位是64bit 8bit ECC,最小的编程单位是8byte,每个最小擦除单位为2kbyte,xml 配置和芯片手册里FLASH 的layout 布局是保持一致的。 P: l( J- Z5 q# c! o! j7 N+ D( ]
* y6 ?2 V& ]5 I2 {5 d. Q$ k
4. *.mac 文件格式说明 .mac 文件定义了 C-SPY 调用的宏函数,如下宏函数会在 flash loader 的不同阶段调用宏函数。 ' G" {0 X5 l. A
4 i @; d3 \- t% A9 T( D! }
| Ext. | Type of file | Output from | Input to | | mac | C-SPY macro definition | Text editor | C-SPY |
macro Specifies the path to a C-SPY macro file, which will be loaded in0 {2 E P/ r5 b: u
conjunction with downloading the flash loader. There are three C-SPY
' Z1 j: x. V! U' {macro functions that will be called automatically if they are defined in, i# V' m# r6 Z" v6 w
this macro file:
: x) ^3 V- l0 _9 u! _ c8 W0 MexecUserFlashInit is called immediately before loading the flash
4 j% X( F7 W0 p0 k9 X' N2 mloader.
! G) _( S' C# L7 ?execUserFlashReset is called immediately after the reset that
# Q! x/ _7 Q1 f$ s) p1 nfollows the loading of the flash loader.
: y) Y4 ~6 F6 e6 R& {- D6 HexecUserFlashExit is called immediately after flash loading has
/ z* g& o* Z* Vfinished, but before the flash loader is unloaded.
$ Y8 H2 ]3 N9 u* Y( nFlashSTM32L4xxx.mac 内容如下: - __var RCC_CFGR;
' j* E1 ^9 z" v6 m1 n - __var RCC_CR;
- p$ z( x6 n! N4 ?& N% y3 \ - __var RCC_CIR;# `7 |# P0 l% u" q f
- __var IWDG_PR;
; L3 {* D$ H T: L' K& g$ Y - __var IWDG_RLR;
$ \" i4 t- f' U) S; E% \ - __var FLASH_ACR;
( W' B; w6 @- s/ h7 i' c5 F9 v& X - ) \7 R% b+ h- V$ o4 m
- execUserFlashInit()" m+ f$ o7 O, A7 x5 m, y3 K! k6 `
- {
" L9 l$ E. a1 @' x0 |+ s - __var tmp;
( c2 P) e7 v9 e% _
5 O+ W- `; p D- __message "Entry execUserFlashInit";
* ]$ \; C( U8 X, g - , h. | i, O9 O& T" f
- //Stop watchdogs when CPU is halted
2 t+ z; [4 C* T" ^& \) O. ~1 x - __writeMemory32(__readMemory32(0xE0042008, "Memory") | 0x1800, 0xE0042008, "Memory");: }1 S/ M% [* n9 q# G! t
- , n" |6 c8 s0 b# p- O
- //Check if hardware watchdog is enabled
( N0 |" r. m* E% c; e9 l - if(!((1<<16) & __readMemory32(0x40022020,"Memory")))
1 P; a% b) w4 H+ m - {
% G- v! c8 U. N2 T: N' B - // wait PVU reset3 G9 U$ @) X) x" j2 g: ~
- while(0x3 & __readMemory32(0x4000300C,"Memory"));! ^7 P; ~ |) o$ k+ d5 S% q, }3 E0 Y
- IWDG_PR = __readMemory32(0x40003004, "Memory");2 B2 O" X5 F: {) V- r- z+ F" j
- IWDG_RLR = __readMemory32(0x40003008, "Memory");
7 ^) Y2 P( A% a$ | -
[9 v& ?8 R6 {: a- r% ? - // unlock WDT registers
8 Q, |2 K2 X9 c- H8 v9 \* L) a0 n - __writeMemory32(0x5555,0x40003000,"Memory");
a" H: j7 E; t$ h/ O- A - // Prescaler
, ~; @2 o ~2 @ - __writeMemory32(0x7,0x40003004,"Memory");
" `3 z! M, d( q) p - // Reload7 j# U8 [" ^% a! g4 p( `
- __writeMemory32(0xFFF,0x40003008,"Memory");
, X5 s- u: G6 t% o - // reload WDT) i k- Y' C! C# ]- v$ p! m
- __writeMemory32(0xAAAA,0x40003000,"Memory");
8 B. }7 o4 {. g0 C* u/ _7 }$ ?; S+ ^ - }, ^% ]( o1 Y' e0 I) M7 E, P+ J
2 E1 o- j8 i$ i6 G4 h1 `- RCC_CR = __readMemory32(0x40021000, "Memory");
% L# ^7 b& i( z' {9 s - RCC_CFGR = __readMemory32(0x40021008, "Memory");1 j' k4 {7 x% O7 V( q
- RCC_CIR = __readMemory32(0x40021018, "Memory");
3 f5 u3 G& S; G. H+ `) I - $ u y2 n( l" c3 V3 L
- /*Enable HSI16 oscilator and select it as system clock*/
\: ?" w4 T' z" b6 ^ - __writeMemory32(0x00000000, 0x40021018, "Memory"); // RCC_CIR = 0;
8 W- B. X4 q! u; v - __writeMemory32(RCC_CR | (1<<8), 0x40021000, "Memory"); // RCC_CR_HSION = 1;$ k, S1 |7 o9 J" H7 W% ]
- while(!((1<<10) & __readMemory32(0x40021000,"Memory")));2 Y- L3 \ ?- x* z
- tmp = (RCC_CFGR & ~(3<<0)) | (1<<0);
; P3 i' I; M5 H3 H% ^+ i( T - __writeMemory32(tmp, 0x40021008, "Memory"); // RCC_CFGR_SW = 1;
( M8 c; O0 Z% ] -
/ J6 Y/ }% m4 I, }% R0 a - FLASH_ACR = __readMemory32(0x40022000, "Memory");
9 K) s$ ~0 [( {7 @ - tmp = (FLASH_ACR & ~(0x7<<0)) | (2<<0);- Y" _- |' Z3 m: w3 u- M2 ]
- tmp &= ~(3<<9);
* H9 n% p% C, C, @$ G' m - __writeMemory32(tmp, 0x40022000, "Memory"); // 2 WS (3 CPU cycles) & disable caches
3 J+ z3 B. j- W- H& i - tmp |= (3<<11);
& k* t T! a( I; ] - __writeMemory32(tmp, 0x40022000, "Memory"); // reset caches
9 [( X3 }8 h7 p ^# ~: ^ -
) M4 Z# V1 [5 @- ?5 H - if ((0xFF & __readMemory32(0x40022020,"Memory")) != 0xAA)
3 u; p& W; z$ L# Q) ]3 x - {! q- k- W8 N4 C5 j6 I5 S5 y5 _8 f
- 1 V6 g4 u0 e- A
- if (!__messageBoxYesCancel("Do you want to perform mass erase to unlock the device?", "Unlocking device"))4 `7 D3 }6 k" r3 q* a2 O
- {0 G6 C6 G8 Q3 h! l8 ?
- __abortLaunch("Unlock cancelled. Debug session cannot continue.");
- M% P0 @2 `0 V% [4 p; l8 u1 B - }* |# \* F& S3 N. s4 Q3 O0 \8 I
- $ e" r' I. L; z: F9 F/ S+ l
- __writeMemory32(0x45670123, 0x40022008, "Memory"); // FLASH->FKEYR = FLASH_KEY1;
, t$ y* R+ ?8 [. @+ J4 H# Z - __writeMemory32(0xCDEF89AB, 0x40022008, "Memory"); // FLASH->FKEYR = FLASH_KEY2;
% T' ^* t6 ]0 N4 {, Y - // __writeMemory32(0x00000000, 0x40022000, "Memory"); // Flash 0 wait state$ j5 M+ e" c' g3 H# {! H0 N
- __writeMemory32(0x08192A3B, 0x4002200C, "Memory"); // FLASH->OPTKEYR = FLASH_OPTKEY1;2 W$ U+ W8 y0 D0 ` I- ^) ?
- __writeMemory32(0x4C5D6E7F, 0x4002200C, "Memory"); // FLASH->OPTKEYR = FLASH_OPTKEY2; . \$ ~! J3 o3 r1 P" w. ~3 |( L% u6 k
-
; A- N5 @7 D' b% J* J - __message "Setting FLASH readout protection level 0 (disabled)";
" _' K3 S, m+ q6 ~+ i - 9 k1 K: O5 u2 q) V, ^* F9 \
- __writeMemory32((__readMemory32(0x40022020,"Memory") & 0xFFFFFF00) | 0xAA, 0x40022020, "Memory"); // Disable readout protection. a/ U" ]6 e. n; o9 A2 J
-
: h1 ?9 n4 I/ v; \ - * N) I7 ?& p6 `3 G
- __writeMemory32((1<<17) | __readMemory32(0x40022014,"Memory"), 0x40022014, "Memory"); // Set the Options Start bit OPTSTRT9 v* f4 Z! {: Y
- ; C" {. A* ~7 h7 f0 u. x
- while((1<<16) & __readMemory32(0x40022010,"Memory")); // Wait while FLASH busy
* |$ J* Z% e7 d -
0 a: l/ K* h. i) I0 y - __writeMemory32((1<<27) | __readMemory32(0x40022014,"Memory"), 0x40022014, "Memory"); // Set the OBL_LAUNCH to Force the option byte loading/ D# W1 ~ b* A! z% ]7 A' X
-
# W5 b7 l9 \/ X! B8 u - }
( p- I4 c+ L: r3 h2 J - }
4 a' G5 r, }% J- o; }; k: r1 ~
: Q9 u) h H8 v O5 i- execUserFlashExit()/ Q9 h% I) Y7 N" i0 b
- {
( L' H- B4 b% G; J2 C" l - __message "Entry execUserFlashExit";2 M/ u% E* E/ d, [' ?5 o
- if(!((1<<16) & __readMemory32(0x40022020,"Memory")))
" ?6 S0 O" g5 e a - {
f4 w6 l6 e3 s% C! F# {) U - __writeMemory32(0x5555,0x40003000,"Memory");
/ B0 K! C; j! C9 E: f4 b. | - __writeMemory32(IWDG_PR,0x40003004,"Memory");
0 ^1 M* i* k- e* m" ^ - __writeMemory32(IWDG_RLR,0x40003008,"Memory");
6 h* _$ U; O( M& E& S7 O: G4 B - __writeMemory32(0xAAAA,0x40003000,"Memory");2 t% R$ p$ F. J& r
- }
- Y# `7 s0 J, g. b2 N% W5 f. |. M - 0 d* t- z' r- ]( M6 D9 \
- //Restore registers modified earlier
* {/ ?: T+ Y! l8 x% O2 Q' a$ r" _6 Y - __writeMemory32(RCC_CFGR, 0x40021008, "Memory");
+ c: F+ r1 D+ z5 d; D - __writeMemory32(RCC_CR, 0x40021000, "Memory");
/ ^' y% J; l& w; A7 ]. y2 J - __writeMemory32(RCC_CIR, 0x40021018, "Memory");
& G6 ?8 l$ T9 } D. t7 b$ F% Q
( L, x% ^: Z. s: f- __writeMemory32(FLASH_ACR, 0x40022000, "Memory"); 0 q( N$ y: o1 w$ V3 v% W; t
- }
复制代码
/ _6 t$ _1 W+ m# l从上述.mac 文件中定义了如下宏函数,并在入口中添加了打印输出:
( k- h9 }& ]: e; @5 B1 }5 l6 S6 cexecUserFlashInit()
& H+ y# E& |1 X, V `# \4 eexecUserFlashExit() " X# ]" H$ L$ S
. V1 l2 J) h1 a3 p U5.下载验证
; U7 }0 |. y4 T( w( P1 z, V5 dmacros 文件是可以被C-SPY 调用的执行文件,为了验证个人的猜想在execUserFlashInit 入口和出口追加了log 输出,来确认猜测是否正确。
" Q g s) C; R6 K) C( q( j/ E. b2 W" j& m有了上述的配置信息及flash 的初始化处理,flash loader程序就可以吧编译的二进制下载到板子上执行了。准备下环境验证下上述猜测是否正确。
. M7 d, x* o) \* X K4 g2 e7 C! c, |4 N* M' d' ~5 m& S
; A Y2 J" y4 ?- S1 U) R0 `从debug log 窗口可以发现mac 文件内定义的函数入口打印输出跟预期的是一致的,同时从log 个中也可以看出flash loader(FlashSTM32L4xxxRAM48K_DUALBANK.out) 程序是按照上述描述的方式被C-SPY 加载到目标系统。
y% y0 W3 r: C- Flash loader example9 r6 U0 `" c7 @. m6 e
- The following example shows the source code for a complete flash loader (except the source* Y* C4 w4 f, S: D
- code for the framework), but with a flash programming algorithm which simply copies bytes% R" y7 d# O) ?0 p
- from the RAM buffer to the destination address:1 T: z2 m3 X. v& H7 k! @* u5 P
- #include "flash_loader.h"
* s+ T7 b# s6 m( ~3 s - uint32_t FlashInit(void *base_of_flash, uint32_t image_size,
7 B0 C9 S" b4 r" U - uint32_t link_address, uint32_t flags)" m8 q1 y& S) h W, }
- {4 m, G* a, m1 t! \% H6 J6 g9 b
- return RESULT_OK;( {. G A5 r6 A% ^
- }6 F9 F. d R* ^
- uint32_t FlashWrite(void *block_start,& {5 A5 A: u" S4 J# x) k P3 \: A
- uint32_t offset_into_block,7 R D4 ?& X# T4 }
- uint32_t count,
# S' r: k" S2 K+ U/ L! r% z5 c - char const *buffer)
) c5 M3 `7 K- U4 m" X& g4 [/ w - {1 v2 V" L4 H; K6 m7 \3 _, ^& q3 K2 j
- char *to = (char*)block_start + offset_into_block;
( O5 S" D# J+ ?: j X* \6 c - while (count--)' B9 c) d$ i: Y, K5 Z6 ]
- {
* w: x# C# D- Y G" B! y - *to++ = *buffer++;
4 P8 Z1 q6 } x - }) p$ Q7 ]! ?" o' G3 @* @% ?/ M* {
- return RESULT_OK;
O/ M5 H# J3 R5 B - }! t3 {' C; m: y. p: M
- uint32_t FlashErase(void *block_start, uint32_t block_size)
) ^0 _) x. `* _: J. X - {: e% z& N5 u0 n# }% q* B% P" m
- char *p = (char*)block_start;8 y/ s4 n$ L8 z# z
- while (block_size--)2 [& N" s! R; X) `- g
- {5 K/ ]# {( B. G1 J1 g, u. ~
- *p++ = 0;3 F. Q& F7 ]+ ~0 Z8 b/ L, ?# @
- }+ f: [8 r; ^5 b; m. ~. X
- return RESULT_OK;% ^, U* ^7 G( D$ ~% p
- }+ {0 m8 `4 I3 f7 u/ j# t
- The parameters to FlashWrite and FlashErase, in combination with the flash memory base7 p& _: U% ], k& B* Z2 N/ U
- address given in FlashInit, fully specify the addresses of the portions of the flash memory to. X0 A, N H1 x# k# X. n
- be programmed. Thus, a given flash loader can be used for any number of different flash
, J/ T* f& R) b% J$ g! } F" j) m - devices, with different total size, page size, or block layout, provided that they all employ the
( Q% }9 n7 f$ |5 e3 h$ P - same flash programming algorithm. The flash memory configuration file (.flash) is used for
4 T2 b& M; D$ \ - specifying such variations between flash memories.
8 K3 v; h: C4 I% i4 D0 M - The reference section at the end of this document describes all framework functions in detail.
复制代码 9 ?4 b% I4 U; M
从上述flash loader 的示例程序中实现了FlashInit/FlashWrite/FlashErase 三个api 函数,我们可以objdump 下flash loader 程序看下内部是否是按照上述方式实现了对应的接口。 + h9 ?. u3 f3 p4 K" ]& k1 e' \
- FlashInit:* {9 l' B! G3 U$ o
- 0x200000c4: 0xb510 PUSH {R4, LR}
. t$ c5 M% ^. @/ ] - 0x200000c6: 0x494a LDR.N R1, `.text_8` ; flash_ie8 x$ z m; n: H) I6 f% D: w
- 0x200000c8: 0xf500 0x2200 ADD.W R2, R0, #524288 ; 0x80000
2 |: ?9 @9 R% S O/ x+ A - 0x200000cc: 0x604a STR R2, [R1, #0x4]* Y s: y! G- w; I% b9 ~: N
- 0x200000ce: 0x2300 MOVS R3, #0
( [# s6 q- V- N& Q0 m+ a7 | - 0x200000d0: 0x2200 MOVS R2, #0. B: J# o6 \* N# R% Q! u: [: w& S C
- 0x200000d2: 0x700a STRB R2, [R1]) ]: ~9 B& t7 j- z# |
- 0x200000d4: 0x9a02 LDR R2, [SP, #0x8]
9 C) G% K; @) E, M! l - 0x200000d6: 0xe000 B.N @200000da
6 ^4 f5 R- b9 ?9 t8 `; l0 J+ ~ - @200000d8:5 O) @( S4 E9 a$ J9 O
- 0x200000d8: 0x1c5b ADDS R3, R3, #1
( Y8 V- H( v) O/ }9 ] - @200000da:+ ^& c$ X* u9 P2 _6 y
- 0x200000da: 0x4293 CMP R3, R2
) H* n0 p, C& g2 K! u1 H2 b5 s6 C - 0x200000dc: 0xdbfc BLT.N @200000d8! x$ l3 U* q* _* n
- 0x200000de: 0x4a45 LDR.N R2, `.text_9` ; 0x40022008 (1073881096)
/ d6 b& q% d# g' ]- Z - 0x200000e0: 0x6993 LDR R3, [R2, #0x18]
8 }3 a! ~% u5 {) }0 B - 0x200000e2: 0x029b LSLS R3, R3, #10$ a; s- p- a. h( H
- 0x200000e4: 0xd507 BPL.N @200000f6- M+ B- I9 w5 X3 f, f
- 0x200000e6: 0x4b44 LDR.N R3, `.text_10` ; 0x1fff75e0 (536835552)
2 D6 g: Y' _8 | - 0x200000e8: 0x4c44 LDR.N R4, `.text_11` ; 0x3ffc00 (4193280), p/ b2 U3 ?, }/ l
- 0x200000ea: 0x881b LDRH R3, [R3]
0 s& w5 m5 h0 Y# r4 D3 K1 q4 R - 0x200000ec: 0xea04 0x2383 AND.W R3, R4, R3, LSL #10( W- b( k/ u# t% N" E8 p
- 0x200000f0: 0xeb00 0x0063 ADD.W R0, R0, R3, ASR #1
* L. n8 I& _& V' `, E$ t - 0x200000f4: 0x6048 STR R0, [R1, #0x4]# o( k( _$ u( I# |& C8 _# r
- @200000f6:6 h9 j' N8 X+ O9 e) n, W, c' _9 W
- 0x200000f6: 0x4842 LDR.N R0, `.text_12` ; 0xe000e100 (-536813312)
1 S+ v1 ]/ q5 K+ C. e - 0x200000f8: 0x4b42 LDR.N R3, `.text_13` ; 0xe000e180 (-536813184); L; @/ A. `- b) |
- 0x200000fa: 0x6800 LDR R0, [R0]: c. c* k8 a* v. P, b
- 0x200000fc: 0x06c0 LSLS R0, R0, #27
% p6 c& p2 p$ f3 l. u; h; ?; W - 0x200000fe: 0xbf44 ITT MI Z7 }% r3 Q0 A
- 0x20000100: 0x2001 MOVMI R0, #1
^- a: ]! I; C - 0x20000102: 0x7008 STRBMI R0, [R1]3 [3 v6 @4 h! h' ~1 ]" x- R8 m
- 0x20000104: 0x2010 MOVS R0, #16 ; 0x106 u) P+ i* T- R; m& _
- 0x20000106: 0x6018 STR R0, [R3]
4 v4 _3 M! |: Z4 A% C! D0 P - 0x20000108: 0x4b3f LDR.N R3, `.text_14` ; 0xc7000ff8 (-956297224)
. R; ?' G( Y& x - 0x2000010a: 0x68d0 LDR R0, [R2, #0xc]
. G, i: x" V3 d0 M8 q - 0x2000010c: 0x4018 ANDS R0, R0, R3" c T+ ]9 y- F6 s8 @# V6 {0 w5 _) D7 X4 B
- 0x2000010e: 0x6088 STR R0, [R1, #0x8]
2 n, b( K" y2 E, J* e4 E7 M - 0x20000110: 0x483e LDR.N R0, `.text_15` ; 0x45670123 (1164378403)* I& T- D& e% G, d8 A
- 0x20000112: 0x6010 STR R0, [R2] H4 j$ i& s# o# h Q( U
- 0x20000114: 0x483e LDR.N R0, `.text_16` ; 0xcdef89ab (-839939669)
8 m3 i& w& o. \) w7 {7 c - 0x20000116: 0x6010 STR R0, [R2]+ [; K& a8 x, k: a
- 0x20000118: 0x68d0 LDR R0, [R2, #0xc]
* C$ ]; @# C9 C( |; u- T - 0x2000011a: 0xf020 0x60c0 BIC.W R0, R0, #100663296 ; 0x6000000
( b% w6 }3 Q+ x& F. q6 Q - 0x2000011e: 0x60d0 STR R0, [R2, #0xc]% q+ H; G9 P+ O* E
- 0x20000120: 0x68d0 LDR R0, [R2, #0xc]
0 h; Y5 h7 w3 n6 X" S - 0x20000122: 0xf040 0x7080 ORR.W R0, R0, #16777216 ; 0x1000000
* |5 E2 j% X1 S1 n0 i1 B - 0x20000126: 0x60d0 STR R0, [R2, #0xc]
; F1 `! } o# U, Z2 m0 E" `" V; i. g2 e - @20000128:
! V( P1 E6 Z J0 G+ U" S" }2 g - 0x20000128: 0x6890 LDR R0, [R2, #0x8]
& q X1 P* }/ i! |; z# H - 0x2000012a: 0x03c0 LSLS R0, R0, #15
% m( q: K" k9 I) \ - 0x2000012c: 0xd4fc BMI.N @20000128
3 k* e5 Y" t0 }! D( P - 0x2000012e: 0x2000 MOVS R0, #0
5 A% a+ b( i! Q0 i" D) N - 0x20000130: 0xbd10 POP {R4, PC}& @% P: Z! z5 C
- `.text_5`:
. S( A9 F k' [9 N" B8 t - FlashWrite:; o3 |0 q6 `7 x; A1 o; [, ]( v0 B
- 0x20000132: 0xb5f0 PUSH {R4-R7, LR}
9 Q5 o% F, z p( r- ]9 v - 0x20000134: 0xf240 0x15ff MOVW R5, #511 ; 0x1ff/ d8 R" f4 e* w. W
- 0x20000138: 0x1844 ADDS R4, R0, R1
' ~2 x* R" B% {$ U) ?7 ~$ f* I3 _ - 0x2000013a: 0x4936 LDR.N R1, `.text_17` ; 0x40022010 (1073881104)1 x8 f7 m; i5 Q0 z5 a
- 0x2000013c: 0x600d STR R5, [R1]
+ N7 H6 k! K8 B# D; T* Z- t8 @ - 0x2000013e: 0x2000 MOVS R0, #0- Z" U$ x3 v$ h
- 0x20000140: 0x684d LDR R5, [R1, #0x4]9 P& t. E/ D* Q2 j. b1 F
- 0x20000142: 0xf045 0x0501 ORR.W R5, R5, #1$ v; l* w; w$ w1 k+ ~
- 0x20000146: 0x604d STR R5, [R1, #0x4]8 P" C3 p% X( t- m- d7 V5 \1 l9 k
- 0x20000148: 0xe000 B.N @2000014c. a4 e% r3 @, B$ x
- @2000014a:
4 {. I& c6 e, D0 t - 0x2000014a: 0x3a08 SUBS R2, R2, #8
* y m: M0 z9 o( W3 \ - @2000014c:$ O' M8 a# |- g/ q/ [" u6 c- _
- 0x2000014c: 0xb162 CBZ R2, @20000168
. O+ w! H$ F5 k' j' U' z: [ - 0x2000014e: 0xe8f3 0x6702 LDRD R6, R7, [R3], #0x8+ E! r) @: m5 Z6 g3 g2 ^
- 0x20000152: 0xe8e4 0x6702 STRD R6, R7, [R4], #0x8
$ B* N. ?( W5 x u- N+ y P - 0x20000156: 0xbf00 NOP
+ T/ a/ t; \* @4 K3 H: y/ T. |- L - 0x20000158: 0xbf00 NOP. d0 @" @. s; n. [- ~2 k3 k
- @2000015a:
4 c4 A' t. s' T( ]9 W8 H+ k - 0x2000015a: 0x680d LDR R5, [R1]
- c$ M3 U4 m) I8 x - 0x2000015c: 0x03ed LSLS R5, R5, #15& J ]' K/ B1 n0 \+ f( E' r
- 0x2000015e: 0xd4fc BMI.N @2000015a2 M m$ d* R; b, h0 ?2 U7 U
- 0x20000160: 0x680d LDR R5, [R1]
+ ?" B( E s* c: q" w2 r - 0x20000162: 0x07ed LSLS R5, R5, #31& F. ?2 o1 W0 M. u8 E& Q$ _, x' u
- 0x20000164: 0xd4f1 BMI.N @2000014a
# A8 M4 j6 P: T% U+ E - 0x20000166: 0x2001 MOVS R0, #1
4 u0 m \* l0 K% f3 j& c/ J) y( V5 Q - @20000168:
5 | K8 N% j! Y6 |- _$ a - 0x20000168: 0x684a LDR R2, [R1, #0x4]3 d( h+ H! n/ c6 c9 c
- 0x2000016a: 0x0852 LSRS R2, R2, #1% ]; u$ W6 p. a0 G
- 0x2000016c: 0x0052 LSLS R2, R2, #1' _7 n6 _* Y+ q3 y4 E
- 0x2000016e: 0x604a STR R2, [R1, #0x4]/ A9 x: @& K# s( P. R$ u7 F9 V' h
- 0x20000170: 0xbdf0 POP {R4-R7, PC}
( z& l, F. j' a3 Q s1 e; N+ M - `.text_6`:7 N' l3 C! P( u" s4 {8 v, ^# G
- FlashErase:
; ^+ _$ c/ {% C" h y6 c5 m5 S2 u - 0x20000172: 0x4a28 LDR.N R2, `.text_17` ; 0x40022010 (1073881104)
( c Y* \8 ?* x+ a l$ [ v) i. e Y - 0x20000174: 0xf240 0x13ff MOVW R3, #511 ; 0x1ff/ e5 I" ~' \3 ]" f- O$ }/ \
- 0x20000178: 0x6013 STR R3, [R2], {# m! |! F( L% b; e
- 0x2000017a: 0x4601 MOV R1, R0
) K* S. {7 t' n/ a8 o. o( a- R - 0x2000017c: 0x6853 LDR R3, [R2, #0x4]$ b6 E5 }; t/ [6 V
- 0x2000017e: 0xf36f 0x03cb BFC R3, #3, #9
* M9 X7 d. F5 O* i1 g - 0x20000182: 0x6053 STR R3, [R2, #0x4]
7 d; z6 B: Y8 m3 O - 0x20000184: 0x2000 MOVS R0, #0# s1 c# T A' X4 q6 `# N
- 0x20000186: 0x4b1a LDR.N R3, `.text_8` ; flash_ie
! J8 D: N) H# S( T7 w: N8 {% I Z, D# a - 0x20000188: 0x685b LDR R3, [R3, #0x4]
Q( X& `. U, i2 U( y( D) H - 0x2000018a: 0x4299 CMP R1, R3
9 z/ e/ u* _( N1 P+ M" ~ - 0x2000018c: 0xd203 BCS.N @20000196
?2 j9 W* J9 v9 |; q' n - 0x2000018e: 0x0a09 LSRS R1, R1, #8
, @; i$ G5 x; i& q1 C5 e- W" [ - 0x20000190: 0xf401 0x61ff AND.W R1, R1, #2040 ; 0x7f86 X B6 N S& Q5 R
- 0x20000194: 0xe007 B.N @200001a6; y2 ~9 v; ?$ \1 Q* d% J
- @20000196:
$ O" [* m6 {* ~3 s& G - 0x20000196: 0x1ac9 SUBS R1, R1, R3' ]3 q. v- u4 V
- 0x20000198: 0x6853 LDR R3, [R2, #0x4]9 T. l8 H- d) N2 m; _
- 0x2000019a: 0x0a09 LSRS R1, R1, #8/ S, k+ ^. j* N
- 0x2000019c: 0xf443 0x6300 ORR.W R3, R3, #2048 ; 0x800
. i& }) E8 U' \4 F - 0x200001a0: 0xf401 0x61ff AND.W R1, R1, #2040 ; 0x7f8
" z/ U$ h% H+ O5 ^ - 0x200001a4: 0x6053 STR R3, [R2, #0x4]
7 i9 W F/ I, t - @200001a6:
" w/ G4 b" B: ~' I: @* g( m - 0x200001a6: 0xf041 0x0102 ORR.W R1, R1, #2- \# Z0 `0 z1 Z1 N, [
- 0x200001aa: 0x6853 LDR R3, [R2, #0x4]
* |2 g% z4 y7 d% C1 u. j. i - 0x200001ac: 0x4319 ORRS R1, R1, R3; q, D# q' o" q* W
- 0x200001ae: 0x6051 STR R1, [R2, #0x4]
( j6 ~" s( l, x9 a$ g9 s# h - 0x200001b0: 0x6851 LDR R1, [R2, #0x4]
3 ?2 L" S! r5 d- B% m' x9 W5 { - 0x200001b2: 0xf441 0x3180 ORR.W R1, R1, #65536 ; 0x100003 g7 P! w( a H) Z2 l0 q
- 0x200001b6: 0x6051 STR R1, [R2, #0x4]" M; w: U! f; C8 T5 ~: M8 a
- 0x200001b8: 0xbf00 NOP
1 K+ N. R: P1 ~) f - 0x200001ba: 0xbf00 NOP8 S$ v% ?3 X& [" G" P' y; M0 r
- @200001bc:; q* C6 V( G( X. @7 o6 n( o5 Q
- 0x200001bc: 0x6811 LDR R1, [R2]
* S/ P% z; S9 L1 f0 J - 0x200001be: 0x03c9 LSLS R1, R1, #15
# Y$ D7 Q$ M0 L# ?- O% Q- P - 0x200001c0: 0xd4fc BMI.N @200001bc# z7 A3 d% v& R X* R
- 0x200001c2: 0x6811 LDR R1, [R2]
! O4 W: U& B: G% W) A. N+ t - 0x200001c4: 0x07c9 LSLS R1, R1, #31
% M7 w) N( @4 l; g - 0x200001c6: 0x6851 LDR R1, [R2, #0x4]% u" v: n1 ~ U
- 0x200001c8: 0xf021 0x0102 BIC.W R1, R1, #28 B E7 N& g2 Z7 {
- 0x200001cc: 0xbf58 IT PL6 R5 w' }2 }- [8 X4 z% w+ x, T
- 0x200001ce: 0x2001 MOVPL R0, #1# H' T8 f5 l1 s9 ~/ O
- 0x200001d0: 0x6051 STR R1, [R2, #0x4]0 n* a4 N, A6 A0 `+ x, [: L
- 0x200001d2: 0x4770 BX LR
复制代码
# K: K- y# @1 {2 m8 }4 M1 S* x9 c上述通过 ielfdumparm.exe FlashSTM32L4xxxRAM48K_DUALBANK.out -o FlashSTM32L4xxxRAM48K_DUALBANK.ASM --code 命令dump 出来的flash loader 程序,跟预期的保持一致实现了FlashInit/FlashWrite/FlashErase 这组API函数,而且通过反汇编的函数地址信息也可以看出对应的函数的link 地址并不是falsh 区域而是内部RAM 的地址,跟C-SPY 调用flash loader 程序的流程是一致的。
3 R6 H( F9 o" w7 z# x# N6 l
/ D2 h' K2 G% x6 c4 l4 l3 O+ e |