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