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

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

[复制链接]
qq344269956 发布时间:2020-1-19 15:47
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:
9 ?* y6 X# t5 D, Z8 c" g上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。' R) M7 q& z4 m, u7 b3 b4 I
7 k. ^% q- J1 x( _" L. u
首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。
5 D3 J) W$ a5 y9 Q7 G& x' }( g
! [; x2 T7 q# `7 C4 z2 F7 P然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动
0 m  d4 t; I# l7 W' f2 d- ^) ?2 @/ Z7 t" z* P8 z! z

0 @0 i0 X% H7 F/ [设置了时间为168MHz,然后生成了一个HAL库的代码。
( c9 H7 S7 u9 \; D* k1 g& {% ]2 T/ A! K
将STM32F4xx_AN3965_V1.0.0里面的4 w1 y/ w1 l7 a; Q3 H4 }0 B
common.c- ]5 R1 Z2 E1 G+ [. R
flash_if.c  ^/ v5 L% F; X/ E  w8 V
menu.c- l  q% Y5 A8 r5 m/ t
ymodem.c6 q* D- x. D- K. q
放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add  existiong .....)
& T, T. ?. ?4 d: |: l( u7 ~6 M: ?* e" n- O5 W) v
在头文件中添加上头文件
* i/ z( v! H9 ^; K#include "menu.h"
( y) G2 E! U8 U6 A. [) R#include "common.h"
, _0 G$ D# x" i3 D) {8 v4 A( q" K#include "string.h"
. L; m9 W' W5 I+ w$ ]0 ~/ L#include "stdio.h"
. A, n% w5 d4 e- u1 E3 A+ r+ ?; }; X8 [/ `0 [
/ n, X: G, ?- [
添加下面的这些外部定义
7 |! X1 ^0 [  U! t  Dextern pFunction Jump_To_Application;
) n2 \" [# v6 I5 E) _2 j6 Eextern uint32_t JumpAddress;0 A9 T, B/ T  T: B* U7 z( ]7 [5 O
extern uint32_t FlashProtection;( H# Q  `/ |/ o5 h1 }) T
, \( E8 u* a. d3 }, m/ K* F" u2 `) Z
$ O! p- I1 k8 f: o
编译后会出现一些错误,主要有:; y/ e8 S- y, ~  W1 I* v  @* o
FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X
, z/ @" @( P! r- G  j: b  b' ]8 t: J- D. M3 c1 O4 I
FLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:
2 P, A6 j: g: S: e- a! C/ L& \6 Vuint32_t FLASH_If_Erase(uint32_t StartSector)) \+ }- \' V$ h7 ]2 y; m
{
5 n+ m- H* e/ }1 z2 L) W3 m# T  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;/ F6 V) j0 Z9 H6 R7 T
2 f8 h& C9 n& ^1 ~! o% h% o
  /* Get the sector where start the user flash area */
' B5 V; w3 N" m! w6 Y  UserStartSector = GetSector(APPLICATION_ADDRESS);1 U9 x" f8 p# Y

8 p- t" I" g  d8 b) n, J  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)) u0 S) X! y# z, k6 G
  {+ R( v8 m8 e8 a; s% b" K# M
    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will+ P$ G- q/ P8 W4 ~
       be done by word */ , l% E% W0 B) c: E
    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);7 v# @$ T! L* _0 ], E. E
  }
% P) ]$ z/ q- F! k  T$ [1 U/ J$ u5 X% _1 ?9 G2 G* D
  return (0);0 A8 x2 K' x3 ~, |+ {  Y
}
8 n' h1 D( G% f* g/ e- f
. M# ]6 z; `" e" |( [9 Y. p8 {1 E2 K( ~4 @6 t
其它的一些基本类似,解决办法都是是到:
7 g; q3 y! N1 f1 l1 k" Q4 P( z  zstm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换
4 ]4 l2 U- }+ @+ a需要注意的是
$ p! V4 _/ G, c* j/ k有些函数:
+ `5 y5 E5 c3 l$ P" L) PFLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中
* B! {- x+ d" f# zvoid               FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);% k7 n: G  I& Z9 K5 Q  y
HAL_StatusTypeDef  FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);! S- o2 R/ h% i
HAL_StatusTypeDef  FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);. C. ^+ t/ f  d: ^
HAL_StatusTypeDef  FLASH_OB_RDP_LevelConfig(uint8_t Level);( t  X+ `+ t* l0 ^: e7 n3 M' r5 X/ a
HAL_StatusTypeDef  FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby);. V+ d: R# `4 K1 t0 o3 T8 S
HAL_StatusTypeDef  FLASH_OB_BOR_LevelConfig(uint8_t Level);: N. |1 M& j$ P' n7 X
uint8_t            FLASH_OB_GetUser(void);" B( K$ `$ |$ _4 C8 s& c. q
uint16_t           FLASH_OB_GetWRP(void);8 Q6 r* V+ j6 z2 Q. @( s7 B
uint8_t            FLASH_OB_GetRDP(void);) ^0 J# w3 D0 x. }3 I
uint8_t            FLASH_OB_GetBOR(void);
% ?0 i% A4 S( v6 a6 D1 `' p4 i8 {& e6 x% s  y) k
将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。. {! D& j* ]2 w7 O- h: {# L
还需要修改这个函数* n( w- o. Q+ o0 o  e  X# b( ?# l
uint32_t FLASH_If_Erase(uint32_t StartSector)
4 N. ~% B- H& l1 Q" |- B{) K% X9 J# U0 A
  uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;5 Z  J# j3 x0 C9 h2 O8 `
$ P' f+ Z6 c  O" V& }1 z
  /* Get the sector where start the user flash area */
: L. O3 m& i' A% ^5 q, n) x  UserStartSector = GetSector(APPLICATION_ADDRESS);
8 A  C1 {* l1 {  L( H0 R* i/ L! t# ~& ^6 s. p
  for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+10 Q, ]! v/ q' G
  {9 `3 `1 D- @$ R! I
    /* Device voltage range supposed to be [2.7V to 3.6V], the operation will( U# S9 J6 T  G6 N; |3 R
       be done by word */
& j4 ^" |! }, s& L/ a    FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);
. a2 R/ D, x3 s1 A# Q  }5 N; f. W# R# L. ?
! j8 s& _0 S+ j* h
  return (0);! [6 Y4 p" X. p1 y6 r; h
}
( e- b6 G# z7 z. S% H8 A/ M/ [# g: n( K9 s2 \9 Y! t/ b) q. Z. x
$ x0 r. E4 D& O# u) u, {

1 X: i: o$ {& {- ~+ E8 K2 k这个函数需要修改一下,标红的两句是新加的:2 w3 d4 |$ F  @3 O* ~. f
void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
- X2 j4 C  Q! ~0 ]% {" n% c{
& e; R+ T* i7 P, k  uint32_t tmp_psize = 0U;9 q! ]& r! v* ]5 N

$ @; h6 N  Q$ \% F8 ~% _  /* Check the parameters */
; z3 v8 {  c2 w  assert_param(IS_FLASH_SECTOR(Sector));( }8 a/ B- q# V$ ^( J# V$ U- s  @
  assert_param(IS_VOLTAGERANGE(VoltageRange));% ~0 l  x# U3 V% W! M' q7 x
  FLASH_WaitForLastOperation(0xFFF);
: \# j. t* A: @# X2 O+ i" c  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)
: P/ |+ m! P3 a  {
1 q$ V2 ~0 F3 S. N% \( C# H     tmp_psize = FLASH_PSIZE_BYTE;  M* O7 P8 M6 n5 J7 U
  }1 Y8 N: |# b0 \5 c% J" m  r
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)
! y* M) ?! s9 E$ U9 _- V/ g  {
) ~, h, w- @! g: S( O: S    tmp_psize = FLASH_PSIZE_HALF_WORD;" |, A! X  ~2 R* b' ~+ ]# p* H
  }
- L7 J$ P, u. C5 `9 n" v+ L* `2 i  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)
. g- t( @- q+ G  J. m; L  {
1 ?% n3 X) }, Z) m. b    tmp_psize = FLASH_PSIZE_WORD;
: w/ q- y, N5 {, U  y$ q$ Y' n1 L8 B* a  }! g) v. y- R7 t8 ~) Y
  else
' v. d1 o* h8 q7 D6 N  {
7 j/ O8 j7 X# A! F# {    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
/ d. Q, {7 M- ]' X  }# a( v+ F' Q. T
        . M- W! G( M  ^; o+ q9 j
        FLASH_WaitForLastOperation(0xFFF);: P+ R' H" Z: Q, y3 ]
  /* If the previous operation is completed, proceed to erase the sector */1 b1 }5 s3 i; f; O
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);% n* M& e4 m! w; i" U: ^; \
  FLASH->CR |= tmp_psize;- b# _- L+ t5 j* Z  X
  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);; O4 q- h) |4 ~0 F; I
  FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);, S# f6 G  A9 a& C
  FLASH->CR |= FLASH_CR_STRT;
5 B$ h5 T/ t5 T5 C* k4 K& m}6 v4 ~+ f5 c0 a4 Y2 _! d

, @8 u4 W7 P) Z+ }) r+ [
0 ]* z9 F! N" e/ |& N( ?" M& @2 A* h0 v1 b9 d& L
其它修改,串口修改:
) ^! i" v  C* Yvoid SerialPutChar(uint8_t c)
8 q9 l0 B' ~$ [* x& p& w; q3 M{: ]8 w  w- {9 l: j, k
  HAL_UART_Transmit_IT(&huart1, &c,1);
( m# v) Y4 ~8 N! s3 k6 f        while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);1 R/ P, Y& s& m8 W( T  j7 U+ J/ c
}
/ n" o* P; H, H6 ?  K/ K4 L8 N5 a8 ~$ p$ {& t  k2 v: Z

7 {9 e$ X/ J5 a4 y1 k& A3 D  m9 g: x  q5 A
uint32_t SerialKeyPressed(uint8_t *key)3 y! W) z% x( \6 W: [; C
{
, L2 W2 i% M: \        ' g& u; e$ q# n
        if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK)
9 B4 M: D, I' e" H5 H. _1 ]; G        {
5 c$ r' W" M& D' g                return 1;
7 v* p: t  ^1 d        }, q# c' `+ S  l5 _
        else! C7 b+ ~/ f" u! ?
        {
; x* b3 \! M1 S) }: A3 s" x3 l                return 0;8 A( h; U( |! L/ U! l0 ]
        }
8 G5 B6 d+ ~0 ^  ~: T3 H% n! h, \& L; U6 Q
}$ j! [* ?$ X7 r. b( Z, Y3 J
0 A+ h1 r) t5 z% q
在修改完成确认没有错误了,就需要如下操作:
6 S- \) e8 K& F) I; i  g修改main函数:
* p* O: ]' s+ T9 b( mint CmpStr(const char *data,const char *data1,int index1,int index2,int length);* O( h! `* D8 d
) ~# P+ V# ]' `) J
#ifdef  __GNUC__  q6 C8 t0 J8 X* e2 u  B: g- ^

7 A+ |" \1 w4 \% |#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)3 b& f4 i- R. K5 d$ Z$ K
       
$ W# u1 c: l8 i: g+ Z; S#else5 q' D9 Y2 v1 X# l9 o, X7 S$ d
( |* Q7 X) k* g% H0 T# P/ v4 C
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)( ~3 \" Y' {" `
       
9 f+ S$ U1 S7 m# b" {0 M3 B4 f# k. ^#endif
% p- \8 o/ F2 S/ E# O3 q9 v7 ~- @5 q' b3 g$ f+ h
PUTCHAR_PROTOTYPE
; M8 ^6 `. V" J8 t4 r{
: [, T) R. p4 I1 A' q9 B3 h! e        HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);6 I7 H, b* p& Q# g
        return ch;
8 K6 K( q' ]8 ^% g; y: t}
7 C& T$ ]4 c- o) y8 j/* USER CODE END 0 */
& |% y, |  s9 c# g8 R9 _
0 p0 l0 b. _% P9 Z/ F1 Y7 y1 r  L/**) G/ Y- p  v$ k
  * @brief  The application entry point.7 S/ \& e2 Y1 R8 z- p/ ^
  * @retval int
, b5 ?# |; U, `  */) a$ {0 I  _  o1 n6 }; d
int main(void)+ k2 e! J1 `7 N* {9 K# Z
{
. P( ~& f. N9 R9 ~- S  /* USER CODE BEGIN 1 */4 y  G4 ^6 \& |" X+ g; Y% o& `
        //FLASH_If_Init();% J4 u5 v- o- ~$ C8 p
  /* USER CODE END 1 */" z% {/ i: O6 M6 Q

; `: P' j& Y8 f
+ n; H' L$ r& f. {$ d  /* MCU Configuration--------------------------------------------------------*/$ V0 S% ]: V' K
7 X& N3 T7 C6 A" d( b
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
2 k. o! I4 r* j. |& U  HAL_Init();+ Y  b! D  u! H
: I& K6 }& m  k9 X; x9 i
  /* USER CODE BEGIN Init */
  y+ Y2 d, ~3 H+ z1 v5 c2 \6 D  uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义
4 \) p3 D" l7 g! ~  /* USER CODE END Init */# J( d- A/ Y5 U' G8 U
/ }9 S. P0 k* ]6 ^3 R5 [' Z1 K' K
  /* Configure the system clock */
2 k4 e7 s; z% `2 X0 N( l7 y  SystemClock_Config();3 n9 k$ x2 \; `/ n# p* X$ w1 x" s

- ^, V/ \5 j# x/ e( T$ Q  /* USER CODE BEGIN SysInit */: h+ ]( t2 O# P
3 Y2 m2 R9 K/ _( x5 |8 \2 R6 N
  /* USER CODE END SysInit */
+ S) v% A" ~& |
% D' l! V3 b1 \  /* Initialize all configured peripherals *// [& u' N; p! I- o
  MX_GPIO_Init();0 c$ b8 l8 W8 ?* K
  MX_USART1_UART_Init();
4 f) R& D$ n: Z/ y* s0 i  /* USER CODE BEGIN 2 */3 X" D8 R: |, `/ b" z& o+ |" s. a
        9 t, z4 w$ |* H3 l

$ p& y6 J7 x4 S& ?5 F1 X  /* USER CODE END 2 */
: |( m; I$ `( E+ }* ~2 i/ ?: y& s( {9 H5 b: M0 `
  /* Infinite loop */1 w# g8 y' C; [3 U' j
  /* USER CODE BEGIN WHILE */
5 M/ u( o( C' X1 y' V  while (1)
0 K) E3 f3 f+ Z! m4 G' _  {8 K# s$ A$ `) G: H6 t. k
               
. |) s, o. L6 j+ y) I$ G1 t( `+ W                Serial_PutString(mychar);5 ~/ L6 B& I( N8 r) i
$ X# f/ x1 q2 W! A. A' e* j2 P0 ]3 t! ^
                if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)
5 Q) Z9 I# P1 m                {6 m4 h+ l. ]$ D+ a
                        if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义
/ D! `& _% ?, d# a* F, Y% o                        {( ?! r+ y% k8 t4 H
                                printf("正在等待数据文件下发......\r\n");  n0 C) Q- H% w+ r

$ }$ S% Z8 v7 J' g; {+ z8 f' c                               
7 \7 O8 S6 ?5 O( N& j                                FLASH_If_Init();7 \+ N4 w/ M1 g8 [
                                1 K% V" [) `( u" w" r
                                //Main_Menu();
9 |4 T6 L) j4 y                                //FlashProtection = !FLASH_If_GetWriteProtectionStatus();
0 @0 F2 ]0 I: O. B                                SerialDownload();5 Z' s; E; n! E% l0 Q* Q; b* f0 [
                        }                       
5 o, Y# P/ D' [$ W# ?1 x# V4 G. \                }8 b. E+ b! ^$ X9 y/ D+ M6 }
4 D8 ^8 Y) \6 Q* [) ^
    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */4 v% C' ^, R: V) i' L$ ]3 [
    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
, G% Z! I. ]2 }( v/ z9 B    { 6 U4 Q2 R( ]9 P' t) k0 L
                        Serial_PutString((uint8_t *)"start user Program!\r\n\n");
: h- y; j; v& B$ b# O7 D                        //HAL_Delay(100);;
$ o+ L7 v$ ^. J# j0 `                        /* Jump to user application */  `$ y' X0 F) r/ q1 X6 g0 s, k8 _
      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);6 l% D- l0 Z0 Z" e
      Jump_To_Application = (pFunction) JumpAddress;
1 o$ v% s# m: n( B" e2 n      /* Initialize user application's Stack Pointer */, J0 A( k' p8 u$ f. j* _
      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
2 y8 w8 X# ^  r( W, r6 Y6 }                        Serial_PutString((uint8_t *)"Start program execution......\r\n\n");
" Y$ e2 l0 ]- I1 e4 x                        //HAL_Delay(100);
) j7 O! J* W* }; ]3 S7 t      Jump_To_Application();
- |" D0 f5 ?' O) @" K; t( v' q    }* t- G. z& I- r5 y( H
                else5 T* |2 w. o! j/ R- T# |: `
                {
" P( g2 |" [: {8 ^0 {                        Serial_PutString((uint8_t *)"no user Program\r\n\n");* e- o2 Y0 y: M3 P6 _$ j
                }
9 d! G  U" ~: _* i. \               
  ^& y8 P3 R" j/ ^    /* USER CODE END WHILE */
3 e8 B& g" }! u* K- V4 o1 `9 P% q1 Q  I
    /* USER CODE BEGIN 3 */
! v! K; m$ M& Z, ?9 a6 a+ o  }
1 D3 L' [2 T7 ]2 B  /* USER CODE END 3 */
3 ]' j+ q8 m/ F2 S8 M/ T}
1 M! k' y# k1 U; T# b/ u$ ~
% w& F1 R" \& \: _( `' k* O4 {
! T* v' ?: T2 P- l0 s) V1 L$ ]: B( c3 @) C; ~4 X
int CmpStr(const char *data,const char *data1,int index1,int index2,int length)
1 v; g! U/ z. G5 F. {& N5 K4 P {& ^: W! @- B" u; U1 B9 {
         //int temp = 0;) r" r1 b9 e: w
         for(int i = 0; i< length;i++)1 k5 Q1 T! d; `. @
         {
& _2 h$ G# C0 F6 Z5 ^: L7 F                 if(*(data+index1+i)- *(data1+index2+i) >0)* I- W" T5 W6 N; N
                 {
2 {% A. H: r$ Y1 S                         return 1;  - f6 r4 S% S/ J6 h& z$ ?
                 }
* ~) {- Q: ~1 v; H5 Q" U0 \                 if(*(data+index1+i)- *(data1+index2+i) <0). E( ^& N0 K5 B: K8 I
                 {
4 k. C* P, F. ~2 g* a                          return -1;4 Y, I$ q$ n. f, R2 X/ M( W5 _
                 }" c; O8 \9 F% D8 ]+ o. u
         }
, }- o# \1 s$ I& T* J& X' q( A2 e         return 0;, ]1 m8 _4 r: a+ d( E9 ~; x( ~9 d
}
; I9 f& r; g/ T" ]6 E# ?: o0 X8 t' Y0 ?. Q
" x8 c. z0 B5 U+ `$ U( q
好了,基本就这些,有问题留言,我有时间就回复。。。1 u7 z& O% r6 _; k) o
如果有好的提议,可以一起探讨一下!
3 a- g5 f5 M! b- r

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