文将针对STML152的IAP移植过程作一个笔记。
& K# T7 g4 p: o4 w% U
7 k, V! z+ E" C, Q* J( ^" A首先得下载AN3310的示例代码,地址为:http://www.st.com/content/st_com ... /stsw-stm32075.html7 K1 f/ l0 E# d( Q) v; e; l
% J3 d# Z, S; _5 j% t9 t' `! g
下载完成后,我们需要做些修改,我们将在NUCLEO-L152RE板子上进行验证测试。2 i, N! e1 F, m0 U$ [/ K$ ]
/ M; Z( F i0 ^4 }% ?6 ~
由于NUCLEO-L152RE板子默认MCU是没有外挂晶振的,但可以通过ByPass方式使用ST-LInk的8M晶振,但这里只是作为IAP,且只需要使用到串口,因此可以只使用HSI,于是,在AN3310的工程中打开system_stm32l1xx.c文件找到SystemInit函数,注释掉//SetSysClock();,让系统使用默认的HSI即可。6 R6 [/ O: v/ o/ J* O* `) n
- [cpp] view plain copy
; [8 }, t$ X$ k9 `9 ^ - void SystemInit (void)
* M4 [4 P- s; S. v% y$ B - { 9 O" \' ]" `7 M' C$ _
- /*!< Set MSION bit */ # Y1 J2 l7 g, F* j$ e% v
- RCC->CR |= (uint32_t)0x00000100;
5 Q I9 t2 j- r - ! X2 g$ ^! L' b# D. f7 P: E( {
- /*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */
9 u, d! ]& c1 T1 u% S - RCC->CFGR &= (uint32_t)0x88FFC00C;
+ O* r/ [2 k* d! | - $ g/ J5 B; d) n* q) A4 z( }6 Y5 Q
- /*!< Reset HSION, HSEON, CSSON and PLLON bits */ 0 [7 Q8 H) _+ e* U; Q _
- RCC->CR &= (uint32_t)0xEEFEFFFE;
3 f @0 n) m- F- w3 ~( _8 T -
1 b: Q9 {) U4 n) p - /*!< Reset HSEBYP bit */ 7 V, e8 d4 m4 B/ W/ Z
- RCC->CR &= (uint32_t)0xFFFBFFFF;
: z4 L0 t+ H( u- l0 u1 _( R8 ]7 g: ?/ C - ( z! l8 h3 L. O/ U' [' w
- /*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */ ) b5 g+ @6 A8 T3 x) q7 e! E9 V
- RCC->CFGR &= (uint32_t)0xFF02FFFF; , X- }) S7 C8 \3 P
-
+ g* @: \4 D. K2 k( E; Z - /*!< Disable all interrupts */ & _' n+ F' T+ E2 n
- RCC->CIR = 0x00000000; ) Y# G% W5 E, \! K: X2 C
-
2 [, N* M8 {, i& m6 ~) n - #ifdef DATA_IN_ExtSRAM 4 C1 [: K$ T5 p& _' s0 ?& O
- SystemInit_ExtMemCtl();
2 P6 n n) f- _$ ~ - #endif /* DATA_IN_ExtSRAM */
) V4 P) k) M+ B! R% D! u& l - + D) G+ x- B. F
- /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */ ! ~8 }2 i; _! C" y2 o
- //SetSysClock();
5 ^% `& W# G( f+ J - 8 G) L- S' B* J: t6 k* b
- #ifdef VECT_TAB_SRAM * G! X( }2 K9 a: s# g" I
- SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
# X- Z" h3 E3 v5 U7 M2 A% [; D( ` - #else
- i! r9 F- y8 y4 f1 I1 ?- o - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
# n M# g5 J8 M - #endif
# [$ ^! `" D q4 n0 g+ J+ g# B - }
复制代码 然后修改man.c文件中的main函数,注释掉一些按键,让程序默认进入到升级模式:
" T' z( N) g, E5 d. W- K) d# A* x; }1 m) @4 a) Y: P7 Y9 R4 G
- [cpp] view plain copy
5 N' ?' q4 ]; U2 Z - int main(void)
1 o# |) g4 D) W: D$ a& P7 B# [9 h - { 6 C2 p. x: c" B& e
- /* Unlock the Flash Program Erase controller */ / o7 h/ B) n/ K I8 f
- FLASH_If_Init();
- j! _& A& I3 d4 `* o4 q8 R' \ - ; I& G$ a. Q2 n' V& d$ U
- /* Initialize Key Button mounted on STM32L15xx-EVAL board */ & m/ u. @" Q- r) B
- //STM_EVAL_PBInit(BUTTON_KEY, BUTTON_MODE_GPIO); $ R! O; @' M3 m* y, z6 a# M
-
$ W: B8 j4 g; p/ j5 ~/ {% Z+ O - /* Test if Key push-button on STM32L15xx-EVAL Board is pressed */
& Z. B; j2 ]* j! S - //if (STM_EVAL_PBGetState(BUTTON_KEY) != 0x00) 5 S- ]0 R7 O5 z: \
- {
' X: |1 m: W" }2 j$ Q - /* Execute the IAP driver in order to reprogram the Flash */ . V$ A0 p" e8 X5 Y1 `- G& w& `5 |
- IAP_Init();
& o: N# C8 Z# d - /* Display main menu */ 2 ]- Z$ @% ` T7 f; L5 I, t
- Main_Menu (); : n: g( n8 J4 B
- }
# e4 r+ E @$ | {, Q - #if 0 $ J- D, H' q/ C6 |" M+ L
- /* Keep the user application running */ 0 V* U6 r4 ?; \* r; ^! U7 i
- else 4 m8 n0 E0 ^1 o8 Q$ g$ }1 P
- {
. q2 b2 N+ t& ~) J4 w; L% ?- \ - /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */ $ x- r! C. `# D4 A/ Q) I
- if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000) : q9 H& _6 w! c! F' B) X
- {
* h" D/ d! Y. Y( o) I - /* Jump to user application */ + A) ?5 F- [% j4 l" R7 F
- JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
0 `5 p0 r+ n5 L0 ~: [ - Jump_To_Application = (pFunction) JumpAddress; 3 A# ]3 S# t5 t' ]
- /* Initialize user application's Stack Pointer */ ?5 L$ U! z) T( ^$ A$ L' V
- __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); 8 [5 C: r, q- @9 X' |; M
- Jump_To_Application();
) _$ G1 S Z3 Q$ t, T( F3 [4 X - } 6 p. A# S# s' M* p- R- w
- } 8 m& Z9 H& t% |3 c/ n0 Y
- #endif 9 {8 p( [/ Z7 M) ?3 m4 [
- while (1)
. Q# V! M. ]) q& l. ]6 \0 s K - {} 1 i q0 M! [+ q$ {) j; Q0 L
- } 1 H9 `8 R. [ ]# s) b0 O! I
复制代码 由于NUCLEO板子默认使用的是USART2,因此需要修改使用的串口:( b6 N5 }* k$ I
- [cpp] view plain copy
, `! i4 }8 `7 [ ?7 W+ N - void IAP_Init(void)
8 B9 i( U% L3 S6 ~' D - {
+ s3 I1 M1 k; v! z* k. s - USART_InitTypeDef USART_InitStructure;
0 p9 k( N9 J! R! A - /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/ + \ g/ u) f5 F7 n/ K; L2 g7 r# ]
- /* USART configured as follow:
2 ^" C/ w4 D0 A - - BaudRate = 115200 baud 9 u4 d4 W- e5 w' g9 o
- - Word Length = 8 Bits ) t( Y- l" z2 l& N/ R
- - One Stop Bit
/ u1 ~$ ^# M) U$ j/ Z - - No parity & |5 F \+ w F. \
- - Hardware flow control disabled (RTS and CTS signals)
% a5 X% N1 O& o9 I6 i, q - - Receive and transmit enabled
+ N/ s9 c! {. s- ]! e. b+ [ q4 M - */
/ N( A+ k& [* J6 ` - USART_InitStructure.USART_BaudRate = 115200;
1 z$ f2 K( w2 D( X* Q- s - USART_InitStructure.USART_WordLength = USART_WordLength_8b;
V2 d: ?: z" t& x - USART_InitStructure.USART_StopBits = USART_StopBits_1;
% S& V, l3 B' f" @! b' I4 B - USART_InitStructure.USART_Parity = USART_Parity_No; . I, A1 h5 x. Q
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
9 m, y5 O: G! W1 p6 L( t6 O5 U - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; " g( g; a5 P4 \8 g h
-
% C4 q- C4 V$ v* G; d3 m - //STM_EVAL_COMInit(COM2, &USART_InitStructure);
^3 @' p. S+ m - USART2_Init(&USART_InitStructure);
+ {7 Y! G* V! D$ ^- w - }
1 k# e- H: O) [- I7 {. x( a! h2 P - ! V) r& q$ Y* t6 |' o, A
- USART2_Init()函数为新添加的串口初始化函数,其定义如下:+ S- p! R7 K- l. G
' j5 }# {5 R" N! v; V- [cpp] view plain copy. ?+ M" Y+ u/ ?& ]
- void USART2_Init(USART_InitTypeDef* USART_InitStruct) 5 J2 l3 D+ a0 c- L, v2 N, B& [4 P. x
- { * n) T# E7 |0 H$ T
- GPIO_InitTypeDef GPIO_InitStructure; 5 r8 V4 Z# O& ]
-
; K; E) x4 X4 s! i8 H5 S. ~ - /* Enable GPIO clock */
* O; O8 I5 h( e) g2 ?: } W9 x( v$ k - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); ; T0 k7 z/ \5 m2 P0 u$ n
- 8 T( E6 {, c9 f, N8 P
- /* Enable UART clock */
" b" }1 T! h8 Y$ m - RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); 5 v: G$ A- u2 U, M
-
! y5 S* y) U9 Z5 |' v" k - /* Connect PXx to USARTx_Tx */ * g4 Z3 ~6 T* c0 K/ O
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
8 q- C7 ~4 H1 B) M0 S5 Y - 0 D y/ o* ^, N. ?
- /* Connect PXx to USARTx_Rx */ 3 U5 A) J2 E+ K- N' W$ a" W
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
; f ?& \5 \( V' F( w2 b, R5 { -
" _3 }9 y6 ~3 d% ` - /* Configure USART Tx as alternate function push-pull */
$ h7 }7 b- G- Y0 r+ Y - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3; & W9 z; a, k9 Y- @! J8 y( Q
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
4 T& p/ p5 f( L2 _. a" N6 V+ H" f - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
+ Q+ A5 y; _. ~) P+ c' q, ] - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
! |; e7 b! p( s, ?; | - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
0 P- A) K1 \. T/ K - GPIO_Init(GPIOA, &GPIO_InitStructure);
2 A. k5 Z$ B. H0 H. {. f: U - 4 |* A* s# K$ Y5 G) a& F
- /* Configure USART Rx as alternate function push-pull */ " Q2 _4 l! w1 u2 G9 m) P0 {
- //GPIO_InitStructure.GPIO_Pin = COM_RX_PIN[COM]; . `8 H) a" j$ O) U6 [ K+ C5 ]
- //GPIO_Init(COM_RX_PORT[COM], &GPIO_InitStructure);
/ l, k9 y/ k$ J" n$ B* I, I, { -
( `7 T9 V4 o, ^/ `- R - /* USART configuration */ 2 o$ S9 x8 C5 v# a
- USART_Init(USART2, USART_InitStruct); _; r) j1 W! `& m
-
& C$ O& K' g( p/ _; t( \9 i - /* Enable USART */ ) F; U& M1 t4 y" c) N
- USART_Cmd(USART2, ENABLE);
1 F) J% |1 t# r. P+ p# C' T& w2 g - }
复制代码 接下来需要修改程序中使用到的打印函数:
i, Y! V: K1 Q$ {- t, ?' G- u3 @4 c- [cpp] view plain copy
! w4 B: p. a. G% a" M/ [# w - void SerialPutChar(uint8_t c) + H F: Y: x b8 k9 i% U9 c
- { ) Z0 c# ?0 P5 u' u2 \
- USART_SendData(USART2, c); & `+ |" s" @: s& m8 o. J- B _- h
- while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
" h- ^% Y; B6 ]' F1 j) w - { 1 T$ N; W0 I& I% g
- } 2 I5 U7 _1 }% ~( \8 u, F- q
- }
5 ?; [, L* \- m: r
8 x! K) B/ ^% Q. t
9 A p! W) r. `/ q7 ^- [cpp] view plain copy- S! E7 I" f' `4 X
- uint32_t SerialKeyPressed(uint8_t *key)
% r& {! v3 y [ - { . U3 e+ \; o& J) _) l
- * z; N* _' K9 r2 R6 O+ r. H
- if ( USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET) / `- i/ ^, E; @. b3 N# Z6 W
- { 7 y& h1 Q) t8 R
- *key = (uint8_t)USART2->DR; $ T' G9 b* y0 w! F, A1 o
- return 1;
% a' x4 j7 N9 @1 e - }
3 G$ p: G A) a# j" `: O - else
4 f9 d* E) f0 a( `# g7 z" g - { ) s" P$ R1 Y* C+ F+ f
- return 0;
9 b! }# c; `" ]4 b4 D# n- c4 W - } " {3 w9 Z( t" Z T# F8 ?9 I# U
- }
! c0 m! g5 I/ y
复制代码 基本上就移植好了,编译烧录进NUCLEO板中运行。4 ?! ?5 T0 U7 N* Q8 o8 K" k5 {
% |# K+ F( g+ q" V# k
接下来需要找一个PC端软件超级终端。- |4 [$ u% |4 Y( S3 f
除了IAP程序,我们还得准备APP程序,由于IAP支持烧录的是BIN文件,因此,我们得生成BIN文件,HEX是不行的。
% L5 o( [' K5 P" ^/ m( {& q6 x4 e! V7 g+ y X4 E2 u {$ `
在APP工程中我们得注意几项内容,以IAR为例:3 j& t, C2 i7 b- H' i
! F7 o( u$ } x4 g' u9 x$ S
1 在option->Linker下:! {3 O u+ e/ g
, u! u# }7 F! u+ z config->Edit..--->Vector Table 的起始地址改为:0x08003000
: p4 X3 f: e& Q& _. y M, r; \5 f- ^8 X8 r) N1 x9 |. Y. g6 A
---->Memory Regions->ROM改为:0x08003000
. ]1 O4 a# `7 Y+ ?2 ]4 [7 v# F$ C1 c" s6 m! G1 L
2 option->Output Converter->修改生成BIN文件
: g& c/ B! F9 n+ H) G' ]5 a" h0 R/ U4 A3 `# r, {3 `
3 sysytem_stm32l1xx.c文件下
# F. J$ @2 F# o
+ N" E* V5 T8 [$ |' j7 c4 z 找到宏定义1 L5 P% b9 ?) [
) X. N r( i# p" Z+ d9 P. h9 B- ^
#define VECT_TAB_OFFSET 0x30007 |3 W- [, G0 [9 _9 A9 d
6 t+ y6 e' R5 q
偏移位置必须改为0x3000+ A M( B9 n% p! I
! e8 U; C1 T6 Q( V$ F( X
到此基本可以了,APP就这样。: o0 ]7 g+ w8 L3 Q; R
. M" h8 l! Y& {% @& W ^" F" ~& [最后就是测试了。* E( _. ]8 F& v! T2 J* U) }
/ N1 C: N( r* D4 n
测试:
5 P7 A2 F/ y p, S* w9 A8 f9 j# H: q
Q" N3 \* J7 U2 q6 t! j" C首先得将IAP烧录进MCU,然后再通过IAP烧录APP。1 s! I4 f5 n. J, j% T: v, X! {
2 t S1 n a/ d% H; i5 J
通过IAP烧录APP过程如下:+ T: q0 S' Z* G$ L
: W% z, y8 \. P打开超级终端,连接上串口,有如下界面:. J0 d) e6 B9 o( u& h$ d# m
, |6 Q& X, m3 w5 P
波特率:115200 data bis:8 parity:none stop bits:1 Flow control:none- d# N: N! T+ `: L0 I3 v- ?
% @. T5 u- j3 J+ ]/ u
8 f- h4 K* h* E
$ G! d8 ~- N5 D9 j通过键盘输入1:
! I, |! [* X( w# a
) C; o) S% v7 w; J% Y: e
: u6 ? \; \: K2 B q
' S0 N I5 Z3 @5 D6 @! U
从菜单transfer->Send file打开如下界面,输入APP的BIN文件路径,并使用Ymodem传输协议,如下图:
5 K3 a; }" V4 c( }; i! ~7 F6 S& J0 T
, z6 U( e6 x8 V7 J) b \# I# j2 w
! A A$ x; E" C& }$ @. W9 }
8 R: p9 K5 ]! ^$ j6 e点击Send,开始烧录。。。
* x$ G' N8 q8 F! t& Q4 s# X
- Y c( A* K$ Y: _8 I$ E$ r
7 I& K& r; Y! j$ e1 \0 f/ w" _2 d; s
! i3 L9 B$ m5 G1 g
传输结束后,按下3,运行APP程序,至此,整个IAP与APP都可以正常工作了。% G; r0 U% P6 `# u
/ C( O& r4 J. n4 j& i+ i; O L结束语:
) g& b1 d7 O# o' H# m5 A9 n9 Q' ?, }& |; C8 q% d" H |' X( ]4 K
这个只是个示例,实际IAP是还需要修改的,得判断是进行升级模式还是直接跳过进入APP,这个就需要看设计如何了。$ Z1 }6 \( A. Q, T1 {- q( K
7 _, J$ x4 z0 {8 t- u4 H
! E1 F: _ P- U% V( R( E% ?0 g h$ u3 C8 K) k; |$ I$ P
! U$ Y/ n D0 x4 z
转载自flydream05 o E/ L( z4 d+ {
5 ^) ?% {. |0 I7 T" p1 G, \
7 j. Z' U! `! i, Z0 g+ F# i$ H
% d: t) N+ m1 [6 m9 \ |