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

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

[复制链接]
qq344269956 发布时间:2020-1-19 15:47
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:% z, x& y8 A$ g7 p
上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。
/ ?9 G7 o: y/ l6 A& Z! d/ q1 v4 s3 J% P1 v3 W, o4 X, J
首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。
7 H/ n7 T: F# R& |3 p$ S; a
9 F+ D+ K2 u0 O& s4 C. }* k' V然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动, b) U7 J7 |. m0 U% y% p
( Z: E3 m: j- H! l- O; `# K' m! F

" t! c  Z4 T7 N; ^8 g0 e0 u设置了时间为168MHz,然后生成了一个HAL库的代码。
  i( M# L' i! K; B, b- |3 W
! s: r; O, k+ g1 `6 J. d将STM32F4xx_AN3965_V1.0.0里面的# R4 D3 F( }& v  I. p6 O& q, i
common.c
) c; _2 I- m' ]$ x. z8 f) R7 ~flash_if.c; N8 i/ V0 f* e0 N
menu.c$ b' W  Q$ x) g/ W( k
ymodem.c' C# R1 |, G% ]# ], i
放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add  existiong .....)
1 T* r, J( d$ H' Z; m. j+ I  X3 ]5 A$ s* J! B7 h
在头文件中添加上头文件1 M0 _( |2 b5 V' z5 @: r
#include "menu.h"8 T2 s/ I2 L5 [
#include "common.h"9 v0 S6 O& h4 I& {
#include "string.h"7 p  L  e+ g7 z8 v+ F8 A- o& x2 u
#include "stdio.h"- l9 @2 F& ^" b& }3 T) j; J: G

6 X6 k- i5 n3 N7 L4 r' {3 Z& o8 W' f3 e1 H" n+ ]4 _
添加下面的这些外部定义$ m; Q; Z# j' h
extern pFunction Jump_To_Application;5 M' ?- s# z7 t0 l
extern uint32_t JumpAddress;
: U9 O1 s# ?: b' x3 Oextern uint32_t FlashProtection;5 r) ]( P/ _' ^# Q+ i

, ~" m1 [( N6 _0 }. H$ r0 _# l4 E$ i% e) k/ q
编译后会出现一些错误,主要有:7 V% h4 Z- C5 }. S. D
FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X
( V$ Z. k) b% ]7 N. |
1 |2 H( ?  a0 n8 IFLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:
. U1 i" E) ^" D* A% X2 Quint32_t FLASH_If_Erase(uint32_t StartSector); H( q% I' l# T  @
{" e& b1 J& v/ o5 P! h7 [1 Y2 r% [
  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;" |! T+ j; [1 a

4 \, ~( t0 }4 W$ i6 s& l1 t) H1 q  /* Get the sector where start the user flash area */
6 ]  Z7 {7 j# m+ G: t/ q; ~  UserStartSector = GetSector(APPLICATION_ADDRESS);
1 l* s5 a$ i5 g! J* T1 F2 Y" m( A. w6 U+ Q0 C2 B5 m- O
  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1); Y2 g1 u7 C& }  Z) Y: p$ i# c
  {
: B' [! g! N  L, J+ W3 z    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will8 O  |9 t. E$ v" C) G- g& \+ z. l
       be done by word */ ) w/ [, _- ~) g2 u; j' V
    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);
* q( f. }4 h+ P/ [8 i0 q) e  }# M! j2 S$ {1 Y* G; j
, r, H: W+ _2 Q( M
  return (0);
: `$ ^0 r- q: j. L}' p$ i  F( X& j3 ]  z: Q

# g, h  m: x/ N& p, d$ n1 Q, W! t9 x9 b
其它的一些基本类似,解决办法都是是到:
# U  M% @1 B+ f) D- ]stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换0 R" X- }8 N7 ~5 s7 K$ ^, v+ L" r
需要注意的是
- H8 k* r: |: v/ q/ Q9 P9 Q: ~有些函数:" q; [- T  |: F
FLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中$ W5 J* ~& m$ c9 C
void               FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);
% k% E+ b9 t) [9 }' e: Y  bHAL_StatusTypeDef  FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);
& t+ l. `& `/ }+ `/ X9 x8 OHAL_StatusTypeDef  FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);8 F  R) |) Y" M# C* T6 e
HAL_StatusTypeDef  FLASH_OB_RDP_LevelConfig(uint8_t Level);* ~- m% u& S# n$ ]- z
HAL_StatusTypeDef  FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby);
5 G; _  U* V* UHAL_StatusTypeDef  FLASH_OB_BOR_LevelConfig(uint8_t Level);
2 @1 |0 w9 c/ R+ \& uuint8_t            FLASH_OB_GetUser(void);& h- n* z! f9 V; ]0 ]8 r/ y5 Q( X2 y8 i, k
uint16_t           FLASH_OB_GetWRP(void);
) v4 ]4 x" l% Huint8_t            FLASH_OB_GetRDP(void);
* x3 {5 d0 k( n( u% M6 v- v8 z. _1 puint8_t            FLASH_OB_GetBOR(void);
; v# X2 K: z' G0 R" J; g2 z1 A! q" u; W
将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。+ k' c+ D' k; L  P2 T5 Z: a- C. L8 ]1 P
还需要修改这个函数
1 V" w# Y/ g0 \2 D. ^: z* Huint32_t FLASH_If_Erase(uint32_t StartSector)
/ J+ ?" z: E, c9 d/ _' d+ f{) d* b5 s8 E1 m5 q  M
  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;7 Y7 P) U- @) o. j8 _2 p

. D' Y9 O' B# E! l8 w* K  /* Get the sector where start the user flash area */
1 V5 c! ?  U# w9 f0 p. o( P1 L  UserStartSector = GetSector(APPLICATION_ADDRESS);/ C0 P( s8 N5 C- B7 X
; M/ n9 K0 V0 B) S) h
  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1
8 A2 [: j; ~3 ~! e4 ]; t  {
2 L, L8 j% `7 O7 L  J. p    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will0 ?6 D4 X1 K1 g* ?# Y4 f; j; }' _
       be done by word */ / N# J! X; E9 w, _/ ?% G
    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);# `/ o6 O, H- h6 o& o. H; K8 W
  }  R' V+ L+ ]' T2 k$ [3 x

7 P3 j. s' h# M/ G, v2 w- b  return (0);
& g% x$ c- A+ m% R5 C. y  D}2 E6 o  b! o: D& H+ \$ Q8 j
* N; `( u2 Y% X$ Z

! Y3 Y$ t, q1 X( |8 ~3 d$ _7 X% Y" ^8 ^* E4 B% t
这个函数需要修改一下,标红的两句是新加的:
3 a' l# c* C% @" j! O! {void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
4 D" \8 @5 t) X+ d3 c, G$ g{
: S  q: A1 v2 s! J: ^6 R  uint32_t tmp_psize = 0U;  |' M! s' |. z2 L
) y9 p; O4 g8 l, M+ D6 b- p2 ]
  /* Check the parameters */+ ]1 m& b8 J3 f7 D
  assert_param(IS_FLASH_SECTOR(Sector));. [7 M" H* D$ Y, B$ g! `
  assert_param(IS_VOLTAGERANGE(VoltageRange));) y! v9 b/ F$ e: c, t
  FLASH_WaitForLastOperation(0xFFF);( E3 a$ J% r" I2 I+ V; X* E% r% V
  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)
1 c( V, Y- v, e. p  o! N  c; Z  {6 D3 _  L7 E( a& R% M" K& F/ h. @
     tmp_psize = FLASH_PSIZE_BYTE;
1 T6 n) |7 O* P  }
! x* k# ]! m" m5 o9 H& f  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)& r/ {  D& q* x8 s8 R
  {4 ~. y1 c, x$ z/ p) c. v+ h
    tmp_psize = FLASH_PSIZE_HALF_WORD;/ d% P6 _, q' ^, k3 T9 Q
  }
$ I# i! }6 ~/ n( d: ]- t& m  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)
& u- k. o! Z; m4 w8 `: W. s  {5 L3 n- D. c. j8 X/ V
    tmp_psize = FLASH_PSIZE_WORD;' L! _, Y: a( t: P3 G0 m9 X/ N
  }
0 M! i1 F5 z' n# Y8 T  else: b6 y# h* v7 K1 b! `5 p% _! a
  {
3 K. I( H8 p3 ]( w$ \. @# a    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
6 D; e5 u1 V$ T% W* C  }
# b# N" y) q' j- y2 s& o        4 V3 O9 t% P  h9 p  }: D5 f" ?1 O
        FLASH_WaitForLastOperation(0xFFF);
  E5 h' ]+ T' y+ l- A  /* If the previous operation is completed, proceed to erase the sector */4 S: o  {9 I8 g0 x& y6 i. ~
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
- L& D4 e) w8 u; r; y9 x  c  FLASH->CR |= tmp_psize;
' g$ i; K9 r2 i% ^7 U! X0 Y5 k  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
7 P  J; Z' R) f$ p3 L9 A  M& B+ t  FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);
3 V) V; r( J! p( A0 Q  FLASH->CR |= FLASH_CR_STRT;
4 O8 ]4 N. v, s$ k/ L}
7 m3 X) d: M5 ]$ o+ S- j1 g( z/ y" X) i8 i. F. H/ G

1 G4 O! M" F# X, h% d  x
% T) S$ I& J5 p* T; ?' V其它修改,串口修改:
  z- m& t* A3 R9 Y! Gvoid SerialPutChar(uint8_t c)6 h6 H5 U- ~* W; H% j% d6 \2 t
{4 |4 P$ i, H: _
  HAL_UART_Transmit_IT(&huart1, &c,1);
5 r* m; m; j8 I2 k3 {        while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);! j/ a8 }1 z/ G
}2 Q2 q1 r( D, Y$ s- e' j' {

% b5 j# q* M: M& r* x& U3 _, e1 l: J* Z& W+ c* ]
3 n) B1 s8 c3 K6 e. }
uint32_t SerialKeyPressed(uint8_t *key)4 z4 S0 n/ c; |
{2 V$ V# _7 n" q5 u0 K; G! K+ r/ L
        4 L: |: O( a: ]5 p
        if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK)3 m, A$ a' Z' `/ ~
        {
! s5 H  r0 w1 w5 U                return 1;
( }0 x! e. o. U9 I! J$ U$ K, F        }5 S8 Z  b' X  Y8 R
        else5 Z. g1 \. R/ h, H
        {
2 G4 N& N( n/ ]6 D                return 0;' \# o9 `3 U! u/ j, i% M4 n/ `
        }
. e7 F* n: {3 i4 ]5 N( |8 n6 N
# R, f& S, H' q0 J( H6 c}
0 ^6 u" t( V. C* ^& i$ ]8 s
/ j; O$ @( C5 ~在修改完成确认没有错误了,就需要如下操作:' ^7 b% i" n4 Q( g( K( p
修改main函数:( h0 \; f$ ]  B
int CmpStr(const char *data,const char *data1,int index1,int index2,int length);) m$ E* ^1 V3 a6 y5 Y0 Y0 q* P

' ?/ G; ?4 r( p4 H! u6 ^#ifdef  __GNUC__
; C8 e: A- M! L# f  p1 V. x6 N' M& h  t
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)  w( t# q/ C; b, l
        ( j$ p# H& s; l
#else2 Y7 A# j0 d6 M4 Q! ]
, u/ c6 M. p5 Q+ F9 S
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
0 m" x4 F' S  Y: I3 J$ q       
3 z# A' E5 Y% ]4 V" o4 ^#endif; Z+ C7 T& A) y3 k  f! K

" ^* [: ?6 O+ t! O: H' Y) _PUTCHAR_PROTOTYPE
# y+ d) ^, p3 q/ J$ E{1 s5 i0 ~! [0 \1 y: l6 g/ m
        HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
% z! A# U1 U2 s        return ch;! o# t- V7 ^/ W5 M4 o) V
}0 W2 D, }9 H% ]  o" b+ F
/* USER CODE END 0 */
( ?# y, M9 ]7 H( K2 ]! y& r  G; `% ?3 U4 V: Y% V
/**$ A9 g$ z. w2 y9 T
  * @brief  The application entry point.! F) C. l& y$ f! o
  * @retval int& a* ?, G  t0 r" |. K
  *// V% |! Q9 F" Z
int main(void)
* P, I! v. @: u7 q& d{, V# L. Q0 v7 R6 h# w+ m4 j; w
  /* USER CODE BEGIN 1 *// O2 m; M( t1 W
        //FLASH_If_Init();7 ~5 {; F  i6 N9 s. x/ B0 @0 B  W( S) G
  /* USER CODE END 1 */
/ E( z' b% e- c- s" C3 `: i  G- ?' q* N) Q

+ W. [* [9 p/ G, E8 D0 }) @- u* M  /* MCU Configuration--------------------------------------------------------*/
- _* _- v2 c. N. P: e4 C5 w( R& e
4 I. p$ S) ~3 t: T# S9 o* O  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */) c! s* A, P) i" F4 @2 O
  HAL_Init();
2 z. J  ^+ ]1 j5 b0 t* z( r4 @; V( L2 a
  /* USER CODE BEGIN Init */- E+ R/ j8 a: `- H+ @
  uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义
2 Z" N6 _8 o3 r3 n8 x6 m# Y  /* USER CODE END Init */4 R: E# X2 [. j. M

  m3 J4 ^3 ~$ \  O) l" U* d7 H  b$ r  /* Configure the system clock */0 f5 {1 O- X0 E& T; r
  SystemClock_Config();
3 B# x, c8 Z$ S) ]; j& n! o0 B7 V$ d$ Q
  /* USER CODE BEGIN SysInit */6 ?: V0 o& q1 o% P5 E

' n6 S6 E7 z3 c7 O. ~  /* USER CODE END SysInit */
0 \2 o2 K4 M1 J6 k: \- U- J
( H4 f  Y0 H, D& _! O  /* Initialize all configured peripherals */! ]# k1 r/ L: x
  MX_GPIO_Init();
  }, ^* {4 }* P% w# W* `; L3 ]0 O  MX_USART1_UART_Init();
( A. O" d6 r( G# Z& v+ c  /* USER CODE BEGIN 2 */. l& S. n+ I+ c( v7 d8 N# N+ z
       
' `) |) w: M* c6 a
" B4 L0 w% @  v8 x' K  /* USER CODE END 2 */
4 r! h: V9 q( P4 ?$ a. }) w6 \! s$ N# a, Z) R
  /* Infinite loop */
  r+ Q$ g' Y4 Y7 J; j) Z2 K0 |( W1 o  /* USER CODE BEGIN WHILE */4 y% E& X. G# S) e. u: b
  while (1)4 g# Q9 \& i* V( Z/ a1 D' t
  {$ t& n; ~* C' ~- ?9 V8 l% r6 s
               
6 A, o8 j5 V' ]# G8 a) A; B2 Y                Serial_PutString(mychar);
1 ]! x/ K' _, K: P1 P/ t
1 F" s8 V- X5 P: t                if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)
( k1 d* m% x5 I+ ~, U- p9 o# S% c                {9 C& b# ^& s+ K3 D5 e7 o4 e
                        if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义5 ]& V4 x2 Y  }: E! z: \) {/ }! D
                        {. }) P7 X3 v; y7 I1 k
                                printf("正在等待数据文件下发......\r\n");0 @) \9 ?' U) f, h" l4 v
. G9 W( s' m6 B
                               
4 D  H0 n0 `% J, F- Z+ [                                FLASH_If_Init();
2 q* D: K8 K; K( u) \2 N9 r                               
7 h2 Z$ t, K# L3 J. ~+ C                                //Main_Menu();
/ c3 Y$ b% G+ }0 v. M                                //FlashProtection = !FLASH_If_GetWriteProtectionStatus();; O1 A: ~" c  q& H2 N4 Y
                                SerialDownload();" q; p5 _# T3 b
                        }                        % d$ y+ O+ D. ~/ o
                }6 y1 g8 {0 S$ M+ t- N. ]
4 _' B0 h: W  B* n3 L; I8 P: o
    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
, g! L6 b) Y) ?: T    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000). o) A* ~: q6 F) T% t
    {
) @$ l4 W  p: V1 V/ P                        Serial_PutString((uint8_t *)"start user Program!\r\n\n");
- p' F1 h$ N) x& r                        //HAL_Delay(100);;8 @2 m3 ]1 J* G* z+ x# X
                        /* Jump to user application */
+ k5 N: E$ l* \! L( [) N      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);& U+ @# r6 h" m) I+ ]. |
      Jump_To_Application = (pFunction) JumpAddress;8 z: o5 y. d% V1 `
      /* Initialize user application's Stack Pointer */
9 ?8 F, W# d" Q) N      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);6 a! ~5 Z5 z6 C8 U8 F
                        Serial_PutString((uint8_t *)"Start program execution......\r\n\n");
% u6 d) l8 V! F: O% H                        //HAL_Delay(100);$ U' B7 y% B, ~8 [9 m
      Jump_To_Application();
& V7 `1 U$ M, ?& t    }$ [! z% g& j; T- v0 @) P+ E! k
                else
4 q. N: V* ~5 c5 I* r! h                {; e9 ?# B" N* V3 x9 Q: `+ E
                        Serial_PutString((uint8_t *)"no user Program\r\n\n");
- x- Y5 o2 S, T5 r4 o# B6 M                }
- z! g# k; E0 X/ Y, W1 z               
/ L/ F! H! c. U# ?) Q* A    /* USER CODE END WHILE */
1 x- a* {7 S% t5 ~% s" }* L$ a7 U' e1 m, Q; L
    /* USER CODE BEGIN 3 */
8 i( E7 w# R8 Z, m( L( S  }
. V" `" A4 ?% B$ i5 U/ W+ M$ j* ]  /* USER CODE END 3 */
9 D3 j+ g. m$ p6 H" q}
2 Y5 K3 l' x- F) S$ H' n  ?0 A( q5 T
5 J1 P; A. G, ^. s
& a% T) t; Z, @9 A6 \) \) W7 m
int CmpStr(const char *data,const char *data1,int index1,int index2,int length)+ n- ]4 z/ O' [2 \5 D& w# U
{
% |; k# ]! a1 `- K( `         //int temp = 0;
+ x3 u/ [% x- T- z; D         for(int i = 0; i< length;i++)
6 w% s6 S3 P" L9 M+ k         {
0 I" C3 E5 g! \; q9 d7 n/ ?- }* b* q                 if(*(data+index1+i)- *(data1+index2+i) >0)
: J: h+ }- q- c                 {$ J3 y! H! |5 _/ |* W
                         return 1;  1 C3 i6 @. ^' @1 K6 {- S
                 }1 J% b+ V, P- G! z8 a0 x
                 if(*(data+index1+i)- *(data1+index2+i) <0)6 E- T6 D+ a7 V7 d5 {6 z  p$ R
                 {
- g  G6 \2 f2 d& c6 J) o* F$ P                          return -1;
- T5 L) a$ F- w9 ?5 y                 }
0 }2 p' s& n8 }# o  y% g         }
- ?) F' |7 ~  x. B% b; X7 h         return 0;: k- o/ ?' t% |
}
! k$ \% F' v) A7 ]; D: S" x3 {- m
) j7 O. I  z' r; V
6 q9 `$ X! i8 X' l好了,基本就这些,有问题留言,我有时间就回复。。。
% I& e: j9 F7 L- v如果有好的提议,可以一起探讨一下!  k$ l; Z' C9 G/ [

串口1设置

串口1设置

stm32f4_iap_using_usart.zip

下载

1.66 MB, 下载次数: 195

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

下载

38.67 KB, 下载次数: 75

收藏 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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版