|
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下: 上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。 首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。3 z8 L. J, B+ W5 ` 然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动 , h) B2 n& B5 t# R# x( I0 M/ x % P3 A# [8 J( M5 t* _, ~4 {4 V# K 设置了时间为168MHz,然后生成了一个HAL库的代码。 9 p& ?" M7 c2 K# Y/ } 将STM32F4xx_AN3965_V1.0.0里面的: z% R' e& o, P* w1 I: H( w common.c flash_if.c menu.c! p; E; u" B, i ymodem.c' r4 k) B) _2 @) b 放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add existiong .....) 在头文件中添加上头文件 #include "menu.h"+ A* b' L5 B) I/ z) B1 t9 X #include "common.h" #include "string.h" #include "stdio.h"; X. P! J W8 f O9 ]0 [2 f. S7 ~ + b& s( | b' N* ?1 B 添加下面的这些外部定义 extern pFunction Jump_To_Application;( P5 ^0 O/ T' a! W2 L+ U extern uint32_t JumpAddress;) C9 O% [' Y# c4 s& ~, ` extern uint32_t FlashProtection; 编译后会出现一些错误,主要有:! Z6 M, Q+ q- A7 P) L$ ] FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X/ S$ v8 a& T0 h8 U0 p( R3 h FLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下: uint32_t FLASH_If_Erase(uint32_t StartSector) { uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;- O) D4 k$ V' x1 O ' r, v2 x+ M3 S/ z: p6 w- {: s /* Get the sector where start the user flash area */7 N) |, \4 ^ n( i5 m. `: r UserStartSector = GetSector(APPLICATION_ADDRESS);- _& @2 l' N: e% W# C , e& A- r- S A* k for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)& C) ?- z, `. p3 t8 k {6 T/ S; M, \" d" f; r5 m: n& W /* Device voltage range supposed to be [2.7V to 3.6V], the operation will$ P8 h( g2 ~4 @1 @ be done by word */ FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3); } 0 ]2 w+ M3 F2 a2 D. D p: ]- W return (0);- q+ F: u) t. F } 9 S( {; ?: _: v" ` 其它的一些基本类似,解决办法都是是到:% M3 A" D" ~- H. J* V7 z6 I6 R2 n- F+ D stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换: _* m; H" \- ]! n 需要注意的是% a. T4 o. g0 k3 T9 | 有些函数:& }( s8 S. `8 n, M FLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中 void FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);' i0 w1 X1 \2 ^1 h( K, _- ]: H HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks); HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);. D' d! b/ P, g( d4 V5 q# o( B# n HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t Level);3 g6 M) z* f, C' z0 B m HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby); HAL_StatusTypeDef FLASH_OB_BOR_LevelConfig(uint8_t Level); uint8_t FLASH_OB_GetUser(void);8 ^6 j7 j$ L% w# a9 i uint16_t FLASH_OB_GetWRP(void);5 R% h( F# I( S* Z* ~$ {. z# I uint8_t FLASH_OB_GetRDP(void); uint8_t FLASH_OB_GetBOR(void);7 |% z- G( a: H+ M5 [7 u 0 [1 H* g8 G, A3 \+ A 将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。 还需要修改这个函数 uint32_t FLASH_If_Erase(uint32_t StartSector) C7 G, G+ U+ b- u: b/ E { uint32_t UserStartSector = FLASH_SECTOR_1, i = 0; 2 j0 _* q# w8 g% m1 Q0 C" S) N /* Get the sector where start the user flash area */# K u6 @& K" f6 P- d: v1 ` UserStartSector = GetSector(APPLICATION_ADDRESS);. O Y8 m* h( R+ g8 h- H % h; `' K- Y: v) `7 b for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1 { /* Device voltage range supposed to be [2.7V to 3.6V], the operation will be done by word */ FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3); } ( F0 J! o2 {; n8 i return (0); }( y# m' c' H* S5 [" j ) l1 V- F% y. ~3 r3 ]* ^1 t) Z ) q; P8 T$ O2 ?* @) }8 \8 i8 d 这个函数需要修改一下,标红的两句是新加的: void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange) S/ M' T a: r0 b- n& R" i {, c- T3 B8 G" f+ k2 @ uint32_t tmp_psize = 0U; /* Check the parameters */ assert_param(IS_FLASH_SECTOR(Sector));- _% j4 z5 X; D& v$ l assert_param(IS_VOLTAGERANGE(VoltageRange)); FLASH_WaitForLastOperation(0xFFF); if(VoltageRange == FLASH_VOLTAGE_RANGE_1)0 V/ g6 \, _0 D5 ^0 f" a$ v- v {6 S4 z/ c. E' U tmp_psize = FLASH_PSIZE_BYTE;6 ]) n3 P1 t7 E } else if(VoltageRange == FLASH_VOLTAGE_RANGE_2) { tmp_psize = FLASH_PSIZE_HALF_WORD; }. P$ A) a4 c/ G3 q) N* O- f# H else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)% f( _( C4 F/ m* M" q- Z8 ^3 |2 t, T! H {( c6 d/ ^4 \9 U3 x9 t4 t tmp_psize = FLASH_PSIZE_WORD; } else {5 K% f0 x& T4 T4 h- r% W0 z tmp_psize = FLASH_PSIZE_DOUBLE_WORD;# g# q- J6 Q0 j& W }: F: }' C- f8 F3 w" k7 c FLASH_WaitForLastOperation(0xFFF); /* If the previous operation is completed, proceed to erase the sector */" ]3 m5 a, s, R CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);) G- b2 ~+ A. M. r1 l1 Y7 L FLASH->CR |= tmp_psize; CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);" s! x& |2 z- _1 |( z FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos); FLASH->CR |= FLASH_CR_STRT;( n7 u" @, a+ E. R4 O% ~( _ } C# y* a; L6 V' j# N 3 x0 U& m; J, r6 ?0 B 其它修改,串口修改: void SerialPutChar(uint8_t c) {# I7 y) N; o+ F( K HAL_UART_Transmit_IT(&huart1, &c,1);& z& q; [, l' Q. U5 d' K while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET); } 7 ^( F( `$ \! J$ f$ N uint32_t SerialKeyPressed(uint8_t *key): c9 |9 l0 n/ B3 V6 P- F { if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK) v5 z# P3 e. C/ U. p! w { return 1; }$ t D1 m) r# ~ else" P: `- q7 H1 L- N% e0 } { return 0; }& X8 N0 w4 k, X! \) l } 3 a. b* U2 w5 ]' I 在修改完成确认没有错误了,就需要如下操作: 修改main函数:" n" ]" c8 Z: H. S3 p6 o! i int CmpStr(const char *data,const char *data1,int index1,int index2,int length);+ z6 }- J, ]& E) H #ifdef __GNUC__; y" e V# h7 I( U% g3 u. P / |' _$ O8 g; y5 L- X$ A2 V1 o6 H #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) 5 d4 n+ `/ E" I #else8 c6 B5 Y* s; h" j% d ' L a: h* w* W, W) f }9 J& i #define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f) #endif0 I0 }5 l. r5 l$ @: Y; h PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);* f# x* t4 M8 o return ch;% z* r# W8 ?3 j. m( [3 l) b% E9 n } /* USER CODE END 0 */ * y) o( p2 w6 N* z* K9 g2 S# j+ U* `% j /** * @brief The application entry point. * @retval int7 ^7 l, A! A3 ^$ W6 ?8 Y */0 l. t( ^2 G$ K* t9 w" C, S) I int main(void) w6 r% R1 k5 G2 M! P6 N+ D; y {9 T- D$ [& P% _) B /* USER CODE BEGIN 1 */( X! G4 U2 w# b; S" R //FLASH_If_Init();, j, k# ^6 s( ^( T; G6 _/ z /* USER CODE END 1 */9 Y2 p' a) e) l9 d5 X 7 g9 m7 ?/ X* s, T0 G2 S# h ; F; L; f( P- @. Z, S1 [ /* MCU Configuration--------------------------------------------------------*/4 M9 t3 I. [5 ?5 F /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init();2 X6 T# v \ K# u /* USER CODE BEGIN Init */ uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义 /* USER CODE END Init */) o; w& t5 B: G% \2 c d /* Configure the system clock */ SystemClock_Config(); r5 G( u0 q5 O/ m) {0 ]7 y4 T 6 G3 J- g$ u6 K7 } /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */9 l5 B7 P; M u$ o7 V2 D& F9 ]" Y MX_GPIO_Init();, a9 Q+ P; V1 N' J+ f MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */3 F( n5 T: Q/ V /* USER CODE END 2 */, _% @* K7 G/ ?& @% x+ U /* Infinite loop */ /* USER CODE BEGIN WHILE */5 L5 ~' T: ]. ? d+ w/ ] while (1)7 J& b1 K8 w7 u8 d' n { & C. S' e) q% z) i3 V Serial_PutString(mychar);1 r% X5 n! V/ L if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK) { if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义 { W8 M' T8 ]0 R) f; A printf("正在等待数据文件下发......\r\n"); # K$ ?- b5 P$ U9 _, t9 C FLASH_If_Init(); 1 i6 Z# C+ i3 v9 ^ //Main_Menu(); //FlashProtection = !FLASH_If_GetWriteProtectionStatus(); SerialDownload(); } } /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */ if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000) { Serial_PutString((uint8_t *)"start user Program!\r\n\n");4 }0 n+ B/ R" t* D1 y2 j //HAL_Delay(100);;6 A( ^& }; k- q8 E7 ^; V1 ^ /* Jump to user application */+ Z! l8 f$ w7 g: Z6 L* h% n JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);) d: h% C- u8 }, ~3 z T1 r% e Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); Serial_PutString((uint8_t *)"Start program execution......\r\n\n");% I; k; E# f" S8 w //HAL_Delay(100); Jump_To_Application(); } else {0 _, S: N; p: O8 i6 Y* h Serial_PutString((uint8_t *)"no user Program\r\n\n");! |( t: [& q! r/ Y* a& { } /* USER CODE END WHILE */& F6 L9 V ]0 u- g - ?) r* X. G$ m /* USER CODE BEGIN 3 */ }& o* e# B w# f# b /* USER CODE END 3 */ F/ P; K$ a- P+ T5 v }/ \5 K8 j. o- k 5 T6 \( g3 l/ m int CmpStr(const char *data,const char *data1,int index1,int index2,int length)$ W4 b, q* t+ X. A3 E9 O {$ N* x. n( M+ T //int temp = 0; for(int i = 0; i< length;i++)' Y" S# Z7 l2 n* G* n { if(*(data+index1+i)- *(data1+index2+i) >0) M# l8 B y3 Y& d { return 1; ( E+ y: h2 N- n: f } if(*(data+index1+i)- *(data1+index2+i) <0)9 Z/ @" Z# B. {# T6 E { return -1; }' H- B9 \6 g' m" c } return 0; }& N+ K$ k6 C1 Y: F6 i+ q ' I2 t, M4 g8 c8 g* k! S. x& }! C 好了,基本就这些,有问题留言,我有时间就回复。。。) X4 G$ V. P& }3 s( @+ k 如果有好的提议,可以一起探讨一下! |
謝謝分享 |
| 感恩分享 |
| 谢谢 分享 |
| 我用的CUBEMX里的例程,自己用CUBEMX建立工程将文件添加进去后,通过Ymodem下载程序,可以正常跑但执行到HAL_Delay()就卡死了,版主有遇到同样的情况吗 |
【福利三:雨露均沾·逢7狂欢】之四:用一个定时器同步另外两个定时器输出PWM
【逢7发帖赢大礼】STM32开发之WIFI实时时钟
【逢7发帖赢大礼】STM32开发之指纹识别!
【逢7发帖赢大礼】STM32开发之环境空气质量监测
【逢7发帖赢大礼】STM32开发之人体实时运动信息监测!
【逢7发帖赢大礼】STM32开发之IC门禁卡UID读取方法!
【逢7发帖赢大礼】全网最简单的Arduino_STM32开发环境搭建教程!
STM32F4中文用户手册
STM32F400、STM32F402 Cortex-M4超值单片机
SPI 高温读错最后一位?STM32F42xx 官方根治方案
微信公众号
手机版