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

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

[复制链接]
qq344269956 发布时间:2020-1-19 15:47
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:
4 g$ g. O. k$ K: ^% d& n. b上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。
, C6 R/ c+ k3 F- E" ^: J
5 @0 v9 v  \) G, J7 l$ H首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。
! `7 A; i: M4 r% t1 }  M
, P: V0 p  F. O然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动
* [# R% M" z0 O" p* v  i7 Z) }0 i/ r1 e* }
% f* E  ?* M0 P$ \; u% q
设置了时间为168MHz,然后生成了一个HAL库的代码。
% T, a: N! r0 L5 c" F' K. d6 R* B; {$ q6 @
将STM32F4xx_AN3965_V1.0.0里面的
: p* [2 R1 G, E' N* E7 Ecommon.c
) q0 d, e* {1 k4 n4 s  u/ ^flash_if.c) @: d8 x1 v/ S: _( |. Y, d
menu.c
1 m# {& R% f) F& |, ^/ h0 Uymodem.c  i3 f6 D, M; B& g! O. Y( J
放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add  existiong .....)
, [; x- i8 p; j, _3 z% N# A' W- G4 G7 S0 B# b
在头文件中添加上头文件
3 ?! ~" s. }& ^4 R% T#include "menu.h"
* J  z1 X8 y* [3 A# n#include "common.h"
  m7 x$ w0 M6 G0 C0 l#include "string.h"
' |3 d. T; e3 S#include "stdio.h"
2 d# Q+ f6 E& a7 h% R/ L* e
; V. k3 T. K; r4 w& r+ U+ u9 C0 A$ m- k4 E
添加下面的这些外部定义3 P* `4 `: A, b$ K$ b7 ], Z" T
extern pFunction Jump_To_Application;
9 R5 ^0 l7 p- j. h6 Zextern uint32_t JumpAddress;1 A4 W8 K  k2 _& o
extern uint32_t FlashProtection;  ]! m; F8 m& b% \

( V  c% k' Z/ V; s
- s2 k4 P1 M8 W: |6 D: R5 A2 z, r编译后会出现一些错误,主要有:* [6 v3 G7 x+ \2 R
FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X' ]) ]8 u, l: w# s, G" B9 D8 W- k

4 g! ?5 U$ J1 ^# G9 X# V( C: V: OFLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:
# B1 R" Q! u1 Q- m; ]" [' Uuint32_t FLASH_If_Erase(uint32_t StartSector)+ q+ q4 o/ J9 }. Y; Z3 P
{4 `' r* v$ _2 T2 w/ |* Q; k
  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;
2 K  ?, ]) w6 W  r1 y. w# u) [" E
/ T0 l8 P# L/ S$ s' o7 g  /* Get the sector where start the user flash area */
; z% V. i8 S2 f  UserStartSector = GetSector(APPLICATION_ADDRESS);. c* t* M& E* }! }7 S3 D

0 i: e' e5 E( d) Q  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)
. D* W$ N# F0 [  {  {
2 i0 r2 y. V' h# k4 i' w    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will7 u7 M" ]7 ^* g: o/ m2 Z
       be done by word */ ) |2 o9 s4 A* A% ^* {) ^! s
    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);4 w7 i! H# c( a2 l
  }9 H/ ]" _+ h  L$ u3 m) j  o- }
0 L2 S) A0 q7 p/ E2 x' m- z
  return (0);: G: d9 F% B6 o& b5 l. |2 [7 R
}  M2 _- ^6 a! F  p

  y- a/ U& U' e) x
, V0 I6 E0 W( C* \1 U其它的一些基本类似,解决办法都是是到:' B# c8 s6 o0 O$ Y4 J
stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换# U& C9 @1 u6 M) f
需要注意的是
! Q0 F' l. B. I4 Z! z* g3 J有些函数:
+ k4 @% B" `" W; C1 G5 mFLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中
$ F/ U$ m, G1 G- ovoid               FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);
+ v/ L8 \! A* D8 ^% V& ~HAL_StatusTypeDef  FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);
& B9 V# h& c( vHAL_StatusTypeDef  FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);
4 @# @9 M' c, Q  \; m; UHAL_StatusTypeDef  FLASH_OB_RDP_LevelConfig(uint8_t Level);
! A6 l3 I& I2 p3 {. e! v# {0 EHAL_StatusTypeDef  FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby);8 p( y+ B# {7 \
HAL_StatusTypeDef  FLASH_OB_BOR_LevelConfig(uint8_t Level);0 d! N% }- i0 u0 l0 `, D( ^
uint8_t            FLASH_OB_GetUser(void);- o( N, |# w% o7 v" B$ ^
uint16_t           FLASH_OB_GetWRP(void);0 C4 q& I2 m4 c) r4 H0 q0 O  Z  ?
uint8_t            FLASH_OB_GetRDP(void);. z1 N$ D( t0 E% o
uint8_t            FLASH_OB_GetBOR(void);
0 F* n& J' Z+ ^- m5 R8 ~! G. \' J0 f3 b: x" [/ A" r1 V( _- z! a6 |) Z1 L
将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。
: U  f& v" k- J- s4 d0 l还需要修改这个函数
/ u7 L! w6 u: t0 r2 `uint32_t FLASH_If_Erase(uint32_t StartSector)! x0 _( h3 k8 F( V* s. x
{
7 ]% ^1 L$ \6 U0 ?0 d1 c& |  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;
; T- v" {7 T9 c: O6 V) s; ?/ f/ I
2 s: N" W0 l2 K+ G  /* Get the sector where start the user flash area */
# p* m( r) i9 Z) r  UserStartSector = GetSector(APPLICATION_ADDRESS);6 b9 v. l+ K# w- S3 g

% v5 o7 q$ T2 }! u  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+18 A- X0 m' z/ J2 v/ V$ l/ V5 T: z
  {
6 g, e5 E& L! V4 R) @    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will* N+ d( K1 p$ L
       be done by word */
( I  C7 @# d0 y$ S9 t5 d' T7 k    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);8 \4 ]4 c2 B# z" b
  }
2 y& M; }/ F- j+ H- ?5 ?! i: E
+ S2 G; z% m3 X/ l! C' F- a2 F: \+ [) J  return (0);
9 r$ m" Q: _% ]1 C& E- _: n" _}
1 w& ~9 i2 @  x  y' [7 }% U1 `: v. A5 U5 W
9 N. G& l9 ^1 o8 f6 t
% t0 A  v' J1 I" T8 e) ^
这个函数需要修改一下,标红的两句是新加的:
& }0 e! d8 c' _0 K  B0 \" T/ u; xvoid FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)8 k8 X1 X& x; P) z- A
{) v3 w* F: ]7 B. A5 I% r1 I
  uint32_t tmp_psize = 0U;% Q9 r+ z2 O* M" _: w
7 k# K" k( v: D- N
  /* Check the parameters */
% x9 h& E# C% p# a1 s% m8 D  assert_param(IS_FLASH_SECTOR(Sector));6 Z0 r" g+ p& ]# ^: U3 n
  assert_param(IS_VOLTAGERANGE(VoltageRange));
. s+ h8 s# A: {* I3 j3 P  FLASH_WaitForLastOperation(0xFFF);
2 [/ y0 {* o4 T  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)* Y- O( |+ p! z0 m4 ]  t; v( y) \9 `" d( _0 n
  {
; W, D$ w" F+ ?. G# E4 Q     tmp_psize = FLASH_PSIZE_BYTE;
: ?/ C: K$ Q% F  }
; O% o& w3 |+ {3 ?  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)2 C3 Z) L% N# b: z+ E# M& W) ]
  {
# T7 J/ L0 V6 ]4 k/ B    tmp_psize = FLASH_PSIZE_HALF_WORD;
  |  n, N1 @+ Q8 x$ S# ~- X  }2 S# U3 d/ _( y$ V) T' @
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)9 b- `1 v% \2 F, g0 }
  {
: ?, [# p! Y1 D" e    tmp_psize = FLASH_PSIZE_WORD;& {# ?7 s0 q, K2 L) m. K! u
  }4 O2 f1 p$ J( M, z' i
  else! f5 x! s$ j9 I6 r6 r' E
  {0 W4 f# W' _) s- T/ w9 c( S
    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
$ j8 L0 Y' f9 p: y2 L3 ]  }
0 o$ V8 k8 {' a. H4 D       
2 S/ j9 n( ]% z        FLASH_WaitForLastOperation(0xFFF);
! `# s" I, V7 L( _. l  /* If the previous operation is completed, proceed to erase the sector */
; N4 v3 x! \% e7 a3 L/ Y) J  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);% {7 d, b7 r5 Z4 {
  FLASH->CR |= tmp_psize;
3 d6 T. O! j( _) w+ g  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
6 i% {- _& O4 W7 e* C  FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);. X5 c2 d8 V7 S
  FLASH->CR |= FLASH_CR_STRT;- j8 J$ O2 S+ E. I0 m
}
6 N; Y; R" f# F- M: x# s! [, o# m- ]3 Y% G/ B

/ e7 k2 V: ^* ~) s) Y. O
& P! w% j$ D9 R! ~. r其它修改,串口修改:
. \- |! l# [  a! X: V: n7 y$ |) Yvoid SerialPutChar(uint8_t c)6 b4 u6 s: G9 H
{
0 Y9 m: u- w& q; h1 A  HAL_UART_Transmit_IT(&huart1, &c,1);
% G4 i# _. i2 A, N7 ?9 ~4 D        while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);; A" _8 ~! m, ]2 b
}
7 x& B3 N, h4 \5 `. t9 X8 L8 ]- x+ q5 r* b$ s
) i0 j; q& X; P' H& u

, z. o% J; T' a7 T3 b9 auint32_t SerialKeyPressed(uint8_t *key)& W) G3 p8 m7 K# h! `
{" D" _1 J6 o( O
        2 i! ~/ X" \. h) ^
        if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK)
$ b: d$ p2 K% \  w2 ]        {
5 T. ]0 r5 b, A6 }2 a                return 1;
2 w6 D  w2 B" Y# @        }: {: ^# i. m7 `8 G! o" ?( J
        else3 U( m- e9 N: S$ k0 J4 v1 F
        {( J4 C5 R; T* m. T1 h' c5 H; k0 X
                return 0;
8 r6 w3 u" P/ k# d3 J        }
0 D( ~+ |! G) w7 u' a6 q' H* s
  K8 U' m. F- U+ l: r6 X}
# U) x7 \2 h$ f" Z& f9 O
$ E0 J1 g6 G2 B在修改完成确认没有错误了,就需要如下操作:: m, Y6 E# S( ?) _: i
修改main函数:4 P4 s  }. a( z" o, o
int CmpStr(const char *data,const char *data1,int index1,int index2,int length);! Z* h; R0 [  {  C' a6 `5 }
+ F2 o, m) V2 ^5 K6 T, W
#ifdef  __GNUC__
0 K# B. }" ]* Q, j
8 K; a! j* T! z- U  T#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)% P3 ]9 ~2 Z! S' W
        ; I4 {  o' ^- G3 Q( X' S
#else4 h, p) N0 f. \; f* J
% ?. C$ _2 @2 U; w. `5 B- Y
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
0 W/ Y9 C- @  A1 g2 V8 o       
( i5 e. Z/ D' w0 w# l5 S2 s7 w) K* _#endif; L) G, z! n* ]

8 U0 h0 Z: [- W$ G! QPUTCHAR_PROTOTYPE) [8 I. T) g, o3 r0 v. K) U6 B
{& U$ D6 e6 I0 ]: B2 g
        HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);3 V6 l* }, O* ]2 C9 T. _8 {! p; a
        return ch;
3 K: \* [$ m% {, h; F3 F}( Z- n, M7 v- Z7 G
/* USER CODE END 0 */% e4 W& ~) N' p* {$ E; n6 a

; S& I+ Y8 n' t2 U% {. r9 x/**! W* F/ [+ T9 v8 A3 G2 b
  * @brief  The application entry point.
+ d0 `- X  d% Z' U$ F. ?  * @retval int* `0 L7 U- a; X" o* U
  */$ i' f. }! K) U0 t
int main(void)
% I5 ]- T" [' I; c2 R2 f8 w{
/ X* Z3 p- v9 M/ F  /* USER CODE BEGIN 1 */8 d. d8 ?% S! v
        //FLASH_If_Init();
( b1 j5 o) R; C/ ]  /* USER CODE END 1 */  ]6 h& j8 T$ o- ]- L  V" }# D$ |
* B. }) a0 \, ~- N1 i

$ J: w; J+ A! _+ ^1 D/ x) R% F  /* MCU Configuration--------------------------------------------------------*/9 N) h3 Y7 Z+ k

8 Q' C+ S3 K# {+ e2 x7 ?2 h% \  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */" T8 {6 W7 _0 w: x
  HAL_Init();& i/ I& l0 p6 `  w
1 o( C( B; R+ X. O( ]' O; w
  /* USER CODE BEGIN Init */" t% D' y' S# C! ~3 h3 `/ ?6 E
  uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义$ _: ?0 [& Y# U
  /* USER CODE END Init */, A1 o' D/ {( K. C" t3 k
" f5 \9 v- ?% l/ e: x
  /* Configure the system clock */
0 p9 z% g, L) |8 S) k% G1 i  SystemClock_Config();
* X* w! U5 _, H5 a/ A1 g
8 }" B5 Z) s; Y& F. }7 r: `1 F  /* USER CODE BEGIN SysInit */; m" D: M2 u/ Z8 k% v6 i
9 A2 l1 k; L" N8 t& e
  /* USER CODE END SysInit */
7 Z0 b( T3 d( H2 t3 _% H! F9 Z; _3 }. y2 R3 K
  /* Initialize all configured peripherals */1 O0 X7 N- [' k+ k' u) A
  MX_GPIO_Init();
3 }& ~8 Y) ^2 N  MX_USART1_UART_Init();) C8 t* }% p- h8 b  p$ l% z
  /* USER CODE BEGIN 2 */
! t. d7 i, M# [+ t# w5 j( ^        4 D3 p' ]+ q& n5 L/ x

# j" t( t: O2 N! Z9 k1 P/ ^  /* USER CODE END 2 */
& r# ^( O$ P1 d! c1 i2 M; n- [7 {9 x; ^! Q
  /* Infinite loop */
1 q3 l7 o4 Z$ K, w: s: T. f  /* USER CODE BEGIN WHILE */* I0 q$ N: J0 m" X$ U# \
  while (1)
4 E: Z5 n+ G! R8 F! i- ^5 Z+ P  {
% M2 y' A" v' {4 m2 e* K' t                $ U- A- l  L/ Z; c$ ^. ?
                Serial_PutString(mychar);
. X( h! s5 k- l, T- B9 {  a: @9 l* j& g! I" M
                if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)
; S3 q0 z6 V* c  u" F$ V                {
; p1 r+ L0 \$ w9 q1 |                        if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义
5 v; {+ w% p# U& W& f                        {
, i0 h* K; [5 |( D& w                                printf("正在等待数据文件下发......\r\n");
/ e6 ]0 q% E1 I3 @! L
7 P  F+ ]) I- v9 Y6 s6 x- @$ m                                - P; G2 m# M- i5 ]$ ?* q( }
                                FLASH_If_Init();
# s! @6 W% x; R0 M9 w                               
3 n& C; _# {( z  r: `( s                                //Main_Menu();4 T9 H6 F2 q' a+ v/ o
                                //FlashProtection = !FLASH_If_GetWriteProtectionStatus();
1 E7 U* p$ r5 T                                SerialDownload();6 n$ _. V, \! x. p+ k1 d
                        }                        3 M( ?# R1 X1 h4 |! `7 k
                }
" @! {5 Z$ H; Y# ?+ Q9 ]0 x) m! n* z; r8 F0 a
    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */1 Q- y, `0 ?! v% b8 \- L
    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
( N5 Y% c/ `) d8 K3 S, D    {
: \4 B( m5 ]) i8 \! J, ^- u* W                        Serial_PutString((uint8_t *)"start user Program!\r\n\n");
. u. q( R' Q0 h) f/ U                        //HAL_Delay(100);;
- C" m8 W, x3 \6 L5 o                        /* Jump to user application */+ P" z3 u6 Y, q0 c( ~9 Y  J+ `
      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
7 I  \- ~- R  r: m      Jump_To_Application = (pFunction) JumpAddress;
7 k, P4 P; ~% G( y& m7 [      /* Initialize user application's Stack Pointer */7 O( q  N' Q& |. P* u# y" n( R: ?' L% j) |" _
      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
9 H) ]# L2 q" e1 X# L                        Serial_PutString((uint8_t *)"Start program execution......\r\n\n");6 A8 m; l3 o  n6 w; M- ^6 }
                        //HAL_Delay(100);, A' w7 b+ x% S/ _, ?0 t$ V
      Jump_To_Application();
# b" P  R4 w7 E8 H( k4 p    }) i- V/ r! m4 n% x/ U
                else
) K) Z: q, ~$ a+ P6 P& t  b& o                {$ ]$ _$ M0 m4 ?  n* J9 |
                        Serial_PutString((uint8_t *)"no user Program\r\n\n");7 F; e  Z( t. j
                }
( E6 X% X) U* s+ X5 W. X( [               
/ V0 j& O$ C6 N0 t7 ^! u& A7 H    /* USER CODE END WHILE */
, j% V; z1 R/ {# a% }* R) q! I# x
" A: L5 a5 ]0 _. D  z& ?    /* USER CODE BEGIN 3 */
! g9 A( s+ X" q. e) }  }0 x9 v2 o/ y7 t; H& R
  /* USER CODE END 3 */
, W$ I7 W* k" ^9 {1 Z' l0 l8 o6 L}
  |" N8 i# m% |
. B1 C; n( ?$ K* n: y3 @0 Y7 c# T* k6 k/ W" y0 P/ b

+ o3 p7 p- m+ H int CmpStr(const char *data,const char *data1,int index1,int index2,int length)! \2 S) H: _8 {
{
2 b5 B/ v; Z( S5 P. j  X         //int temp = 0;3 y* L+ F2 J6 U. A) U
         for(int i = 0; i< length;i++)
- r3 \' @( s" A& V6 G( k         {' ]# G$ b: q7 l7 G" W0 h
                 if(*(data+index1+i)- *(data1+index2+i) >0)
% a8 g0 y) Z  b! g5 ?+ A/ V                 {, z+ _; j2 A7 P. K1 w
                         return 1;  - t5 F/ K, a9 ~& H4 z
                 }# X9 M4 u) N9 V$ v3 A# ~
                 if(*(data+index1+i)- *(data1+index2+i) <0)6 |+ o0 q# l* R' `
                 {
! M6 `) s' S: q                          return -1;
9 ^$ {9 Q" X1 I6 X& v# Q                 }
1 ]& L% _  Z$ W9 W& h. l: t& x         }9 {' d: n, x  W, f- z# b
         return 0;
8 I: v6 N+ ]: M }
7 O& ]+ f* i8 W* }
* J+ F; C3 m3 L* @& H1 |* y$ X% `' H
好了,基本就这些,有问题留言,我有时间就回复。。。2 {5 Z0 U, b, {4 ?  N
如果有好的提议,可以一起探讨一下!
" r2 h- q+ G/ T$ B

串口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 手机版