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