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