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

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

[复制链接]
qq344269956 发布时间:2020-1-19 15:47
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:% Y% X) m2 Q/ J' i: j
上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。
4 w! x1 n- B( ?: i. L7 a  r% L* r, c# R. @* a5 h. ?5 g1 O# E2 k. ]
首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。
( \0 }; u+ R# v6 a
- u/ R; y% H  N; O5 \* o5 ^1 o然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动
) b. j! O" b' M+ x1 M& N$ ]
' u: B9 G: ?. P5 k, k$ a6 F; R- J( J" V" N- E4 p5 D
设置了时间为168MHz,然后生成了一个HAL库的代码。2 h; Z. f$ w! r( E0 b

6 W8 s9 n5 T1 Y% i* G- q( x, Q* A将STM32F4xx_AN3965_V1.0.0里面的# ~) g) Z, e+ Z% }& D7 c7 e
common.c
; c" a6 a, O' ?- J$ [: Hflash_if.c- l& k& Z8 S9 v5 W$ ?# ]2 k) a: o
menu.c
! F8 V# w6 P6 S5 cymodem.c5 t: Y9 ?2 r- z# }" ^) e4 y. x  V
放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add  existiong .....)
) {6 d5 c" K/ e2 {6 l" X. B7 n% U& d* ?% O
在头文件中添加上头文件+ h8 U5 M5 z! f  ]
#include "menu.h"8 g4 i! \  y; v( M# Z
#include "common.h"
8 Q0 p4 m/ D& t& Y* B9 b#include "string.h"' y% n1 \, u6 e
#include "stdio.h"
" `0 ?4 s# G0 F5 D" A( z
" W  x5 p' ^1 b) u
! K3 u2 n) P4 K8 x4 n添加下面的这些外部定义
% j% G+ B/ J1 d  D8 D2 Oextern pFunction Jump_To_Application;" r, Y( }$ K4 f% o$ X; w
extern uint32_t JumpAddress;
" S& }4 g$ v; V- F) E0 ?6 fextern uint32_t FlashProtection;
8 B' X4 U( n, u+ U8 C' s
( q1 b( a3 |/ b: L, m
/ E! o' M9 Q- ?/ J编译后会出现一些错误,主要有:8 {- T; ^3 J* h* a# F% U
FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X& A- a* w# Z9 ]1 z8 V7 X) l

7 D# x0 C  w# GFLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:; Y6 @# r: e" M& F! r5 P/ ]/ M
uint32_t FLASH_If_Erase(uint32_t StartSector)
; t9 }# h3 `: j0 E{! G- ~- O% a5 _3 ~0 ^; a4 {9 ?
  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;
9 T8 h' N# c! `. V6 V$ W& X7 F* M+ U; e( l; n6 Y
  /* Get the sector where start the user flash area */
/ ]: j- S: m6 M  UserStartSector = GetSector(APPLICATION_ADDRESS);5 C8 M! I2 V' Q+ v

( [& t( u& c0 f* \1 p  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)0 D" g: i2 n' _2 ?) x; k
  {
% P" u" d( [: p    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will+ P( A$ X- e1 A2 M, r! N- ~
       be done by word */   s$ p, Q$ h8 J9 z9 c0 L- ~
    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);$ V7 O6 G, Q8 |' r, [
  }
$ x. H3 q( b( b! ~$ s5 Z
. X" F. V! N# V: ^2 k  return (0);2 ?7 u( l# t/ ?1 @4 O% c
}
' X) p3 I' E! L# s: K" W0 |6 {+ R+ C1 e+ N* l) Q2 l( Z- ?; L+ }! U

' _  n7 r' ]8 M5 ]0 H  q  f其它的一些基本类似,解决办法都是是到:$ \) H6 ?0 C( M* ^2 D4 V$ {
stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换( G/ }  e! ~7 P) W" j( V3 f
需要注意的是: F! F5 `& R( C+ g7 Q! |# t
有些函数:* K/ t4 {3 ?+ X  b2 a* O0 R
FLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中
4 B7 S/ e& |9 U2 l, L* Lvoid               FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);0 x, w; l. T1 c  b
HAL_StatusTypeDef  FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);* y( r+ g* b+ q
HAL_StatusTypeDef  FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);" T6 f7 o% W4 e& d9 P* A) t
HAL_StatusTypeDef  FLASH_OB_RDP_LevelConfig(uint8_t Level);  o+ ~4 F7 g9 C6 ^- O
HAL_StatusTypeDef  FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby);
) @: L; ]3 C4 p0 uHAL_StatusTypeDef  FLASH_OB_BOR_LevelConfig(uint8_t Level);
4 R% V% m/ _  J( f4 _# F5 S+ V+ kuint8_t            FLASH_OB_GetUser(void);) K. ~& t+ Y6 Y  E1 Q3 N: @
uint16_t           FLASH_OB_GetWRP(void);
/ \5 J! {8 T7 [0 T2 }0 d& puint8_t            FLASH_OB_GetRDP(void);/ z* ]0 o' e3 T1 V. ^' [- ^
uint8_t            FLASH_OB_GetBOR(void);
. P( U2 r5 r% H% \& b
& p0 {2 N# ]* n% v" ?4 @* }将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。
7 k  @- r, f3 q( K- ?% G+ i还需要修改这个函数
# Z: {5 |: o/ o# Buint32_t FLASH_If_Erase(uint32_t StartSector); r- i7 a8 e/ V
{
* Y, e; A4 J; `  h2 ?+ E  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;
4 b* E6 r; D' q; ]% w, J6 G& e! \6 p
  /* Get the sector where start the user flash area */! C3 {% I0 O3 I  u1 F  u% Q7 G; Y
  UserStartSector = GetSector(APPLICATION_ADDRESS);
" n0 p. \& J* |, D2 H0 v% D- ~! s, Q+ Z, L; q
  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1
) m6 p4 s5 V& q% ?& f/ b  {
/ I; N5 x5 M/ t- I9 L( i  a3 e    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
, J+ H( Q$ r& f: I: Z% B       be done by word */ % G0 o7 }. K, v, Q( i# f( O$ R
    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);; ?4 ?% O; h5 t8 V
  }
0 A2 _3 ]5 E9 T9 x3 [2 g
; E) n. V" `3 g: p  return (0);
6 Q6 G! z1 J6 p* ~6 `}
: W# t9 }: H  _1 V( w' F0 R% c( E/ a# q; A
' d+ N) }  T" s7 [, h
( A, a% {6 d( N9 h' ]
这个函数需要修改一下,标红的两句是新加的:
$ [+ B8 @& u* l" m: mvoid FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)2 ]8 P* v7 K1 i4 s5 n
{  N' F5 }# q! }7 [7 e
  uint32_t tmp_psize = 0U;8 h2 ]2 X( o9 I1 N

' w' S3 _7 \2 L$ l# C  /* Check the parameters */4 V& V2 ~1 ?4 v* R1 I  v7 q# l2 p7 E
  assert_param(IS_FLASH_SECTOR(Sector));& i5 K. o0 i# h* f1 t  c
  assert_param(IS_VOLTAGERANGE(VoltageRange));% ~% }$ p) I# R; |0 y  k2 Q# A  f  ?
  FLASH_WaitForLastOperation(0xFFF);- x% Y' \7 \; s* y; {4 Z
  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)
: d/ V$ H1 A2 |; J3 b: Z/ A) B  {
$ @1 m) h! f& ]: J- N     tmp_psize = FLASH_PSIZE_BYTE;
! g2 x5 X" t% b0 S9 M( W) @' k  }: F. e1 A9 \* \9 t
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)
( N4 b3 A7 a+ ^' F/ A  {$ n$ J  G& K7 V0 X5 V6 B
    tmp_psize = FLASH_PSIZE_HALF_WORD;
9 g% g( ~4 n- A  `  }
5 A. R) G2 s' I0 B  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)
5 T0 N$ _; k, v' c' b/ o; R3 ^/ z  {
* [) F3 Z# B* y* r. _% A# i    tmp_psize = FLASH_PSIZE_WORD;
( g. G& g1 J* m1 l  }; v. ^8 o( O2 ~# I
  else+ j& h- Z: m6 E3 G9 E4 i
  {$ c9 I, U  W2 V* U* w
    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
6 K: B1 W- v' N- @$ G5 g2 ]  }- f& o2 Z( m/ k: f6 _
        , I% Q3 g' I2 V2 N
        FLASH_WaitForLastOperation(0xFFF);
. H* {, _# v( Q; \! t2 y  /* If the previous operation is completed, proceed to erase the sector */! e! o+ H! x% Y# Z! w" V: B
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
  _# b  d0 B  h' q7 D7 i6 ]  FLASH->CR |= tmp_psize;
% l) R- v$ A7 o+ K2 Y  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);0 f) O% Z; {; ~( O" ^; k5 p4 n, Z' n
  FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);# }: F+ {9 A* U! h7 |
  FLASH->CR |= FLASH_CR_STRT;1 c/ K) X5 Y9 i- @8 ?" w
}
' m) N8 z  Z- P$ T# f; h9 x: f8 X" y! r; k# E

5 Z+ j( ^9 G, r/ a; `6 g" y0 A" R$ R4 g
其它修改,串口修改:
$ {7 t3 u; w0 Bvoid SerialPutChar(uint8_t c)
9 d( j1 O* Y& u' X; f9 x/ k6 v{
/ y  o$ p" u/ n3 i  P- o3 ~  HAL_UART_Transmit_IT(&huart1, &c,1);
: C2 d  }3 d; s  h/ G  H/ d( Q        while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);
( c* Q5 F, T8 F. n5 ^3 O( z}
6 u) [/ ~; M) {. c/ @+ O3 e7 k* x8 t! [4 o

$ k) R3 k4 Z' ?- b. R  |) |, t( I+ I  d' g3 S
uint32_t SerialKeyPressed(uint8_t *key)
3 K! ]- M; O# L3 t3 @$ X& V{! K+ w/ H. l  P$ a8 e% l- [
        * ?6 N- s) V# {% d- S
        if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK)4 i7 Q% P3 P% {' d& l
        {- J. u! D+ G; e" t
                return 1;+ P+ `3 W% x) c% v5 L8 W7 w
        }
" A; R: {1 d; V. p! o6 ?0 |- {% s        else
. \8 C( d- y2 S  p9 A9 r4 O        {
! g, x/ m/ R, _& a+ ^                return 0;  [4 r5 s' Z: g, b( N# z+ F
        }7 H* g. w: c* _$ u
& _9 M. C# b( Y4 M& A* U
}. a% T: s  }: z- h: A

; h0 E5 R% Q' b) u8 J. r! x' J; k在修改完成确认没有错误了,就需要如下操作:' _% B5 H, N0 M  ^, Q
修改main函数:
$ c: b) g2 B7 F& v* v. Nint CmpStr(const char *data,const char *data1,int index1,int index2,int length);% u/ a! {+ y3 @$ e* R+ r7 S

. J0 d- g5 @7 \#ifdef  __GNUC__
2 w+ N$ c: W0 B: U/ W* |4 G* Y% ~9 Z0 ~5 H+ Q+ ?7 Q
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)& u. f8 w2 P/ V1 w0 m7 f
       
: B' x7 v3 x; V; Z. N5 Z1 D8 {#else
8 b4 r" l* h4 l5 B! n1 G( h) h2 x$ x3 ]) j# |4 y# B
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
9 x) E. d( u: U) t8 g% v% H       
7 X! Q" r* @; Q% K/ S#endif4 i8 n2 @/ R. `' D# {
8 C2 A; `) D: E2 E
PUTCHAR_PROTOTYPE  E* I- J% e; V8 O
{" m5 p6 w# y4 k
        HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
8 j8 t$ S# w( d  M        return ch;$ a4 L: h$ E  Q0 B
}
6 J1 F0 B8 V5 `, e/* USER CODE END 0 */
9 g- K# J& U" D
# ]( r: A+ g9 r8 U7 A/ r/**
% G& r: v. _. t: S6 i; C8 J" U) m9 B  * @brief  The application entry point.+ Z/ _/ L2 g1 K  u* T
  * @retval int
5 E" k" S8 W# O0 _$ D  */
% G" D# x! i) J" x) s. tint main(void), \9 d4 A4 {& ^- |$ _8 x# P  a
{1 ~& t( V( x. A$ H" L& p  I$ k
  /* USER CODE BEGIN 1 */1 Q( C" m" E9 q) ]* P  ^" f# w
        //FLASH_If_Init();
% o" c* O. d' N- R* j; F2 |# [  /* USER CODE END 1 */
' ^' k8 M# `8 ?% u0 K2 @: h7 m  G% i& X4 H* ~8 u! g7 |

  @4 y7 I; L7 c' x, }  /* MCU Configuration--------------------------------------------------------*/6 t, P7 z; t) q1 L: b+ }7 O
. u7 T4 B' h+ l4 H" E% d
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */( W, R) S! r0 D
  HAL_Init();
) ^$ e. H3 A0 i$ Z& i
: r; z- \; J& h3 m2 R; B- _* J  /* USER CODE BEGIN Init */
; X' q+ g  S+ Y1 z7 I1 h( h  uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义- Y1 Q8 c0 s+ b5 ?" H* w- Q& v
  /* USER CODE END Init */
4 c5 a  a% s8 G4 I' p$ U2 s$ v& z
$ ^# t: A2 @2 n1 t7 Y5 [& z" v  /* Configure the system clock */! z9 \/ R" b, x) s7 O* n" x7 `# [
  SystemClock_Config();* Y6 k! |) C7 K, C( A

: |6 x  }3 g9 \; [  `. F) ^  /* USER CODE BEGIN SysInit */6 [8 Z  g7 g/ e) C" k: ~
1 X8 O# S6 _- u2 M
  /* USER CODE END SysInit */
0 U, C; c& l, q7 u: y: {
- C9 Q4 U0 f0 f0 k+ C4 t  /* Initialize all configured peripherals */0 ~6 f" m$ Y9 X) d8 Z/ x/ U
  MX_GPIO_Init();5 w5 \6 s2 y6 P! V7 B8 `4 _9 {
  MX_USART1_UART_Init();9 ^5 Y: e2 y! z0 a
  /* USER CODE BEGIN 2 */
& y: a" V: F1 C; Z& |. u& s5 m        3 [; m8 m2 q# p/ y2 |2 r

) n* Z2 T5 P$ T! }3 N& `  /* USER CODE END 2 */
. u% h7 J$ T+ ?3 q
( U. i  M3 r# r1 s( F  /* Infinite loop */  }$ I% f& L3 c' \& y0 o7 E% `
  /* USER CODE BEGIN WHILE */
5 r; s" P5 @: z! h/ y3 Z  while (1)
" q! X0 X" H6 S  {0 t, @4 J( A, @- T" P6 H& g
                4 h( e7 r1 S+ |
                Serial_PutString(mychar);
( Q+ {/ s6 D/ U
" T% o4 o5 l1 y& f                if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)
4 q% ?* {/ o' ~& t( F; p5 r                {$ y9 E0 e4 h; n7 T0 @2 `) x
                        if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义- M1 S- Q) a) C6 Z5 e# l& w
                        {
8 @+ H; `: U! q# U) H                                printf("正在等待数据文件下发......\r\n");
6 x9 \3 |' [+ h; O  c
7 y! S4 ?( l% M( D4 Z5 K  u                                . K- A' I2 p- M' ^7 u: A" y
                                FLASH_If_Init();
8 Y; V2 @  C. n% k                                + v+ o6 Z' h& c% f, Q3 |
                                //Main_Menu();
! Y7 `0 p; G7 O, Q0 M! z                                //FlashProtection = !FLASH_If_GetWriteProtectionStatus();0 x* u: L- k- g% _0 j& M2 I- L
                                SerialDownload();: ]. V7 |0 v( f
                        }                        * \7 ]4 o4 g" A& ~. L( i
                }4 ?$ Z% z+ i8 u; @4 Q+ Y2 m3 X3 w

; K' \! N# g3 q* V& X0 G    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */0 A% O7 o: |, r: b$ ~
    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
. \. I2 E5 c! U4 e    {
# u+ N1 r2 _1 R, j# ^                        Serial_PutString((uint8_t *)"start user Program!\r\n\n");2 X$ s& @4 y; H7 Y
                        //HAL_Delay(100);;1 l7 Z" J; Q( [2 [
                        /* Jump to user application */0 l  U: L3 p" {
      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);9 G# B. z# K% X# z' g# B! q, X0 u+ C
      Jump_To_Application = (pFunction) JumpAddress;
$ z9 }/ H" M1 q$ L) K+ M      /* Initialize user application's Stack Pointer */# X8 Q/ A: z" U( v/ W
      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);" i# \( }* B4 r- M4 H6 b- u1 _; r
                        Serial_PutString((uint8_t *)"Start program execution......\r\n\n");
! S9 y# ^. D2 S5 ?: k                        //HAL_Delay(100);) K! N+ q( k7 t' x4 t
      Jump_To_Application();+ D% R  k5 ~, J5 l7 B5 B
    }' z* c6 U' f9 E2 Q2 A  f# ?4 W. H
                else
3 L, u" l6 z3 d  t# R' z                {: ?5 i: I4 u- p8 F1 s! ~
                        Serial_PutString((uint8_t *)"no user Program\r\n\n");
6 h7 o- Y: y0 W5 \# w8 j                }
2 R2 K- ~" b; ?7 j" t% c               
& [. V6 j- n" R4 z$ ?    /* USER CODE END WHILE */
% B$ y( |9 v7 u& o6 j$ S' F" {
8 e( C' t5 A( C  S- q) q1 d4 T& X, ?    /* USER CODE BEGIN 3 */
6 H. {6 `9 _- y& i2 h! o  }
1 n/ n9 g) H7 F! w% |6 T4 |7 T- e+ T  /* USER CODE END 3 */, b' m/ [  d4 j  j
}/ x* w' r2 ~3 R) r7 P
* U4 r$ y1 O$ ^; V# z: Z9 p
, J  U( \8 ^% Z( t# J* o
+ i9 U* w) c" ^5 g' R; q% D
int CmpStr(const char *data,const char *data1,int index1,int index2,int length)" @( K& P$ R( a) P( Q& X* d' O: J
{
. ]! w% O/ Y3 |* u* d         //int temp = 0;
  }1 A5 ~6 O$ B; V! I8 K         for(int i = 0; i< length;i++)
! H5 P: h3 L6 {/ C4 N         {
3 M0 v7 b2 {; b  L; g                 if(*(data+index1+i)- *(data1+index2+i) >0)2 @* T( \4 J6 p$ p! g( c5 x# I" q0 J
                 {$ t) g5 ~) T% V! n4 k; j: b; _
                         return 1;  0 I4 B- p  @7 A0 ]6 a6 d
                 }+ B1 P: P3 d9 T: M. L  E
                 if(*(data+index1+i)- *(data1+index2+i) <0)
& v& W# `' j& j" n9 ^4 y' ]                 {
" F: y# Y9 V) t5 F0 i                          return -1;- q: _/ s3 s( ]5 x8 j, q
                 }
$ F. E: `% [+ a7 l         }0 R; Q. b4 s  ~/ S: @
         return 0;
, V4 |6 z% Y' J( r- n! | }
1 @7 E( \* Z6 p( v$ k7 B
( e! Q) e& |3 g7 L8 ]( v3 \) H
6 ^- Y  l* b. k! c2 E* \好了,基本就这些,有问题留言,我有时间就回复。。。
* Q$ v2 e! B, ?" m& C9 S如果有好的提议,可以一起探讨一下!
# f; G; L8 N- n0 v; _

串口1设置

串口1设置

stm32f4_iap_using_usart.zip

下载

1.66 MB, 下载次数: 203

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

下载

38.67 KB, 下载次数: 79

赞 收藏 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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版