这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:/ o; ^ R- I# @4 O 上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。 ) J& m* O2 x0 \5 g- D 首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。 6 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 flash_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 .....) 在头文件中添加上头文件$ 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 添加下面的这些外部定义 extern pFunction Jump_To_Application;) _4 R4 ]5 @4 F3 r! F g extern uint32_t JumpAddress; extern uint32_t FlashProtection;: l0 _4 w# D! X2 c$ W( m % P% |! v9 q( [3 _: a5 q 编译后会出现一些错误,主要有: FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X 9 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 { uint32_t UserStartSector = FLASH_SECTOR_1, i = 0; /* Get the sector where start the user flash area */ UserStartSector = GetSector(APPLICATION_ADDRESS);9 E. y! m) }- B1 y$ W 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 be done by word */ FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3); }& ~9 m) t. V0 t% U2 ^+ Y 1 S7 l$ g) D0 f! i' z) e+ M return (0); }0 v! d/ N5 _7 L& c, Y . O9 F! Y( m; H, y 其它的一些基本类似,解决办法都是是到:1 F4 R2 l5 R8 v) u z stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换 需要注意的是 有些函数:& 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); HAL_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); HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t Level); HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby); HAL_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); uint8_t FLASH_OB_GetBOR(void); % T& T! W) J6 K; J, _( [$ m 将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。 还需要修改这个函数 uint32_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; /* Get the sector where start the user flash area */ UserStartSector = GetSector(APPLICATION_ADDRESS); for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1 {- }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); }# c e/ @1 \: y% k' U2 |) m return (0);9 L, V% H& [/ z% [4 V }, y3 x, r! R% Z: x / i4 T3 S$ _5 C; X/ e 这个函数需要修改一下,标红的两句是新加的: void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)5 N# v# S( ^7 [! w2 j& F6 l/ W { uint32_t tmp_psize = 0U;" C- i& c$ t3 v A" ~5 O1 _& v /* Check the parameters */& ]9 C4 k! Z# m6 r' Z8 ?! | assert_param(IS_FLASH_SECTOR(Sector)); assert_param(IS_VOLTAGERANGE(VoltageRange)); 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; } 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 { 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 { 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 FLASH_WaitForLastOperation(0xFFF); /* 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); FLASH->CR |= tmp_psize; CLEAR_BIT(FLASH->CR, FLASH_CR_SNB); FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos); FLASH->CR |= FLASH_CR_STRT; }) u& S/ L3 i6 H$ d# n4 t" C6 s & a$ K6 |/ g' h! P& G 其它修改,串口修改:# `: E$ J4 c# ]* @+ c$ {- e" F7 U& r void SerialPutChar(uint8_t c)9 O5 R) B* d5 W0 I* C# z9 B" O { HAL_UART_Transmit_IT(&huart1, &c,1); while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);: I* C W8 @, `4 P/ t } " F5 N9 |" ~3 W uint32_t SerialKeyPressed(uint8_t *key) {7 P" C. Q$ o/ K( M) T1 |0 }$ a8 T' n 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 } else f3 C3 Q) n; i/ v, N9 F. v {( ~' j+ A: F6 d( X3 L7 o6 D return 0; } }, ?+ D- g4 I% p& i: N, S$ M6 a8 L 在修改完成确认没有错误了,就需要如下操作: 修改main函数: int CmpStr(const char *data,const char *data1,int index1,int index2,int length); ) G! J4 d, K% Z( _5 W #ifdef __GNUC__7 F w, I" i1 l3 P& M8 P; G #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)4 ]7 g& Y$ o+ e' t1 r- M+ @9 O1 \ #else #define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f) & u" I' } F h2 h5 P" _$ f #endif/ Y( i8 N0 Z! | 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; }2 J) a( D3 N# r. e+ w/ x /* USER CODE END 0 */ /**# Q9 b W: z. A* t7 ]* w * @brief The application entry point.% L% z' Z% i" C0 Y3 Y. Y * @retval int */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 */ //FLASH_If_Init();" A, |8 n9 H" K /* USER CODE END 1 */ 9 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. */ HAL_Init(); /* USER CODE BEGIN Init */ 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(); /* 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 */ /* 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(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */5 S# W5 e6 s: R 4 W" [# f, B& G3 x# ?# d /* Infinite loop */ /* USER CODE BEGIN WHILE */2 B; J% G1 v- p' e0 L while (1)9 V0 p% T5 I* A# A5 D, Q2 Q { 8 M2 X- {* [% e' K* q2 D0 }0 P6 P/ L Serial_PutString(mychar); if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)0 A$ N3 O) O j. ?: H& ]' O { if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义$ G" L# W" G# Q! \% ]' I { printf("正在等待数据文件下发......\r\n");! C6 a$ \, F, n# U" ]+ V# m 6 @: W- {1 S6 g+ n, M2 K FLASH_If_Init();9 [; J$ L& e* Z) N$ i" y //Main_Menu(); //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 /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */ if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000) { " 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);; /* Jump to user application */ 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 */ __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); Serial_PutString((uint8_t *)"Start program execution......\r\n\n"); //HAL_Delay(100); Jump_To_Application(); } else0 V; s: d0 }: m7 B. c { Serial_PutString((uint8_t *)"no user Program\r\n\n");; k% V u f b i w }+ V7 f) |. T! r- |* w& E g /* USER CODE END WHILE */' Y/ ?6 U5 p4 [. f- B /* USER CODE BEGIN 3 */# e. m* a+ a+ D0 p }5 k0 |& I l- |, E( w5 J& i /* USER CODE END 3 */ } : 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 { //int temp = 0; for(int i = 0; i< length;i++)+ |; Y6 a4 K8 t2 G. | o8 H; O5 h1 g { if(*(data+index1+i)- *(data1+index2+i) >0)/ C8 y, p/ K& D F; D { return 1; 5 L8 ]/ O6 u" P5 C: n; g3 P } if(*(data+index1+i)- *(data1+index2+i) <0) {, 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; } 好了,基本就这些,有问题留言,我有时间就回复。。。 如果有好的提议,可以一起探讨一下! |
謝謝分享 |
感恩分享 |
谢谢 分享 |
我用的CUBEMX里的例程,自己用CUBEMX建立工程将文件添加进去后,通过Ymodem下载程序,可以正常跑但执行到HAL_Delay()就卡死了,版主有遇到同样的情况吗 |
OpenBLT移植到STM32F405开发板
串口通信波特率异常的解决办法
《RT-Thread设备驱动开发指南》书籍学习记录
STM32F407/STM32F417通过以太网实现在应用中编程 (IAP)
STM32固件库分享,超全系列整理
分享STM32F407的学习资料 附学习笔记
STM32F4中文资料--基础篇
基于STM32F407和Cubemx的ADC采集+DMA传输实现简易示波器经验分享
基于STM32F407的DMA采样+FFT时域经验分享
基于STM32F407中的RNG获取随机数经验分享