你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

移植官方STM32F4XX IAP程序为HAL库的过程

[复制链接]
qq344269956 发布时间:2020-1-19 15:47
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:
* d, A2 `6 x% _, f5 D上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。4 [& B4 _+ s5 ~+ A+ V9 |! c
. H+ l, l* b" w* v9 ~1 y1 |
首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。2 F0 h, r2 ^/ c5 D: q
+ E$ g; c( G/ l  \
然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动
# W; Y- E0 z. ]& \7 c$ P: H: T2 L' y: U, ~
2 C, {; q4 R* F
设置了时间为168MHz,然后生成了一个HAL库的代码。
0 y) J" q8 [; |
" f: F7 `( {' u6 w% I' i( G# w将STM32F4xx_AN3965_V1.0.0里面的
6 K7 ^( [4 y& Dcommon.c) z# B0 X" D$ n9 {# s
flash_if.c
# K8 R+ N) I* X1 G, n6 e7 Pmenu.c
" y" g) v0 N' i  k) cymodem.c
" [. }) m& F/ m' p9 I! R& v放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add  existiong .....)5 S# H+ G7 e. S  D0 \

' D9 T' b/ u, ~' l在头文件中添加上头文件
' e* `) f/ l3 O# o; ]5 V& @4 f( z: G#include "menu.h"
" F; p4 ^* Z) b' R5 L2 h#include "common.h"; b1 r/ a2 C( C* x) S
#include "string.h"
' Q# P8 {9 F2 Y2 _2 V4 A8 D& o. t( n#include "stdio.h"
. r. i0 L' U/ C+ c: F
4 F' ]# i% t! x; j& M: c' X4 a1 g& c  R
添加下面的这些外部定义3 E7 F# ]* K, \) y" K
extern pFunction Jump_To_Application;
0 [4 C* `0 D; @! ?, u6 }% Bextern uint32_t JumpAddress;5 ^9 h3 o" S# S9 C/ v/ N9 A
extern uint32_t FlashProtection;
& P( u0 {# ~2 j1 Z+ x! h/ U9 _
, R/ j* z( M3 P2 T
" ^4 G  Z. g! l编译后会出现一些错误,主要有:
% `6 ]$ y- l7 L/ T: }0 \( WFLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X- Q9 {+ M$ U% }& C' K* `# F7 ]% Z
; v% H4 M( }" r. o! g) @
FLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:9 S. S2 h4 U3 x& ~. ^( G2 r, m
uint32_t FLASH_If_Erase(uint32_t StartSector)
/ G% n5 _( u1 a' S{
; H: m1 D) h" d8 O8 [, X  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;' c2 i. x% E: n, _6 n  x

* }$ X: K+ u1 v. W. k) Y  /* Get the sector where start the user flash area */
% }$ U, K2 k/ o7 X  UserStartSector = GetSector(APPLICATION_ADDRESS);* |" \9 L# t1 ^5 t. C& `

, l6 Z0 N/ }' q# O3 }) C- R- b  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)
6 d6 @# t  y4 S/ D+ [* v& y  {9 d( z( N1 f7 ~8 M3 \
    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
( G; G6 H& c# @  k2 D, U' m, Y       be done by word */
9 @! U1 O; x8 `# }( v    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);/ `& \$ {* t' f8 \
  }3 d2 Q/ F) B8 e
8 T9 U. M6 z8 x/ c' z
  return (0);7 r% s% C: e( J& j- m* ^
}- w0 g" l2 K) w/ m1 v; l
$ l% \5 Q0 C. U7 f$ I- Z  o: e3 |9 j

6 K8 J9 a( T8 }* e) C其它的一些基本类似,解决办法都是是到:
2 v/ J" e' |* l: [; h  L9 W+ I  Wstm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换
" t$ [9 B# h( X" @) F' W需要注意的是
, @7 d5 f0 z! D9 x有些函数:
& W2 p, D: C& M" j7 B# T; QFLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中& s0 v; I. \1 z
void               FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);
6 y9 a2 c! o5 w3 {3 _HAL_StatusTypeDef  FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);7 Z% l& _4 V; _+ ]
HAL_StatusTypeDef  FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);
& Q$ L9 ^+ H+ |3 g7 c4 Y" KHAL_StatusTypeDef  FLASH_OB_RDP_LevelConfig(uint8_t Level);
( Z6 e, z* v0 V4 U9 HHAL_StatusTypeDef  FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby);. s% E1 T; T$ V4 }4 ]+ }
HAL_StatusTypeDef  FLASH_OB_BOR_LevelConfig(uint8_t Level);1 Y) F0 K$ y; J8 t
uint8_t            FLASH_OB_GetUser(void);
- B. f# k' E3 s# @) Auint16_t           FLASH_OB_GetWRP(void);$ b$ }  P0 P( G
uint8_t            FLASH_OB_GetRDP(void);+ C) c2 E. D$ P, l6 }1 V
uint8_t            FLASH_OB_GetBOR(void);* b) p& U# @( W/ D7 @

- u8 z5 f) B1 d, i% T- L+ Z将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。0 j0 s) i8 n4 D" O% _
还需要修改这个函数1 J! ?% i/ Y. t! h8 e
uint32_t FLASH_If_Erase(uint32_t StartSector)
; M. x0 U6 T2 j# ]+ w6 H" g{
- X+ t3 i) M. ^! m  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;8 R% ^& N& k/ d; Y& Q! G

. M# Z3 {1 u* |  /* Get the sector where start the user flash area *// m# F8 b" P  f8 x
  UserStartSector = GetSector(APPLICATION_ADDRESS);6 s# H3 q# H" s: B( |5 W6 b/ q( S% g  a
, h5 [/ L( ]5 A- U
  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1# d, X% G' ]! v2 d3 O5 s4 x
  {- Y/ a! N( ^0 k
    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will+ s* X5 _' I+ M7 a3 C2 R  ^9 m+ n9 a
       be done by word */
0 ?3 u9 k& [) |$ O    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);
" |( u8 r. K2 ?  }; n" s1 `! F% T, e$ m

& N8 I* T  O* U" K' v  return (0);
, P7 \+ c1 n0 \7 Z2 J' A}
6 J. a$ ~3 w$ n  F) W$ ]' z: C0 h/ [: J: N* R; l" h. ]9 Q
9 x6 E' j5 ~1 ^' k6 A

! G* r+ o$ n  ?7 {这个函数需要修改一下,标红的两句是新加的:
5 s' P! Y% K$ q# @+ F  Qvoid FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)# [' E5 d; ]: q4 V* t
{$ x' [& I6 Y( C! H8 T" o, x
  uint32_t tmp_psize = 0U;& I7 _7 i+ p; V  L% _0 @) d+ R
# d2 R% J3 I4 D. Q
  /* Check the parameters */( C! _+ f( }9 w6 O
  assert_param(IS_FLASH_SECTOR(Sector));
5 |3 q9 g3 Y# y( P/ N  assert_param(IS_VOLTAGERANGE(VoltageRange));
7 i! [& z9 z  V% z1 v9 J  FLASH_WaitForLastOperation(0xFFF);
( n; i; c; ~$ t; z) T. _  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)9 B! O$ {0 d' x" {
  {
9 }* w! }( J& Q# M6 @) S     tmp_psize = FLASH_PSIZE_BYTE;  Y8 h0 C3 z: T8 w( W+ ~8 S6 Y% m
  }
: l3 o9 w7 _" G+ R7 Z2 b- V  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)4 i4 |- n& ]& j) q
  {
8 q4 {9 L0 R- @, r% H    tmp_psize = FLASH_PSIZE_HALF_WORD;
1 h: c; m0 {2 T) U  b6 f3 d7 y  }( e+ n- N' z2 _/ ^7 G
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)
9 _& @7 G' h& U* L3 Y& m  {, Z/ |1 M5 I3 u
    tmp_psize = FLASH_PSIZE_WORD;- |0 [# x* Z4 ?9 D
  }* D5 J, `4 V2 W2 U. ~0 `) P
  else$ v" ~- F' e0 I
  {; B/ I3 x$ p, F8 {: F+ E
    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;" \3 |) v9 ^" u7 M0 P
  }) g  ~0 t) T, v/ C
        4 Y6 D' S3 h1 G0 O% C' T
        FLASH_WaitForLastOperation(0xFFF);
' B8 E0 c8 F) e1 s4 ]# M+ w  /* If the previous operation is completed, proceed to erase the sector */- ~9 F1 I2 P) [  L+ F
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);- P6 S+ b" O4 k& x& [: R
  FLASH->CR |= tmp_psize;$ s7 h; u& [4 k9 H! u% r
  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);& S' }4 `" v: {) s* Y( g' h
  FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);( C" w+ a8 O; n3 x+ c8 c( a, `
  FLASH->CR |= FLASH_CR_STRT;0 K0 r5 x. Q. `5 y
}
7 \/ G9 ~: w2 G7 s$ ~. o6 _/ [: c- C$ U+ A- `$ e9 A) ^

; i+ K( j- s; h- ?; P1 V
, \1 I. T! Z9 m0 U+ `其它修改,串口修改:$ q; L' Q) m' t4 \/ t
void SerialPutChar(uint8_t c)
$ k- z# z) m# T% y" n) X7 Q$ E{
* i: O3 X# W0 ]& s9 D. H4 q# G  HAL_UART_Transmit_IT(&huart1, &c,1);
% O& l* P4 ]$ k  l        while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);1 s4 P6 X* I* b
}' R1 w  o% \  ~- I
7 O5 r! R7 x' i- U( a$ i
% H/ a  X' h. P  e1 y+ V( i

5 @  n; b" _9 G* G. [* ^7 n' Wuint32_t SerialKeyPressed(uint8_t *key)
" F' ^) J. T: C7 n{
$ S6 W* q/ T+ x1 ?' t       
" Z4 o# [7 K# ^: E) q        if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK)
- e1 L3 [) t, Y" d7 @7 X- m  A        {- Z  h% `! C: }) P: }7 W
                return 1;
: h7 n6 ]+ p# p9 p3 O$ l0 T        }
, {. y, r  K7 F* ~' U" z: M        else
: j+ o# }2 L7 `& n) c- [        {
3 Q* l* H2 b- N7 f2 @# x* t* X' |                return 0;  x* U8 ], d1 l+ j
        }
1 B6 V* @0 S6 m2 L9 n, D( P8 F5 F( a
}
1 k* y7 ]8 [2 O/ w/ ]$ O. B: s; p- _' ?4 P: B7 F
在修改完成确认没有错误了,就需要如下操作:9 B7 }5 i6 K/ a, r9 \& I( J" _
修改main函数:
1 w: r; w( Z% @# i0 W& iint CmpStr(const char *data,const char *data1,int index1,int index2,int length);6 |) e0 T9 u& z2 ^  e

& r4 O. \& R7 E& z! Q#ifdef  __GNUC__3 Y# g- I' A6 A% S# B2 c( }

% ~& ]4 ~( w! s( z3 H#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- \: N5 @  {$ o) g       
' E; J: G% e$ x; {3 A1 t#else' a! Q* [. [8 @: S/ g( f
" c# A6 e' Z1 Z" w# o/ c- ^/ C
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)/ l5 F- R, H2 W4 I, Q; F
       
7 L4 J# G  S! D& \- _6 i#endif4 B/ F$ S4 N" \; v2 N
7 q7 _* s  c( @+ F: D) ~& `! Q
PUTCHAR_PROTOTYPE9 P' U8 ^' i) w* J
{, b" B" p  T9 l# i' f0 S8 `" @
        HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
' R; ?0 n4 p' }. X9 p; q        return ch;
/ U: T0 U$ K  q7 G}7 |' y) [, v( {# {+ `6 p
/* USER CODE END 0 */
2 h7 L0 y2 }  X8 {: h$ E
& l6 a+ \1 X  {. I# p) J/**; S3 i  f; h' {) {4 i! J
  * @brief  The application entry point.
# l" V9 Y4 @8 k$ ~! W- o2 N3 L) n  * @retval int
2 d0 _" s( n5 q/ {  */6 S1 O& s" F$ U8 L0 q
int main(void)
; p- N6 }$ E6 Z* ~9 u{
. s4 }: L* V( S9 q# z  /* USER CODE BEGIN 1 */
: \  c% ^8 s6 D( L5 n( W, \4 T$ v        //FLASH_If_Init();
0 W* j6 D9 L  X7 X  /* USER CODE END 1 */
5 t5 T% p: B+ s( e/ u; L
) p' h7 F) s: @2 d# r* y* f: @9 v/ X# x' }
  /* MCU Configuration--------------------------------------------------------*/
  l6 L2 u& l2 e4 {0 J5 {: w; V& G
$ }! x: c: u+ O; y  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */! b8 K- m" F0 Y$ Q0 t, \+ b
  HAL_Init();; i. e, c  z. e* j/ X" m9 x

, v! x9 N3 t2 J  /* USER CODE BEGIN Init */
  Y) {7 k! z# Q4 N  uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义4 G1 [+ R/ g0 k& P+ @
  /* USER CODE END Init */2 u& S1 i- l$ F" {7 A

& D, J  f5 T( R7 G. z/ p& R  /* Configure the system clock */
! N2 K, g: f4 h  SystemClock_Config();
0 i) d$ Z: Q) \" i2 G( G! v! F* A1 I6 O" g1 M8 p1 ~4 z, |
  /* USER CODE BEGIN SysInit */7 H, o# N, t9 `: ~6 r5 @
7 j! }0 p2 ]; v) i$ `' w8 I. K1 b8 s' v
  /* USER CODE END SysInit */' t; o7 [: B2 [, q" @/ w
( V9 U4 r7 b6 z; g' R( {
  /* Initialize all configured peripherals */
7 m3 }9 ?$ {: D; [% ]5 p0 B1 ^: |  MX_GPIO_Init();
" ?8 ^4 T/ [) C* K) I  MX_USART1_UART_Init();$ y& P( C- M: v0 y+ A, r
  /* USER CODE BEGIN 2 */8 h+ h; Q. O# |5 [  h& n/ h
        1 Z/ b% I6 v# v- D3 S  ^

" Y# P, e2 O2 E8 u5 i' b  /* USER CODE END 2 */& x( a3 `! }& t- [! F7 A

9 c0 `7 ^% D& n; p! _0 N  /* Infinite loop */7 R7 C+ z8 n. O! C! d' Z: g' }
  /* USER CODE BEGIN WHILE */
6 ^. r: |1 \9 [  while (1)6 k, O3 L( Q& e) |* O$ Z
  {
0 g2 R5 D" M1 a) v. s$ U                $ z1 ~9 k+ d$ f0 {0 E6 b
                Serial_PutString(mychar);" `4 G- _" p+ ~: V
. g* x/ B# i) w: k* a# J5 K* Q1 M' o
                if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)4 B3 h0 J3 [: b' t/ A. b0 W
                {* ^  z+ F# Y1 ]- O( v2 P: \
                        if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义+ P: N9 k$ Z9 {7 S
                        {+ O: V2 U" E3 i% d1 E6 @
                                printf("正在等待数据文件下发......\r\n");/ H: \! d% K' F! {( E

6 R4 J: ~9 m: R3 u) q0 {: h) a                               
1 j/ S2 J; ~, y  H7 }" L( i                                FLASH_If_Init();- A' b( R6 g" [' Z/ _
                                6 `! S3 \" [6 C" s. G" z  Y
                                //Main_Menu();
$ q$ O9 [# }: q. L                                //FlashProtection = !FLASH_If_GetWriteProtectionStatus();# O; g- i1 k2 o7 w; K' L6 F
                                SerialDownload();( }  d- M% s& V* g0 v( Z# {
                        }                        ) p/ n/ E3 W- K$ h' x
                }
! a" M6 U: a; F* k0 X& K. [, n' Y/ K2 F5 h5 W: x% P- O6 a
    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
! u/ g6 E7 V( m  h# Q    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
( [  r7 g$ U5 v4 O- y6 K& C    {   k5 C1 C9 C0 P+ S, F% t
                        Serial_PutString((uint8_t *)"start user Program!\r\n\n");
* k  p0 E; }7 p$ P+ H. Z6 |                        //HAL_Delay(100);;$ }0 G  L% [& @& C1 F* I, B
                        /* Jump to user application */
* Z4 g7 w* U  ~9 o% P2 j+ T( s      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
% @; r7 B$ Z  l; J7 a+ k      Jump_To_Application = (pFunction) JumpAddress;
0 b0 N9 d1 T0 S0 G8 {% N5 M      /* Initialize user application's Stack Pointer */
& a0 o% F! A! X2 T. C      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);: g9 ^' h  h6 Y( l" {% ]/ O
                        Serial_PutString((uint8_t *)"Start program execution......\r\n\n");
6 E+ Y3 J- S* c4 g9 P6 C" K$ F                        //HAL_Delay(100);' M( e8 X9 z$ Y- s
      Jump_To_Application();( O7 m+ }& b( J3 q
    }
" w) d& A& M' q# i; D- k* v6 C6 N                else
, s; U/ x# F1 O+ a# P                {
5 x' F, x- a9 Q                        Serial_PutString((uint8_t *)"no user Program\r\n\n");
0 V- T$ X( O6 D" R' ~; D) x8 p6 s                }
% o) h$ |6 [) }7 d# L% Q1 i5 o               
$ f, i, l: K" p    /* USER CODE END WHILE */: ^/ K3 `& j, b/ `  W" T

- z+ N6 t% R! g: l4 ]/ `    /* USER CODE BEGIN 3 */% T4 F  S: Z5 W. I
  }' j# q4 {/ U1 U! {
  /* USER CODE END 3 */
8 ^- y" w; }' l}
/ O! A7 y5 P4 W* B# w& L2 o
. o/ h* f4 o1 l6 e
; Z% ^! q5 ^; ~( u' e3 x$ i1 m
  |# W4 g( j# [  h8 x- g, H int CmpStr(const char *data,const char *data1,int index1,int index2,int length)
3 @/ X/ Y2 @. A' W+ q$ g" v; y {
1 i4 H6 }( D6 B0 d; {! T: r         //int temp = 0;6 d7 ?; w# P9 M0 F  p
         for(int i = 0; i< length;i++)& W0 J3 Q* c. B% r
         {/ E% ^; V* n  Q) o! a  q
                 if(*(data+index1+i)- *(data1+index2+i) >0)( i6 Z8 I  w  ?+ m9 A
                 {( i: i, {+ Q/ _; C. n
                         return 1;  6 J8 _3 ?- ^8 `) B/ C
                 }4 O+ G8 ^& e2 @5 I  [! \
                 if(*(data+index1+i)- *(data1+index2+i) <0); b. u  R  A: v6 A
                 {) Z( E* E( Z" D
                          return -1;7 N# X+ j$ ]/ V
                 }% b7 ^$ w; }* s/ k
         }
  V8 ?5 f* W% i! G3 P* K+ x         return 0;/ Y8 D+ H+ W& ]' A
}
  g, b6 n8 m$ `2 Y$ L5 }, r4 _" g" B* N0 i

1 |- H- \' V5 g, ^好了,基本就这些,有问题留言,我有时间就回复。。。1 c6 q2 u) t) u. U4 Q& C/ h0 e
如果有好的提议,可以一起探讨一下!
/ Y6 n' V- M, t9 a6 W/ Q$ M4 G

串口1设置

串口1设置

stm32f4_iap_using_usart.zip

下载

1.66 MB, 下载次数: 188

STM32 MCU IAP例程跳转到APP代码简要分析.pdf

下载

38.67 KB, 下载次数: 71

收藏 5 评论4 发布时间:2020-1-19 15:47

举报

4个回答
jeffhe1 回答时间:2020-1-20 09:12:11
謝謝分享
慎微 回答时间:2020-1-20 15:20:55
感恩分享
生命在于折腾! 回答时间:2020-1-31 09:56:06
谢谢 分享
LaLaLa321 回答时间:2020-8-27 16:01:51
我用的CUBEMX里的例程,自己用CUBEMX建立工程将文件添加进去后,通过Ymodem下载程序,可以正常跑但执行到HAL_Delay()就卡死了,版主有遇到同样的情况吗
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版