这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下: 上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。4 [& B4 _+ s5 ~+ A+ V9 |! c . H+ l, l* b" w* v9 ~1 y1 | 首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。2 F0 h, r2 ^/ c5 D: q + E$ g; c( G/ l \ 然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动 & \7 c$ P: H: T2 L' y: U, ~ 2 C, {; q4 R* F 设置了时间为168MHz,然后生成了一个HAL库的代码。 将STM32F4xx_AN3965_V1.0.0里面的 common.c) z# B0 X" D$ n9 {# s flash_if.c menu.c ymodem.c 放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add existiong .....)5 S# H+ G7 e. S D0 \ 在头文件中添加上头文件 #include "menu.h" #include "common.h"; b1 r/ a2 C( C* x) S #include "string.h" #include "stdio.h" : c' X4 a1 g& c R 添加下面的这些外部定义3 E7 F# ]* K, \) y" K extern pFunction Jump_To_Application; extern uint32_t JumpAddress;5 ^9 h3 o" S# S9 C/ v/ N9 A extern uint32_t FlashProtection; 编译后会出现一些错误,主要有: FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X- Q9 {+ M$ U% }& C' K* `# F7 ]% Z ; v% H4 M( }" r. o! g) @ FLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:9 S. S2 h4 U3 x& ~. ^( G2 r, m uint32_t FLASH_If_Erase(uint32_t StartSector) { uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;' c2 i. x% E: n, _6 n x /* Get the sector where start the user flash area */ UserStartSector = GetSector(APPLICATION_ADDRESS);* |" \9 L# t1 ^5 t. C& ` for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1) {9 d( z( N1 f7 ~8 M3 \ /* 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);/ `& \$ {* t' f8 \ }3 d2 Q/ F) B8 e 8 T9 U. M6 z8 x/ c' z return (0);7 r% s% C: e( J& j- m* ^ }- w0 g" l2 K) w/ m1 v; l $ l% \5 Q0 C. U7 f$ I- Z o: e3 |9 j 其它的一些基本类似,解决办法都是是到: stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换 需要注意的是 有些函数: FLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中& s0 v; I. \1 z void FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks); HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);7 Z% l& _4 V; _+ ] HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks); HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t Level); HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby);. s% E1 T; T$ V4 }4 ]+ } HAL_StatusTypeDef FLASH_OB_BOR_LevelConfig(uint8_t Level);1 Y) F0 K$ y; J8 t uint8_t FLASH_OB_GetUser(void); uint16_t FLASH_OB_GetWRP(void);$ b$ } P0 P( G uint8_t FLASH_OB_GetRDP(void);+ C) c2 E. D$ P, l6 }1 V uint8_t FLASH_OB_GetBOR(void);* b) p& U# @( W/ D7 @ 将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。0 j0 s) i8 n4 D" O% _ 还需要修改这个函数1 J! ?% i/ Y. t! h8 e uint32_t FLASH_If_Erase(uint32_t StartSector) { uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;8 R% ^& N& k/ d; Y& Q! G /* Get the sector where start the user flash area *// m# F8 b" P f8 x UserStartSector = GetSector(APPLICATION_ADDRESS);6 s# H3 q# H" s: B( |5 W6 b/ q( S% g a , h5 [/ L( ]5 A- U for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1# d, X% G' ]! v2 d3 O5 s4 x {- Y/ a! N( ^0 k /* Device voltage range supposed to be [2.7V to 3.6V], the operation will+ s* X5 _' I+ M7 a3 C2 R ^9 m+ n9 a be done by word */ FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3); }; n" s1 `! F% T, e$ m return (0); } ' z: C0 h/ [: J: N* R; l" h. ]9 Q 9 x6 E' j5 ~1 ^' k6 A 这个函数需要修改一下,标红的两句是新加的: void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)# [' E5 d; ]: q4 V* t {$ x' [& I6 Y( C! H8 T" o, x uint32_t tmp_psize = 0U;& I7 _7 i+ p; V L% _0 @) d+ R # d2 R% J3 I4 D. Q /* Check the parameters */( C! _+ f( }9 w6 O assert_param(IS_FLASH_SECTOR(Sector)); assert_param(IS_VOLTAGERANGE(VoltageRange)); FLASH_WaitForLastOperation(0xFFF); if(VoltageRange == FLASH_VOLTAGE_RANGE_1)9 B! O$ {0 d' x" { { tmp_psize = FLASH_PSIZE_BYTE; Y8 h0 C3 z: T8 w( W+ ~8 S6 Y% m } else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)4 i4 |- n& ]& j) q { tmp_psize = FLASH_PSIZE_HALF_WORD; }( e+ n- N' z2 _/ ^7 G else if(VoltageRange == FLASH_VOLTAGE_RANGE_3) {, Z/ |1 M5 I3 u tmp_psize = FLASH_PSIZE_WORD;- |0 [# x* Z4 ?9 D }* D5 J, `4 V2 W2 U. ~0 `) P else$ v" ~- F' e0 I {; B/ I3 x$ p, F8 {: F+ E tmp_psize = FLASH_PSIZE_DOUBLE_WORD;" \3 |) v9 ^" u7 M0 P }) g ~0 t) T, v/ C 4 Y6 D' S3 h1 G0 O% C' T FLASH_WaitForLastOperation(0xFFF); /* If the previous operation is completed, proceed to erase the sector */- ~9 F1 I2 P) [ L+ F CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);- P6 S+ b" O4 k& x& [: R FLASH->CR |= tmp_psize;$ s7 h; u& [4 k9 H! u% r CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);& S' }4 `" v: {) s* Y( g' h FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);( C" w+ a8 O; n3 x+ c8 c( a, ` FLASH->CR |= FLASH_CR_STRT;0 K0 r5 x. Q. `5 y } : c- C$ U+ A- `$ e9 A) ^ 其它修改,串口修改:$ q; L' Q) m' t4 \/ t void SerialPutChar(uint8_t c) { HAL_UART_Transmit_IT(&huart1, &c,1); while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);1 s4 P6 X* I* b }' R1 w o% \ ~- I 7 O5 r! R7 x' i- U( a$ i % H/ a X' h. P e1 y+ V( i uint32_t SerialKeyPressed(uint8_t *key) { if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK) {- Z h% `! C: }) P: }7 W return 1; } else { return 0; x* U8 ], d1 l+ j } 9 n, D( P8 F5 F( a } . B: s; p- _' ?4 P: B7 F 在修改完成确认没有错误了,就需要如下操作:9 B7 }5 i6 K/ a, r9 \& I( J" _ 修改main函数: int CmpStr(const char *data,const char *data1,int index1,int index2,int length);6 |) e0 T9 u& z2 ^ e #ifdef __GNUC__3 Y# g- I' A6 A% S# B2 c( } #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else' a! Q* [. [8 @: S/ g( f " c# A6 e' Z1 Z" w# o/ c- ^/ C #define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)/ l5 F- R, H2 W4 I, Q; F #endif4 B/ F$ S4 N" \; v2 N 7 q7 _* s c( @+ F: D) ~& `! Q PUTCHAR_PROTOTYPE9 P' U8 ^' i) w* J {, b" B" p T9 l# i' f0 S8 `" @ HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF); return ch; }7 |' y) [, v( {# {+ `6 p /* USER CODE END 0 */ /**; S3 i f; h' {) {4 i! J * @brief The application entry point. * @retval int */6 S1 O& s" F$ U8 L0 q int main(void) { /* USER CODE BEGIN 1 */ //FLASH_If_Init(); /* USER CODE END 1 */ * y* f: @9 v/ X# x' } /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */! b8 K- m" F0 Y$ Q0 t, \+ b HAL_Init();; i. e, c z. e* j/ X" m9 x /* USER CODE BEGIN Init */ uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义4 G1 [+ R/ g0 k& P+ @ /* USER CODE END Init */2 u& S1 i- l$ F" {7 A /* Configure the system clock */ SystemClock_Config(); 1 I6 O" g1 M8 p1 ~4 z, | /* USER CODE BEGIN SysInit */7 H, o# N, t9 `: ~6 r5 @ 7 j! }0 p2 ]; v) i$ `' w8 I. K1 b8 s' v /* USER CODE END SysInit */' t; o7 [: B2 [, q" @/ w ( V9 U4 r7 b6 z; g' R( { /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init();$ y& P( C- M: v0 y+ A, r /* USER CODE BEGIN 2 */8 h+ h; Q. O# |5 [ h& n/ h 1 Z/ b% I6 v# v- D3 S ^ /* USER CODE END 2 */& x( a3 `! }& t- [! F7 A /* Infinite loop */7 R7 C+ z8 n. O! C! d' Z: g' } /* USER CODE BEGIN WHILE */ while (1)6 k, O3 L( Q& e) |* O$ Z { $ z1 ~9 k+ d$ f0 {0 E6 b Serial_PutString(mychar);" `4 G- _" p+ ~: V . g* x/ B# i) w: k* a# J5 K* Q1 M' o if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)4 B3 h0 J3 [: b' t/ A. b0 W {* ^ z+ F# Y1 ]- O( v2 P: \ if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义+ P: N9 k$ Z9 {7 S {+ O: V2 U" E3 i% d1 E6 @ printf("正在等待数据文件下发......\r\n");/ H: \! d% K' F! {( E FLASH_If_Init();- A' b( R6 g" [' Z/ _ 6 `! S3 \" [6 C" s. G" z Y //Main_Menu(); //FlashProtection = !FLASH_If_GetWriteProtectionStatus();# O; g- i1 k2 o7 w; K' L6 F SerialDownload();( } d- M% s& V* g0 v( Z# { } ) p/ n/ E3 W- K$ h' x } . [, n' Y/ K2 F5 h5 W: x% P- O6 a /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */ if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000) { k5 C1 C9 C0 P+ S, F% t Serial_PutString((uint8_t *)"start user Program!\r\n\n"); //HAL_Delay(100);;$ }0 G L% [& @& C1 F* I, B /* Jump to user application */ JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4); Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);: g9 ^' h h6 Y( l" {% ]/ O Serial_PutString((uint8_t *)"Start program execution......\r\n\n"); //HAL_Delay(100);' M( e8 X9 z$ Y- s Jump_To_Application();( O7 m+ }& b( J3 q } else { Serial_PutString((uint8_t *)"no user Program\r\n\n"); } /* USER CODE END WHILE */: ^/ K3 `& j, b/ ` W" T /* USER CODE BEGIN 3 */% T4 F S: Z5 W. I }' j# q4 {/ U1 U! { /* USER CODE END 3 */ } int CmpStr(const char *data,const char *data1,int index1,int index2,int length) { //int temp = 0;6 d7 ?; w# P9 M0 F p for(int i = 0; i< length;i++)& W0 J3 Q* c. B% r {/ E% ^; V* n Q) o! a q if(*(data+index1+i)- *(data1+index2+i) >0)( i6 Z8 I w ?+ m9 A {( i: i, {+ Q/ _; C. n return 1; 6 J8 _3 ?- ^8 `) B/ C }4 O+ G8 ^& e2 @5 I [! \ if(*(data+index1+i)- *(data1+index2+i) <0); b. u R A: v6 A {) Z( E* E( Z" D return -1;7 N# X+ j$ ]/ V }% b7 ^$ w; }* s/ k } return 0;/ Y8 D+ H+ W& ]' A } 5 }, r4 _" g" B* N0 i 好了,基本就这些,有问题留言,我有时间就回复。。。1 c6 q2 u) t) u. U4 Q& C/ h0 e 如果有好的提议,可以一起探讨一下! |
謝謝分享 |
感恩分享 |
谢谢 分享 |
我用的CUBEMX里的例程,自己用CUBEMX建立工程将文件添加进去后,通过Ymodem下载程序,可以正常跑但执行到HAL_Delay()就卡死了,版主有遇到同样的情况吗 |
OpenBLT移植到STM32F405开发板
串口通信波特率异常的解决办法
《RT-Thread设备驱动开发指南》书籍学习记录
STM32F407/STM32F417通过以太网实现在应用中编程 (IAP)
STM32固件库分享,超全系列整理
分享STM32F407的学习资料 附学习笔记
STM32F4中文资料--基础篇
基于STM32F407和Cubemx的ADC采集+DMA传输实现简易示波器经验分享
基于STM32F407的DMA采样+FFT时域经验分享
基于STM32F407中的RNG获取随机数经验分享