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