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