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