文将针对STML152的IAP移植过程作一个笔记。
' l; H4 i' o8 V2 G' j% j
: r; `1 w4 b0 X8 h) a+ ?: ]首先得下载AN3310的示例代码,地址为:http://www.st.com/content/st_com ... /stsw-stm32075.html
, ~9 ] ~7 u4 E) ~" U
8 ]: u5 h. \, e" m m' N& b下载完成后,我们需要做些修改,我们将在NUCLEO-L152RE板子上进行验证测试。, d4 _+ J/ Q6 [# ~& d; |' y
2 i) x" }7 Y, Y8 O
由于NUCLEO-L152RE板子默认MCU是没有外挂晶振的,但可以通过ByPass方式使用ST-LInk的8M晶振,但这里只是作为IAP,且只需要使用到串口,因此可以只使用HSI,于是,在AN3310的工程中打开system_stm32l1xx.c文件找到SystemInit函数,注释掉//SetSysClock();,让系统使用默认的HSI即可。9 \ _1 `. p! x
- [cpp] view plain copy5 c! \/ w( i$ c- K: n5 b+ s6 q& j
- void SystemInit (void)
3 ?/ k( y7 R1 X% _8 K# g - {
2 ]( j8 y! ?# i% _/ O - /*!< Set MSION bit */
7 A- l: j( a$ v5 U% R - RCC->CR |= (uint32_t)0x00000100; ' y1 ]- t* z7 B* Q# n: u# ]
- v* N* a8 M- @4 }0 p7 W. Q
- /*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */ ) f6 y& ^( f$ K$ X" k5 |/ v
- RCC->CFGR &= (uint32_t)0x88FFC00C;
7 H* c! f6 z6 m( |$ `0 V -
3 {% l6 |7 @8 A" I8 x - /*!< Reset HSION, HSEON, CSSON and PLLON bits */ ; U1 K* y7 {/ O# d
- RCC->CR &= (uint32_t)0xEEFEFFFE; 2 [2 n9 ]" G, \" D0 N1 [
- ! d8 A( D7 Q/ m0 D M4 X) P% s ~
- /*!< Reset HSEBYP bit */ 1 r* l @" I' ]0 D% z
- RCC->CR &= (uint32_t)0xFFFBFFFF;
; ~; O" |. \* `/ Q" |* S5 }& X) D: P - : n+ v( P( n3 N
- /*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */
' [- p& m A- j1 ^6 j - RCC->CFGR &= (uint32_t)0xFF02FFFF;
, V1 `/ K5 h( r0 I+ ~$ B) s; U7 m - 1 s A: s" ~; e# L
- /*!< Disable all interrupts */ 8 q' ?7 m' ?2 R" v3 `
- RCC->CIR = 0x00000000; & b' X; G) M2 M
-
$ L( I: p) V; H/ G; g: y6 F1 D - #ifdef DATA_IN_ExtSRAM
- X \# B7 M$ u7 R - SystemInit_ExtMemCtl(); : |* f( o- o1 x/ e( m
- #endif /* DATA_IN_ExtSRAM */ , Q& X ^' p8 r; d- @( S
- " K6 W* t8 S7 H; n
- /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
# s7 ?7 d* a3 m' N - //SetSysClock();
+ I6 k8 c' M0 S5 B6 W: c; O/ ^ - 9 M! N+ d/ M* H$ M, F
- #ifdef VECT_TAB_SRAM ) f; [0 c6 t7 ~$ t* H X- o, D
- SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
1 e2 w' E2 Q" @; m: o1 q# i, N - #else $ b9 k9 F& w. g- F: V8 e% L
- SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ 9 F3 H: J" J, w0 `' |( o- W- ]5 A
- #endif
6 z$ L. k$ d) O1 L; }/ f z. X' A - }
复制代码 然后修改man.c文件中的main函数,注释掉一些按键,让程序默认进入到升级模式:
) \6 k; k' G c& Z" U
5 M* ]' o1 C4 [! h, }- [cpp] view plain copy/ h( y" e# o+ T( l( S
- int main(void)
5 \' F# C8 F/ x6 }# C" O - {
; {7 S# l: l) z* L& s9 d1 { - /* Unlock the Flash Program Erase controller */ ( f, A, _& p1 u
- FLASH_If_Init(); M2 X3 o& p; x0 P+ [, M
-
& f& B- \# K7 `- W - /* Initialize Key Button mounted on STM32L15xx-EVAL board */
i& [0 U0 T' u8 ?4 e! @ - //STM_EVAL_PBInit(BUTTON_KEY, BUTTON_MODE_GPIO);
# ~: [* [7 h$ ?- b& u9 T, j. v -
' f, X. F5 r) C+ ~; H' L% m+ y - /* Test if Key push-button on STM32L15xx-EVAL Board is pressed */ 9 Z/ K. M9 L) W* R+ c) K: ^7 b
- //if (STM_EVAL_PBGetState(BUTTON_KEY) != 0x00) - Y b) B) z$ r! ?
- {
' F+ @" Y6 G# f' }( _* D) `2 L# x3 x - /* Execute the IAP driver in order to reprogram the Flash */ 2 h- f4 f5 v8 E2 p0 D$ D
- IAP_Init(); 1 ?! @# ~. p) O% s
- /* Display main menu */ 8 N7 ?5 l9 B: |
- Main_Menu (); 9 A6 p2 H7 i6 F# @ e8 r
- }
7 s) ?' I' o( d- L - #if 0
. Q% z( W; {5 v0 S) z0 V! \ - /* Keep the user application running */ 7 j4 ]1 y0 M! q" i- I- h
- else 5 t" k$ u: v5 [& q" J: M9 ~ d) [
- { $ o5 @) H3 E8 m- @
- /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
0 x+ O& c" K$ I5 K* i) `- j - if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
]% z; H: V M! a7 w9 r - { * R& V, T. [7 p1 a9 o: b# u5 g: V* }
- /* Jump to user application */
* _& q9 S* R" B/ |$ H - JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
3 z. Y O2 M+ \3 | - Jump_To_Application = (pFunction) JumpAddress;
: \' e6 w* L+ j" g& R5 N d; M - /* Initialize user application's Stack Pointer */
: y. V7 T9 e3 ~* ~ - __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
# h8 S, X9 Z/ E( M* M - Jump_To_Application(); 9 n/ M( y/ o: f1 \) W3 D
- } ) f$ j, D2 K# u4 r
- }
+ |. [" j- [; W" R7 d2 j' X - #endif
/ c0 P6 U: Y* q" K3 [3 i - while (1)
8 ]& H$ x. F- a0 E& T+ T - {} 1 |% X0 h) W! b7 _- W, i3 ]5 ?
- }
- C8 L+ a: P1 G2 q% ^7 E
复制代码 由于NUCLEO板子默认使用的是USART2,因此需要修改使用的串口:
! N$ {8 ], T( x, T. T0 _, n+ f- [cpp] view plain copy
& w3 Y3 J& Q; s4 E# y - void IAP_Init(void)
7 p% O, C( }5 y) f; d6 ~ - {
3 R! Q8 E' e: W Q8 h! V8 h. U, a- I - USART_InitTypeDef USART_InitStructure; 3 T3 ~3 G8 A8 J8 C" V* S
- /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/ 4 h% K+ w/ h2 y7 n
- /* USART configured as follow: % M6 s- ^# H- ?2 W% ~; J
- - BaudRate = 115200 baud
. [0 a3 C* c) o" A# s H - - Word Length = 8 Bits
6 _( U8 N# f; @* w7 j - - One Stop Bit ) l2 A' S" T" J+ x N8 Q# d
- - No parity
7 w: ^- V) X% h - - Hardware flow control disabled (RTS and CTS signals)
$ Y) K1 ?# ?! m* m5 q3 c/ Q# a. w - - Receive and transmit enabled
% R; c% N+ j0 U8 ^" ]" x' l6 j# E - */ 2 D4 Z6 z- P' ~ J! Z1 Z0 n3 I
- USART_InitStructure.USART_BaudRate = 115200; : C* }7 d8 ?6 Z& z! u
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
& N, D! T) I, c2 A. f, |6 u, f - USART_InitStructure.USART_StopBits = USART_StopBits_1;
0 p7 f; m% n. P# R& l6 G - USART_InitStructure.USART_Parity = USART_Parity_No;
L1 Z! [$ q$ d! r+ m# ]7 z: U - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
9 t4 A$ _/ s! ~# E# J - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
% [, k% P, G; H+ T -
/ G' r" i9 P. N' `& h0 D - //STM_EVAL_COMInit(COM2, &USART_InitStructure); , }0 n& C0 P7 [, B
- USART2_Init(&USART_InitStructure);
- v8 u& F% c2 u$ R1 e0 H - }
4 I, f7 g0 u7 M# N. N - & ]6 y2 q; J, ^$ y3 j3 e) W! S+ s( J7 `
- USART2_Init()函数为新添加的串口初始化函数,其定义如下:
3 W( u2 [. u8 D/ e2 {2 j) O% ~ - . m" o1 q) x! D9 y9 s! @$ n
- [cpp] view plain copy$ _- w J% q" L
- void USART2_Init(USART_InitTypeDef* USART_InitStruct)
. B8 m2 w% k) h" l/ U: \ - { 4 j, F7 Y2 Q0 D% S9 y; ]8 ?+ r
- GPIO_InitTypeDef GPIO_InitStructure; 9 {4 }! \! j& z& I6 c+ Q( \2 A
-
1 x0 o7 a, T: ^4 c: ]2 Y - /* Enable GPIO clock */ ! S; N _* d- T; t, M
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
9 u7 f, k4 k' C) } h3 J1 H - + {- V0 o. i4 `6 a1 u( e
- /* Enable UART clock */ " u% c0 L. ]8 T0 ~4 T0 H
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); ' O3 E6 q; G, X4 a
- # y Y% W& }& D* M- f8 M
- /* Connect PXx to USARTx_Tx */ : O! k* }" N R" k( a- O4 f
- GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
8 L2 i/ p8 H+ {; p& c1 d q - 4 W' m: |$ [8 p2 ^, ]* K+ N
- /* Connect PXx to USARTx_Rx */
6 u! j' A# ]7 S% M8 x! ^" W - GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); * l0 I5 q o J3 Z1 W6 m9 E! i
- 0 c0 O2 G, N2 X
- /* Configure USART Tx as alternate function push-pull */ " s) t1 B k+ d6 }7 ^
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
5 n6 Z& |; W2 N: I7 \+ t/ L - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
, k( b7 J; ^+ a; ^( f - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz; 7 t, S0 N* C; m4 D- O
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; $ \* D5 ?3 P Y# o" [
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
# I7 E0 Z& g# N# }% {- v - GPIO_Init(GPIOA, &GPIO_InitStructure); ' M2 t' \4 v0 T* [
-
, F c$ ?* c* p - /* Configure USART Rx as alternate function push-pull */ 7 z6 a; J5 d9 O( S
- //GPIO_InitStructure.GPIO_Pin = COM_RX_PIN[COM];
Y" M! _7 @6 P5 A, O' f - //GPIO_Init(COM_RX_PORT[COM], &GPIO_InitStructure); 2 l$ b6 P B; p0 J) A6 x
-
, ?+ u# |0 R; [; n+ p2 @% p - /* USART configuration */ * ?! p+ I9 ]6 X% b& k8 R9 w) b" V
- USART_Init(USART2, USART_InitStruct);
# r& O, A$ @$ C5 R -
( F: P) M @ |( o. R - /* Enable USART */
+ y9 O# y% s" ?( r3 n( b8 _ - USART_Cmd(USART2, ENABLE); - s$ g, Y7 d( @& `
- }
复制代码 接下来需要修改程序中使用到的打印函数:
( T* r9 S8 B2 P6 I- [cpp] view plain copy
! Q* o* }! ~) E( ^3 B - void SerialPutChar(uint8_t c)
7 L( d5 v0 F+ l% i - {
1 C# k O, |4 x' v - USART_SendData(USART2, c); # n: e: M- ^# U! Z# S# S
- while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) 8 [) _6 } F' a, ?
- {
9 \6 i8 X5 u5 w - }
. u* F1 u* B m4 ` - }
H5 |. m+ [9 O3 J- V9 O
) r+ ~$ V8 B. B& p. r- . l& i. H' w# w& i# S3 Z
- [cpp] view plain copy( ]4 T! I! B( \& w7 o4 V9 K- s
- uint32_t SerialKeyPressed(uint8_t *key) ! C% N' U4 v0 D& \1 ^3 Y7 ?
- { 1 \) E; b; G# I3 t7 e) G1 @- Q
- ' P1 q2 _' E% @7 |8 n1 j, H; h8 c
- if ( USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET) " Z! C/ X* t/ j6 U8 ^5 N5 a% O
- {
6 Y1 S4 c6 A: R" j$ N - *key = (uint8_t)USART2->DR;
j$ X2 y/ y5 y; y - return 1; 4 t( W: Y$ ~4 G) n ^$ ]
- }
; r! J* V8 P! x+ k! G - else
4 Z7 U! Z' i. S) c7 i1 O6 o8 ]2 O - {
( E1 s( g9 e. K: z' X, N - return 0;
2 G/ M% T9 T: F% O, o+ _5 F - } 6 \( Y( x: e7 s1 F& N
- }
3 k2 ~ W2 i% B
复制代码 基本上就移植好了,编译烧录进NUCLEO板中运行。
4 Z) E$ [) k/ C# o7 _ ?& U9 ~6 [3 w% k6 O6 b' E
接下来需要找一个PC端软件超级终端。$ S* S( p( ?5 Y# \+ b+ K
除了IAP程序,我们还得准备APP程序,由于IAP支持烧录的是BIN文件,因此,我们得生成BIN文件,HEX是不行的。! Q0 }' z2 c. W8 @* w, I
. p0 w! W) I& C1 D$ q) ~
在APP工程中我们得注意几项内容,以IAR为例:0 g1 \- |' f# v9 h
% ? E5 m, T( k; x4 ]8 ~$ p1 在option->Linker下:
2 K) L9 M) g& Z" v) t% N D% m0 R
config->Edit..--->Vector Table 的起始地址改为:0x08003000# _( @6 Z# A$ y+ |% w
2 q9 r- l3 f+ D) W4 h0 W ---->Memory Regions->ROM改为:0x08003000
; u) Y" ^9 w) d) a& K. {+ p- v% s0 t! k" S) k& V( I- c2 e
2 option->Output Converter->修改生成BIN文件
6 x5 |- @0 K) S* h* r* R" V
* D1 R1 q8 ]/ [/ k: j3 i" Y& x3 sysytem_stm32l1xx.c文件下
0 Y6 t! ~, R/ F# ?8 m+ v* c
9 q# W8 M1 ]0 m E5 X8 S 找到宏定义
+ \7 h* i+ Q9 M8 Y4 P' E3 N7 l, W x, V7 x% {# `* p% G# [
#define VECT_TAB_OFFSET 0x30000 T* B! {- ?: x) c9 W) Y Y
0 K2 I: m( q) C$ j' l
偏移位置必须改为0x3000
\% h1 R1 X8 `6 t) u- k4 _3 F1 j1 d: n# F" t d. [
到此基本可以了,APP就这样。, n! [- s# v0 m- m& y9 `
9 I6 g. r6 j0 z- v* W6 B最后就是测试了。! c, ^$ E9 b4 h6 t
) q/ C1 w e2 I
测试:. E$ C! c* n" e& K3 N; a
* {' U7 p( {6 Q
首先得将IAP烧录进MCU,然后再通过IAP烧录APP。2 _( U' b! X7 n8 Y, L
9 t* r. J* \; c* k' Q
通过IAP烧录APP过程如下:
1 N6 d9 ^& P* f7 I F, z( `1 [; B/ C: u( {+ [. w
打开超级终端,连接上串口,有如下界面:" x" S) b$ u1 g
" |8 Z9 `& y x
波特率:115200 data bis:8 parity:none stop bits:1 Flow control:none
& O% C; F: w" \% M
- m W( l _& Q! n: i9 P. f
+ B0 t3 n# _& C" `8 Y- c1 a1 h; |: J5 t4 D8 u
通过键盘输入1:# p& L$ R( h; b
+ ^& L* ?4 [" l) k% `
: f0 G2 d; v; V$ H U' I$ q7 U, h* x Y+ T7 q$ ?4 \* s( F
从菜单transfer->Send file打开如下界面,输入APP的BIN文件路径,并使用Ymodem传输协议,如下图:# d' p: C) u* h( H# q8 l
) ^) a0 | f# J1 F' [/ t( c
, S6 z* [. r0 ]9 J3 l$ J# i' G/ h/ M I
' w6 O3 n. q* t e4 j
点击Send,开始烧录。。。 p! W: v$ e3 h. ]1 b8 s# D; w: V
; V4 J% I0 F7 p% h
9 a Y6 B y: e0 J* R
* F) A3 W$ `6 F传输结束后,按下3,运行APP程序,至此,整个IAP与APP都可以正常工作了。- d1 I0 i; I. x8 c
# W: q+ `% X) {8 v( f6 U4 w# { t( y7 N/ G结束语:
; }# c: D; t) B7 t0 W4 r& H0 z6 j& r, K# g
这个只是个示例,实际IAP是还需要修改的,得判断是进行升级模式还是直接跳过进入APP,这个就需要看设计如何了。 _( s2 O9 _% R
% f2 b/ a) c! j& S3 R9 D: F6 N0 x+ C5 s9 |
; b/ c6 q4 }* e8 w2 G9 K Q5 v+ H @: W+ V1 e- r% D
转载自flydream0( B, d& z6 k2 g6 |0 B h" _
g6 _: [+ W; u( I3 H1 ?* r- J
0 v7 o/ k" A9 C. r8 H: M9 b2 F
! [. N# a: p4 E# B* h
|