请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
qq344269956 发布时间:2020-1-19 15:47
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:8 }2 Y+ m  B8 y$ v9 M& X. r/ ]0 I
上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。0 [' J9 w: m' ?# a
+ Y5 Q, Z, g; H" ]' q* h
首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。
/ T$ }4 z" P' u+ S* g5 t
" C7 w9 B  F, U7 J; t& j! w然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动
& ~8 F; O: Z8 W7 f, C7 h
# D# W8 {/ i9 Z: u9 I, r; ^6 Y
设置了时间为168MHz,然后生成了一个HAL库的代码。9 }& a# L  G8 Y( M6 P. k) F- |  [

# A% Z" H2 ?" w$ W" p6 A将STM32F4xx_AN3965_V1.0.0里面的
% E7 e- i7 i  r/ h% Y& H. f( R+ vcommon.c8 M. p" @1 ~1 E/ u4 H
flash_if.c$ M/ q+ S7 s9 j  W' n* ~, p! g3 n) R
menu.c
5 c, Y9 N' p9 S+ W" _; Tymodem.c2 G# e$ {( `- r: ^% }
放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add  existiong .....)
0 X( K2 C3 o3 @! H8 T: \5 W2 {7 R! w4 r! X
在头文件中添加上头文件
( M5 K0 o+ B, h- \& X& d#include "menu.h". o! m: W( D; Z2 V  Q
#include "common.h"$ B# u, B1 L) r5 c; D
#include "string.h": u5 R- c7 H, R$ Z- O& N# r8 k
#include "stdio.h"
% L  Q5 K- E" Q, L5 y$ [# P& W# _0 P* X6 n" F$ X& t9 e
8 r% b& c: C% A
添加下面的这些外部定义  h2 x7 h1 D; D% p& g
extern pFunction Jump_To_Application;
) U8 O) e+ \) t- a" mextern uint32_t JumpAddress;% t" Y2 \4 ^3 y$ C
extern uint32_t FlashProtection;
4 P) O+ w) N0 B8 ^% Y( d' d% d, N

+ ^/ r( C. S3 i8 ]编译后会出现一些错误,主要有:
' j+ o7 d' j  w0 B- I  W# iFLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X9 |4 T" C: A" ~( E1 t4 m
. e8 Q; d: t0 Y% m# k
FLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:
, B, u9 b1 k6 P; k7 euint32_t FLASH_If_Erase(uint32_t StartSector)
$ ?* n8 h7 {9 ?/ Q% L% Q{( |1 L: X5 y6 b& b! s9 b: C* m- \
  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;
/ v+ G7 w( a8 R
( L4 J6 t( V5 T  /* Get the sector where start the user flash area */
$ w: @3 y$ x* W4 A# N  UserStartSector = GetSector(APPLICATION_ADDRESS);( [" u; z+ {: O1 [1 |; M4 L
8 p  `, U2 y+ e# M* o
  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)
, b4 C/ I) A! l0 a2 [  {9 N0 g+ ]9 a: H% y% V" d4 j8 @8 ]
    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will$ H# q2 o% G, V1 O8 L( J8 ~9 G; w1 c
       be done by word */
5 h( w  O8 X& v3 W    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);+ `- k* @$ [. g' O# H: f( g4 @
  }$ }- ^6 _0 \" M$ H
: h3 A7 w6 B& z- v8 _4 j7 V4 D
  return (0);! N- |$ k+ V5 @" b1 V* L4 ^3 R9 Q
}6 U" v7 m* Q7 d7 f* S# N6 u* \

) M! X1 Q: ~- `) J3 y5 s" l9 q* P( A# ]: q4 ~
其它的一些基本类似,解决办法都是是到:" V6 l' G) S/ u" t- a7 z/ W9 k- u. t
stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换
6 V! |/ i/ s, v8 U/ ~需要注意的是
( C! A" h7 D5 A有些函数:5 M$ y: \1 {+ ~
FLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中
5 r6 }- {- N& K) Z8 \. {/ ?" t' W2 Ovoid               FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);
' v! h" f# V4 y" W1 b, R/ D7 P6 QHAL_StatusTypeDef  FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);
( K2 I$ o1 s; B* q+ hHAL_StatusTypeDef  FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);7 s6 ^" L2 k( m$ w$ o6 e
HAL_StatusTypeDef  FLASH_OB_RDP_LevelConfig(uint8_t Level);
. Z3 u" W7 a0 ^: s' ~* x1 GHAL_StatusTypeDef  FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby);
8 P& k1 [$ L  ZHAL_StatusTypeDef  FLASH_OB_BOR_LevelConfig(uint8_t Level);4 |/ n2 W3 A5 l7 p& S0 c
uint8_t            FLASH_OB_GetUser(void);
7 e; F2 f0 U- q) N) guint16_t           FLASH_OB_GetWRP(void);
2 V3 z1 ?: M, Z( l; b' Z& Q3 M; kuint8_t            FLASH_OB_GetRDP(void);
. N8 ~, B6 @2 @" S8 E+ d. F0 ?: duint8_t            FLASH_OB_GetBOR(void);* {9 K% U  U' H3 ^

  d; J# H0 H2 d- P4 B将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。
5 F3 v& t" ~/ ^' u还需要修改这个函数+ ]/ M1 v& d" u5 f2 a% P8 _
uint32_t FLASH_If_Erase(uint32_t StartSector)3 r. z! t; h. d- H1 Y
{6 C2 M' N# w6 D9 l3 j* K9 _
  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;+ P0 h, e$ `% ^, o* E8 U

8 }. E, ^5 S; `  \: R  /* Get the sector where start the user flash area */6 T2 R- ]4 a" r) }1 \
  UserStartSector = GetSector(APPLICATION_ADDRESS);
: b1 w0 Q) {: T7 E' e: f/ N3 C* X# U/ O
  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1' i2 B: E/ E& G9 d
  {
" z1 o7 }$ {8 J2 E) `    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will# x, \2 E/ j3 y
       be done by word */ ( p. o; |* x& }8 i) W& i' b# ~
    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);
& M. L& k, y* y* g3 t  }! N- O( o0 v. B: B, }0 {1 x
+ w/ s2 S: |0 [6 `, E5 Q
  return (0);
! s& M# u0 s+ A0 z: ?* T6 f}. t( S2 ^( \0 Z$ _
  s. ?( I) R" Z# ?1 A+ D5 `1 d
. _! D) r* N. z* h4 b2 G0 u# y1 P

  K! @; X$ f- c$ y+ i9 h这个函数需要修改一下,标红的两句是新加的:
8 z4 D, ^: I5 C  F" }void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)) U( p3 H  E; p6 j, b3 T) p3 [" \
{* C# K: f. N, t$ C; s% a
  uint32_t tmp_psize = 0U;
6 I* o; q& v- ]$ F
2 T3 o& t0 P- g$ b9 m( o  /* Check the parameters */
+ W& I; Q! c+ k& C  assert_param(IS_FLASH_SECTOR(Sector));
9 q3 i  ^' j( M! E- ^4 g  assert_param(IS_VOLTAGERANGE(VoltageRange));: k; K+ @! }% j! X8 M
  FLASH_WaitForLastOperation(0xFFF);  B# ]% I; M$ g" V. o, {
  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)2 }* J( z3 h) v( O: {( E% t' U
  {
) {3 s3 m3 }' l4 w     tmp_psize = FLASH_PSIZE_BYTE;" c7 ]: U- M. j1 v- @
  }- Y$ r! N( U' _! U; n. `5 d+ f, J
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)
4 n2 ~8 p, C' J7 W( m  {
( G2 r. `* Z1 f" l    tmp_psize = FLASH_PSIZE_HALF_WORD;
% W0 N$ s3 o3 m% W2 o2 A  }
( I( ~( V! c; a4 U  x  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)* ~) L9 a1 U1 \* L/ z
  {
! F9 ]. ^, y, y" a9 Y+ e: v0 C/ B    tmp_psize = FLASH_PSIZE_WORD;
4 Y8 K8 Q2 I% O  }
, k* ?5 Y/ T1 \# S2 l  else9 A2 i* K# x5 ^7 }" y5 s
  {
6 k1 ~. E3 F* r& H; T5 _. L    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
( t+ s& [; v) D" E7 ^6 G  }: N1 X9 B3 `) O6 @7 K$ q  N+ B4 R
        . B. {8 W, k4 Q& Y- R  q; P/ _
        FLASH_WaitForLastOperation(0xFFF);- q! n8 Z2 P  m2 C
  /* If the previous operation is completed, proceed to erase the sector */. p8 Y; ]) I7 W  D
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
5 Z. k+ H1 G4 b$ u1 `5 A  FLASH->CR |= tmp_psize;5 g+ G3 z3 O8 x( A, p+ {
  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
* A$ L# q- s- F) F$ Z( g  FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);
6 p' }2 }) u- [; E  FLASH->CR |= FLASH_CR_STRT;+ D5 _$ L$ p# p; }$ Z4 _
}2 P! c' O* ^- m+ s$ s1 n; w, J

' B0 ^( `) `+ S+ R# q3 g2 o# a- [0 o# Z( x* _* `  e
" F5 o* L/ f9 @- N& ]
其它修改,串口修改:4 w- o: |7 k0 C1 d- g
void SerialPutChar(uint8_t c)! u  J' i: N0 c/ ^: D5 p$ Q
{) f+ |  A7 z; x; r7 e( o- T# ~2 h
  HAL_UART_Transmit_IT(&huart1, &c,1);
7 m4 Q' D5 m: T8 b" v. e        while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);, u& s' p& R" W5 |
}- d4 F$ B- b0 o

6 v  E# E" t* U$ |
$ S% z2 Z! o/ A2 \& e% T
0 H* f) K# `, i$ y5 Zuint32_t SerialKeyPressed(uint8_t *key)5 l3 @- V0 F- e. F: `) p9 c/ ~9 M0 {* G
{1 J' y+ A: r: `3 p
        3 U$ q2 a5 N1 s! A. H2 |$ K3 r
        if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK)
' t* n) E' Y9 d9 q* A6 R) J        {
- l5 @0 U1 y: b8 v2 @5 K                return 1;
) a) ~: g% m7 m4 @$ U        }" M9 S; s7 s! n" n8 M! M) M/ J
        else
/ |# E9 {+ Y" M, n/ M        {
: N! E! N4 I3 l                return 0;
( ]' y3 i/ j+ B7 @: b1 }6 q" |* u        }
5 p2 g. {/ G( s+ b* \) D4 M0 V' u8 b9 X" Y4 k5 X5 X
}4 Y2 L# M9 g- W

; G' K, J$ q: K在修改完成确认没有错误了,就需要如下操作:5 L- d; \! C0 W+ i) X
修改main函数:& c" N% q+ H: C2 f
int CmpStr(const char *data,const char *data1,int index1,int index2,int length);3 @* k1 N4 M5 M" J
$ E8 A2 n# ~& x+ u/ c
#ifdef  __GNUC__
; x% C4 z3 U+ M; X- s1 t9 W. w/ L6 D& }  F4 ]
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
1 i7 w4 n3 a5 S5 G. G, K  o: f       
# F5 E/ B* u- A4 h- q/ \#else0 z+ D  x, b; R- S+ k. c
* n* n' t0 D3 S5 {5 f
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
2 k( k; U5 W- Y0 N1 h        5 \0 V1 P9 g" i* P9 z
#endif
# z, z, n! h- x* o  v$ E2 h
6 j- c" B( y: c" z. I( t  iPUTCHAR_PROTOTYPE
1 H! a. c# r& H9 O! q{
; }2 U  L& Y, i' U2 r+ C) U6 B        HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);( R! v  B9 @( c+ ^! _
        return ch;
0 }: a) i: T9 b9 p; r. Z}( @  q9 N7 z# Z  }
/* USER CODE END 0 */
7 \) o) Y$ v, b- _" _, ^
( n" M7 J' F  z4 w3 z/**
- @* Z" v2 w2 ~4 `# j+ a  * @brief  The application entry point.
! E$ a7 T& j& Z) r% N5 i  * @retval int6 N/ s* V9 M5 V4 z3 Z. e6 X
  */
% z* r) D8 U6 tint main(void)
4 z) |) n6 h, D{
1 R3 T# X* Q1 ]9 _  /* USER CODE BEGIN 1 */
8 z7 \: r8 h( `$ `+ ]) p        //FLASH_If_Init();! @7 K+ l* P; f1 e7 z
  /* USER CODE END 1 */
* n% n, u& s3 K9 j! D) Q  w
0 k# g* ]. h2 U
! X5 y0 Z2 E0 T' l  /* MCU Configuration--------------------------------------------------------*/6 [# n/ O8 `. _2 g- c/ F. P

' k) `$ ]9 l* @  A  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */* k" \) V( I2 I: t# U1 y
  HAL_Init();
* n  n4 u; N! e& z' O6 h4 y5 S' r% B  M# E: ^5 k; g' B; i0 y
  /* USER CODE BEGIN Init */  ~* r3 j* E- q0 r+ [4 `' |* A  n
  uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义5 ]3 x* P5 M7 W6 e! ^
  /* USER CODE END Init */" H* K2 U! l% V# |9 t
; [6 U! s+ ?0 Y  k( b" Z- Z! t
  /* Configure the system clock */
6 t# E4 m" @* W1 _' T: j, v, A! W  SystemClock_Config();
$ q1 L6 R; f" e# O. c( o6 c! V) y" C9 Y1 n9 u) s/ y' q" V7 h
  /* USER CODE BEGIN SysInit */
  O# K. ^) l- u# M5 x0 Q+ t; T+ Z$ T1 H0 f+ u3 W
  /* USER CODE END SysInit */9 R" D4 I- m# o2 U' k5 ]0 f8 _
4 N# B5 M1 a! v) g- ^! O
  /* Initialize all configured peripherals */
3 \& t8 K- a3 r7 z. m& A  MX_GPIO_Init();
( ?: N5 |6 l$ p  MX_USART1_UART_Init();
+ C+ A! @1 _4 i# q. H$ k* Y+ a- p4 c  /* USER CODE BEGIN 2 */
- B$ x# b; z* n       
$ ^# x( x2 I; j. m/ x# E! }% u+ t" F5 J2 ?
0 U) K  ~9 @8 L4 \5 P/ j  /* USER CODE END 2 */
; T( K& P, R4 D6 s! Y
6 \2 ~* H3 Q, Y8 b, Y, S) b  /* Infinite loop */
" J% X1 o5 x+ ?/ S  /* USER CODE BEGIN WHILE */( V) g1 R' m$ ?; x
  while (1)$ \" G$ s- `1 f" z8 v9 M
  {
8 c4 \) h- l! d4 O" c: W+ r5 s                * y2 L1 f4 L' Y0 Q: t) s
                Serial_PutString(mychar);; V& M7 w: q9 W

, o! v, L  @) q( S5 ?                if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)9 O9 u& F. z" [( g/ d. ~" c
                {
2 r' Z; X* b7 y( w9 i9 E, v4 n# t- y                        if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义
( G0 {  @5 X8 Y0 |$ T                        {* C) y8 r' _, L- ^
                                printf("正在等待数据文件下发......\r\n");4 I1 Z# \7 }) C) s" m8 p7 F/ o
* @( K7 s6 n8 U1 i& q; B5 o# s8 z
                                ) C2 P; [3 ]$ C
                                FLASH_If_Init();* ?+ k) R# j3 Z* c4 {+ C) m* P
                                . s. }* p* V7 |+ a* W; _9 i
                                //Main_Menu();
8 S" b( l- }, j& y( w& \& u                                //FlashProtection = !FLASH_If_GetWriteProtectionStatus();
+ @1 ?. E( b" b/ `& x) n$ B                                SerialDownload();
' B$ W- f5 M; S7 |                        }                       
* O; U8 b3 ]8 @: C8 w  m9 @4 i                }) y7 e$ w" b: \' q6 ^! y

1 G2 q4 {2 u9 l" N! W    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */) n- M9 M- M" ]5 e; X
    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
0 u4 D) j7 _* \; X    { % X4 |. r& Q/ \
                        Serial_PutString((uint8_t *)"start user Program!\r\n\n");' Q! [9 S. @1 h0 w2 `7 F$ T
                        //HAL_Delay(100);;( U# c) \5 ~6 [
                        /* Jump to user application */
' n2 M! w0 E+ Y) p3 Z      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
# {( i, Z# L% ~      Jump_To_Application = (pFunction) JumpAddress;
) w4 {/ ~" j, \' ?% v9 F      /* Initialize user application's Stack Pointer */
; w' F8 m. C6 ?  f1 m      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
" f& e* h7 k8 _4 F. C* p                        Serial_PutString((uint8_t *)"Start program execution......\r\n\n");
- R0 D) ^/ ?/ @" Q                        //HAL_Delay(100);
$ Y6 |; w) W- q' @" n' W      Jump_To_Application();+ V* N3 b' {9 k! N% Q' S
    }
( j5 M# D- `% Q2 r3 [8 A3 s                else
2 |  I  y  V, `% ~. W, W9 f                {
' @9 \; b$ p2 Q/ v& [9 l, h                        Serial_PutString((uint8_t *)"no user Program\r\n\n");
8 H, x7 e" c6 n2 O+ }4 L/ F6 E                }8 e1 E9 e1 ~9 X3 N
                9 J/ ^& G0 \5 f9 k" @; q1 n
    /* USER CODE END WHILE */$ \7 x6 ^% T$ i1 g
6 f& V6 {  D+ j" j6 V' S
    /* USER CODE BEGIN 3 */1 W) l  P* t- f% z) N
  }
0 t: d1 h7 M* b( E& Q; ?/ D* n  /* USER CODE END 3 */
4 i9 t$ Z2 s+ c5 ]}
+ z2 i# N. p" i7 b4 r2 d: e1 Z! p3 W& B
7 J: k! q7 j' z+ N! {
; \1 p7 g3 @8 Q0 W
int CmpStr(const char *data,const char *data1,int index1,int index2,int length)
' Q4 s: P& Q" ?6 o% J8 X& b {$ Q' f+ M! I8 ~& w
         //int temp = 0;! M0 H  y2 X. Z5 _3 q$ G
         for(int i = 0; i< length;i++)
4 w7 @, K1 {9 M9 W         {
+ x# Y4 J* U$ ]  j2 ~* z# o( f                 if(*(data+index1+i)- *(data1+index2+i) >0)1 H8 N+ T4 Y: v( w& f  X6 r
                 {, q* g% f5 M0 [5 N4 b
                         return 1;  
4 d* o$ j( @3 M/ G                 }3 s8 `$ @4 q) R
                 if(*(data+index1+i)- *(data1+index2+i) <0)# ^- l0 A0 z- K; K, e4 W
                 {
" v( d. Q) U7 P2 U5 a* r2 f                          return -1;
" w2 I; G2 B" A3 q$ K7 ^% `                 }( s6 ?; e- Y9 i) R
         }& u* W: l% r5 D$ w9 {0 J
         return 0;6 h4 ]  Y2 [3 _- ~. [* d
}
) ?: y2 f  h' d! h# @& a8 ^( w+ O- }6 A# _: M7 y
" n* l: p( P4 H! }# w6 L( Q
好了,基本就这些,有问题留言,我有时间就回复。。。) Q8 S' h2 e4 O# `, [
如果有好的提议,可以一起探讨一下!
. M) q2 ]' L0 |

串口1设置

串口1设置

stm32f4_iap_using_usart.zip

下载

1.66 MB, 下载次数: 178

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

下载

38.67 KB, 下载次数: 62

收藏 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管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版