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

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

[复制链接]
qq344269956 发布时间:2020-1-19 15:47
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:/ o; ^  R- I# @4 O
上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。
$ W; q$ ~7 C8 d) s" C/ V) J& m* O2 x0 \5 g- D
首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。
6 Q  X' [5 l8 D& y0 I. L6 u& C3 Z: _# s2 m
然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动, ]  ^, R' a3 G3 i
3 Q, `  i" l- @0 j& b
/ Z; |+ J9 \) d  F! p4 z& O
设置了时间为168MHz,然后生成了一个HAL库的代码。+ W, G1 B4 }1 Q0 O1 J
/ N. t" E- P* L3 M! I# M
将STM32F4xx_AN3965_V1.0.0里面的* Z5 A, i2 H. n
common.c
$ r$ w" |8 U7 v/ z9 E( V: P$ eflash_if.c+ O3 z7 h0 G& d/ F8 D
menu.c/ M2 T& {- ~! C. d" s5 d8 q7 `5 ^
ymodem.c, s( N8 f' {) ]' F+ J1 Y9 r
放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add  existiong .....)
6 s2 Q0 ]# e2 F( `
  o" X- e  T! L, ?$ j2 e; m在头文件中添加上头文件$ w0 E: ~# I8 ^" Q& q. }+ R
#include "menu.h"# f  {) S% H2 ?. u9 N
#include "common.h"! p' D5 ?9 L6 `; t
#include "string.h"# O4 D" `" j" y" o+ h# q# n
#include "stdio.h"- w' U- q/ d) Q; q. F

3 A& T6 _) E1 B( O; e
" m; k1 g8 _: J" x& l; A添加下面的这些外部定义
* h1 ?, a1 V& a. g. p0 j1 f; lextern pFunction Jump_To_Application;) _4 R4 ]5 @4 F3 r! F  g
extern uint32_t JumpAddress;
/ P" d" ]2 W/ N1 H/ i6 \4 Xextern uint32_t FlashProtection;: l0 _4 w# D! X2 c$ W( m
% P% |! v9 q( [3 _: a5 q

& S, {* ^5 F: f7 c3 W编译后会出现一些错误,主要有:
2 p" \5 L! `4 w1 e. {1 ~2 EFLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X
* q0 S6 ]% j# x+ w$ q! t9 A. ~& c: Z' R, t
FLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:9 M0 L1 j9 M7 Q/ n
uint32_t FLASH_If_Erase(uint32_t StartSector); J/ [6 C( S: F! i! O- C
{
. P( O! ]) D$ H( p1 i. j  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;
" H+ x) Y5 x, `' o6 M( \: C$ V
. [4 p* }& n) G; K/ H% c  /* Get the sector where start the user flash area */
2 a' o+ F0 L  V) a  UserStartSector = GetSector(APPLICATION_ADDRESS);9 E. y! m) }- B1 y$ W

5 @$ M% U. Z9 S2 V- }" R  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)- n4 X+ H: c3 G7 [. X
  {4 W5 J* H* v/ B4 N; t, J
    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
# ~  q4 F% S; A3 d4 g. f       be done by word */
" D) Q# o, g+ W& ^    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);
9 i; U7 E9 ?0 X3 a9 M0 J$ |( W  }& ~9 m) t. V0 t% U2 ^+ Y
1 S7 l$ g) D0 f! i' z) e+ M
  return (0);
4 t6 F! F5 _+ V/ m( W}0 v! d/ N5 _7 L& c, Y
. O9 F! Y( m; H, y

- ?) Q- @, D) v/ N0 o+ b. A; D其它的一些基本类似,解决办法都是是到:1 F4 R2 l5 R8 v) u  z
stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换
0 E9 |7 Z* ^+ x7 u! t需要注意的是
9 R, E- i7 F9 w& a有些函数:& s; k6 ]4 h' ]- c1 L# C: x0 Q
FLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中* o" G6 j+ x" q9 M
void               FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);
% S1 Q: [6 ^3 S4 A) THAL_StatusTypeDef  FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);% R& J- g8 [, [/ L! |. [) U
HAL_StatusTypeDef  FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);
7 s1 C" ^9 q0 v. x& PHAL_StatusTypeDef  FLASH_OB_RDP_LevelConfig(uint8_t Level);
: n4 q; {. w# a% R; X6 y  AHAL_StatusTypeDef  FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby);
+ a1 b) i( [2 b7 G5 a. F) J* JHAL_StatusTypeDef  FLASH_OB_BOR_LevelConfig(uint8_t Level);- m% T9 _; a7 \  }
uint8_t            FLASH_OB_GetUser(void);0 q7 b& w! L+ o/ L! O4 V
uint16_t           FLASH_OB_GetWRP(void);% U* O9 c1 i$ x* `% g
uint8_t            FLASH_OB_GetRDP(void);
! L$ |. G4 j3 _; [6 s7 g9 Uuint8_t            FLASH_OB_GetBOR(void);
& k- b' o4 b8 _2 I& ?% T& T! W) J6 K; J, _( [$ m
将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。
- c* \8 S  N, \7 f' R4 f* f还需要修改这个函数
, S8 \$ W3 c* Z9 Q2 ]; ?# Auint32_t FLASH_If_Erase(uint32_t StartSector)6 `; t+ F/ }! W7 B8 y
{! P$ z  Z; g8 T" T1 E& f6 t3 v, w
  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;
8 T" Z5 R! p  c* i; l
! x( S5 H) N# ~3 e. a  /* Get the sector where start the user flash area */
, \1 Z7 i9 H- W; |, N9 b; H  UserStartSector = GetSector(APPLICATION_ADDRESS);
: R1 B% q! I# F" @" `& g
1 k6 y/ M6 {- v0 c/ Q: ?0 h, k# c  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1
" Z; a# y6 z5 }' R  {- }9 X: O) C4 e; E% T
    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will1 l9 i( n2 \! Q& s. T
       be done by word */ 8 z4 @) P- U8 o. E8 \
    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);
+ \9 K; {  [) z6 q6 x4 n  }# c  e/ @1 \: y% k' U2 |) m

9 N* J6 u1 P2 w  H% v+ i! U  return (0);9 L, V% H& [/ z% [4 V
}, y3 x, r! R% Z: x

, N& [- N3 v* p. Z1 V, H3 A" C
( i( ]2 K" n  P# |/ i4 T3 S$ _5 C; X/ e
这个函数需要修改一下,标红的两句是新加的:
2 f! i1 B9 g& T/ d, {4 w3 Pvoid FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)5 N# v# S( ^7 [! w2 j& F6 l/ W
{
  `! s8 L6 Y8 R8 W( g. t: p  uint32_t tmp_psize = 0U;" C- i& c$ t3 v  A" ~5 O1 _& v

: @# v! E; V! C6 a, G+ D3 y" c  /* Check the parameters */& ]9 C4 k! Z# m6 r' Z8 ?! |
  assert_param(IS_FLASH_SECTOR(Sector));
1 ~. f2 N/ }- P3 @  assert_param(IS_VOLTAGERANGE(VoltageRange));
/ @: ?, t1 P9 r4 p/ A! j5 s  FLASH_WaitForLastOperation(0xFFF);" `$ `. h8 q2 L5 n4 k2 Z0 f
  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)! u* Z6 c! \/ q: a" h) I) j) P
  {# R/ |/ u. H4 e
     tmp_psize = FLASH_PSIZE_BYTE;
! R. L) r5 q' E7 Y% L  }
) j; c: W8 |; Q, f) W7 j  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)+ T: j! C7 {* V' }" c) N" J
  {2 q* D, K& f9 Z. U
    tmp_psize = FLASH_PSIZE_HALF_WORD;$ Y8 B+ l+ K$ I$ q3 n
  }( [* c* N/ \$ f  ?9 k4 n
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)- z, K$ X, r' D. D) g
  {
, p* M5 i3 p7 n    tmp_psize = FLASH_PSIZE_WORD;4 [5 i" O' x* r4 ~) R! G" P4 Z
  }" K" |5 P- v4 P4 J% X) D2 j
  else
- h# K6 i- u1 S  {
0 a; k; }9 b8 ~- O4 I    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;9 N7 w3 A* d0 B. F: p2 Y/ a" e
  }* `$ u& z; f, _4 I7 W" k" T2 a
       
' P4 |9 [2 [, v        FLASH_WaitForLastOperation(0xFFF);
7 P' s5 P& j* E. C% v  /* If the previous operation is completed, proceed to erase the sector */' B7 ]; m  H! H) c4 X6 \3 B
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
( Y0 E* {1 A1 j* Q  FLASH->CR |= tmp_psize;
8 p4 q" @0 P6 I; c8 K6 f* O" W" {  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
; k1 f$ k( s2 d7 U7 c  FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);
0 X8 f; U7 a% }) i, @( h( y& F  FLASH->CR |= FLASH_CR_STRT;
0 p1 T0 B' X/ o  K: y}) u& S/ L3 i6 H$ d# n4 t" C6 s

" I- _; I* d  O* n5 P7 d1 X& a$ K6 |/ g' h! P& G

9 p* P6 b5 G& z8 {其它修改,串口修改:# `: E$ J4 c# ]* @+ c$ {- e" F7 U& r
void SerialPutChar(uint8_t c)9 O5 R) B* d5 W0 I* C# z9 B" O
{
9 b6 x$ a3 r6 ^, H  HAL_UART_Transmit_IT(&huart1, &c,1);
$ s0 j- K0 w2 G6 H( K5 V! ^. F        while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);: I* C  W8 @, `4 P/ t
}
. U; T- c$ O4 ~& G
' }+ C5 A5 M1 V/ U" F5 N9 |" ~3 W

2 e3 v& w; p* k0 s" n9 |5 muint32_t SerialKeyPressed(uint8_t *key)
2 v2 P, ~4 m# \' o/ R{7 P" C. Q$ o/ K( M) T1 |0 }$ a8 T' n
       
* R6 R  `5 r; {; o        if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK)$ ~$ a" l1 C7 w9 a! E# N
        {3 c: a) z. J2 C
                return 1;' _# T# M+ g* G: g) s$ Z* }0 R
        }
" o" P, o3 Z- d0 I& d/ f- {- Y1 H        else  f3 C3 Q) n; i/ v, N9 F. v
        {( ~' j+ A: F6 d( X3 L7 o6 D
                return 0;
2 ~) Y' {9 v: u% e) R        }
' e# |6 \! B. \) ~. d
1 l+ h0 I7 d. q! p- W' C7 o" O2 g: y}, ?+ D- g4 I% p& i: N, S$ M6 a8 L

; S/ |. W+ a; c在修改完成确认没有错误了,就需要如下操作:
! e8 I; Y8 `" w% X. c/ U修改main函数:
( B% w% C. }- o: qint CmpStr(const char *data,const char *data1,int index1,int index2,int length);
* w$ J8 {5 X" G. d$ B) G! J4 d, K% Z( _5 W
#ifdef  __GNUC__7 F  w, I" i1 l3 P& M8 P; G

. x) j  j, O2 `' e+ B2 C; |- T. Z#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)4 ]7 g& Y$ o+ e' t1 r- M+ @9 O1 \
       
: j* x0 e( S; {# A#else
2 g! y; f& E$ S$ @* }
9 I; _+ f1 P& U. z#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
' q! ]. o6 A4 p4 `9 s, _' m" w% j        & u" I' }  F  h2 h5 P" _$ f
#endif/ Y( i8 N0 Z! |

9 M! s0 l  x; `- k# ^PUTCHAR_PROTOTYPE6 Y" ^, C" j) X2 T: R% R
{" E8 }" T6 r6 U9 _0 F6 {7 b
        HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);7 F+ H! T5 Z* n. j
        return ch;
  E  S  S) g0 l* G/ e5 ]}2 J) a( D3 N# r. e+ w/ x
/* USER CODE END 0 */
% U" i5 _+ w7 E6 T: y+ M" [% D
  L+ ]# E9 b+ q: \% C2 w( F/**# Q9 b  W: z. A* t7 ]* w
  * @brief  The application entry point.% L% z' Z% i" C0 Y3 Y. Y
  * @retval int
! a; y& j, G# f1 U) m# X  */4 F  V  c& w* w" e6 e* O. h, e/ J: `: o
int main(void)7 P# B. t1 d; e3 o* q8 W8 i
{& \8 `4 }' V2 y' E5 x. T6 }
  /* USER CODE BEGIN 1 */
+ _0 V; ]8 r# Y! z9 j        //FLASH_If_Init();" A, |8 n9 H" K
  /* USER CODE END 1 */
2 M; {' @, q! {, |) f0 x
: ~0 U7 f& r6 q/ L9 e& l' f- u+ @
  /* MCU Configuration--------------------------------------------------------*/- p/ m7 b) L3 J0 @  T1 B# K
2 O* g) t0 w% Z/ Q3 N. k. D
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
8 F$ [7 m4 T0 Q+ d$ g% V+ C1 {  HAL_Init();
9 O% h5 T2 ^8 j/ e" P1 J
) z' N2 R. F0 k1 U# s  /* USER CODE BEGIN Init */
6 r$ q1 ?! U9 A6 W) ~, D: I  uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义( U' \5 k# t7 K6 A+ A( g! G9 k
  /* USER CODE END Init */2 g8 \( Q. {3 r; q
' J4 N" O. ~* C6 }
  /* Configure the system clock */( N) w: _' U! H5 ~1 ^! {- ~4 K" @
  SystemClock_Config();
# s" q6 s4 J4 \6 E2 t
) J4 k) o  D2 V3 @% j% Y  K0 ~  /* USER CODE BEGIN SysInit */' v8 P" A6 V% D; X7 g* H% y
" m" B/ j" \3 A. ?+ A" a" w; Q
  /* USER CODE END SysInit */
9 P+ A, t5 r7 m. U$ K. G1 _0 ]
  ^3 B& R6 R" E- X* n. P  /* Initialize all configured peripherals */0 O, L9 N7 }- |) ?4 ]. B
  MX_GPIO_Init();5 T; h6 E$ M6 h+ r  W5 T
  MX_USART1_UART_Init();
; t% F# a$ y- b3 }) |+ O2 I  /* USER CODE BEGIN 2 */
- ^1 R( \# l* a* U6 L; s       
5 u0 i& n$ X& ]
9 W6 e: \6 Z: C) r3 ?  /* USER CODE END 2 */5 S# W5 e6 s: R
4 W" [# f, B& G3 x# ?# d
  /* Infinite loop */
; w3 N: c6 i+ w7 [- P0 m% k+ o) d  /* USER CODE BEGIN WHILE */2 B; J% G1 v- p' e0 L
  while (1)9 V0 p% T5 I* A# A5 D, Q2 Q
  {
& ^! y+ L  l. L" r% j* I, L  z2 b                8 M2 X- {* [% e' K* q2 D0 }0 P6 P/ L
                Serial_PutString(mychar);
& r9 l( q; A7 f! v4 R' U
  k8 Y  Y% i' J9 X! J0 D2 j                if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)0 A$ N3 O) O  j. ?: H& ]' O
                {
- i1 ?) n% B# w  ]                        if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义$ G" L# W" G# Q! \% ]' I
                        {
5 \7 }  `" ?0 Z6 D) w' h9 C& E                                printf("正在等待数据文件下发......\r\n");! C6 a$ \, F, n# U" ]+ V# m

) `( L  y; [$ \2 p$ ~                                6 @: W- {1 S6 g+ n, M2 K
                                FLASH_If_Init();9 [; J$ L& e* Z) N$ i" y
                               
. C- G8 U2 e5 b0 Y1 _( [- A; C$ {                                //Main_Menu();
! N# O7 _( K" N/ j% ~                                //FlashProtection = !FLASH_If_GetWriteProtectionStatus();7 u6 _4 O) R) Y/ d
                                SerialDownload();" B/ B  m' m2 j) t
                        }                          G8 U+ ]. U' ~$ b/ X2 G
                }8 ?9 c, p6 Y& i

5 ^* g1 ^$ H3 w    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
) T' T9 |6 l1 H    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
5 }, G/ t0 z9 E3 c- l! v" q5 H  N' }    { " p# L  Z$ t, @4 \$ D
                        Serial_PutString((uint8_t *)"start user Program!\r\n\n");0 \9 i' F+ x# a: h
                        //HAL_Delay(100);;
+ @. t, D: U: R/ a# S& e: O                        /* Jump to user application */
) ?' ^9 U0 C$ z, d4 k      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);+ \4 P( [7 r4 b6 @: [4 _
      Jump_To_Application = (pFunction) JumpAddress;; Z, N, `# w: A! _3 |  l
      /* Initialize user application's Stack Pointer */
$ f' ~8 @) u0 |# w* r( Y      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
9 Q0 _9 c4 z% }                        Serial_PutString((uint8_t *)"Start program execution......\r\n\n");
' X0 F' ^4 K1 \* }  d5 p9 l5 K9 r                        //HAL_Delay(100);
3 U9 U0 `$ z9 f      Jump_To_Application();
  q. G2 B. r! c+ H# K5 i    }
9 G" Z: C. C5 z3 j                else0 V; s: d0 }: m7 B. c
                {
+ ]$ C( W; T$ T+ p  j                        Serial_PutString((uint8_t *)"no user Program\r\n\n");; k% V  u  f  b  i  w
                }+ V7 f) |. T! r- |* w& E  g
               
7 m( m, d& J2 v& f& v0 U! l    /* USER CODE END WHILE */' Y/ ?6 U5 p4 [. f- B

3 l5 g9 b% {* N7 G5 b  I( M1 B    /* USER CODE BEGIN 3 */# e. m* a+ a+ D0 p
  }5 k0 |& I  l- |, E( w5 J& i
  /* USER CODE END 3 */
; P( `$ S. m- q1 w- H}
* v, o! F5 y8 h+ W: l3 t3 U$ O- u7 w& o3 S
' U+ H6 N7 d1 h
7 Y) \3 S6 O4 v) i
int CmpStr(const char *data,const char *data1,int index1,int index2,int length)0 z  K5 |* x* X7 i' D1 U$ D* n
{
5 l6 H0 j6 o: Y9 a( y         //int temp = 0;
- x/ Y% s7 ^' e& E' |         for(int i = 0; i< length;i++)+ |; Y6 a4 K8 t2 G. |  o8 H; O5 h1 g
         {
% e- Q( @7 ^, k6 W                 if(*(data+index1+i)- *(data1+index2+i) >0)/ C8 y, p/ K& D  F; D
                 {
& S1 P4 ?$ }0 k/ b                         return 1;  5 L8 ]/ O6 u" P5 C: n; g3 P
                 }
+ X) e0 P9 L% _5 G% p! d4 c                 if(*(data+index1+i)- *(data1+index2+i) <0)
8 e* g6 t0 X2 u8 u; i* ?                 {, h) w" T$ ^& ^& F' G- A
                          return -1;% U, N) o: W0 \6 Y0 S1 H7 d
                 }9 X" v+ K1 I* Y/ x
         }4 J4 i, U# [* `! A
         return 0;
$ W2 E# ^+ Z1 l1 |( ]; _ }
: l+ ?+ |/ c' F, Y, h) z, s
# b' o2 d% _% Z' t* X
( d( ?$ Z; o* e' n$ X2 l$ s好了,基本就这些,有问题留言,我有时间就回复。。。
: Z! `  i& V$ a5 c9 H  n$ G& m如果有好的提议,可以一起探讨一下!
6 |% P4 `/ N8 O6 U2 T- `

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