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