|
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:% Y% X) m2 Q/ J' i: j 上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。 % L* r, c# R. @* a5 h. ?5 g1 O# E2 k. ] 首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。 然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动 5 k, k$ a6 F; R- J( J" V" N- E4 p5 D 设置了时间为168MHz,然后生成了一个HAL库的代码。2 h; Z. f$ w! r( E0 b 将STM32F4xx_AN3965_V1.0.0里面的# ~) g) Z, e+ Z% }& D7 c7 e common.c flash_if.c- l& k& Z8 S9 v5 W$ ?# ]2 k) a: o menu.c ymodem.c5 t: Y9 ?2 r- z# }" ^) e4 y. x V 放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add existiong .....) 2 {6 l" X. B7 n% U& d* ?% O 在头文件中添加上头文件+ h8 U5 M5 z! f ] #include "menu.h"8 g4 i! \ y; v( M# Z #include "common.h" #include "string.h"' y% n1 \, u6 e #include "stdio.h" 添加下面的这些外部定义 extern pFunction Jump_To_Application;" r, Y( }$ K4 f% o$ X; w extern uint32_t JumpAddress; extern uint32_t FlashProtection; 编译后会出现一些错误,主要有:8 {- T; ^3 J* h* a# F% U FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X& A- a* w# Z9 ]1 z8 V7 X) l FLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:; Y6 @# r: e" M& F! r5 P/ ]/ M uint32_t FLASH_If_Erase(uint32_t StartSector) {! G- ~- O% a5 _3 ~0 ^; a4 {9 ? uint32_t UserStartSector = FLASH_SECTOR_1, i = 0; . V6 V$ W& X7 F* M+ U; e( l; n6 Y /* Get the sector where start the user flash area */ UserStartSector = GetSector(APPLICATION_ADDRESS);5 C8 M! I2 V' Q+ v for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)0 D" g: i2 n' _2 ?) x; k { /* Device voltage range supposed to be [2.7V to 3.6V], the operation will+ P( A$ X- e1 A2 M, r! N- ~ be done by word */ s$ p, Q$ h8 J9 z9 c0 L- ~ FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);$ V7 O6 G, Q8 |' r, [ } return (0);2 ?7 u( l# t/ ?1 @4 O% c } + C1 e+ N* l) Q2 l( Z- ?; L+ }! U 其它的一些基本类似,解决办法都是是到:$ \) H6 ?0 C( M* ^2 D4 V$ { stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换( G/ } e! ~7 P) W" j( V3 f 需要注意的是: F! F5 `& R( C+ g7 Q! |# t 有些函数:* K/ t4 {3 ?+ X b2 a* O0 R FLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中 void FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);0 x, w; l. T1 c b HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);* y( r+ g* b+ q HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);" T6 f7 o% W4 e& d9 P* A) t HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t Level); o+ ~4 F7 g9 C6 ^- O 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);) K. ~& t+ Y6 Y E1 Q3 N: @ uint16_t FLASH_OB_GetWRP(void); uint8_t FLASH_OB_GetRDP(void);/ z* ]0 o' e3 T1 V. ^' [- ^ uint8_t FLASH_OB_GetBOR(void); 将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。 还需要修改这个函数 uint32_t FLASH_If_Erase(uint32_t StartSector); r- i7 a8 e/ V { uint32_t UserStartSector = FLASH_SECTOR_1, i = 0; ; ]% w, J6 G& e! \6 p /* Get the sector where start the user flash area */! C3 {% I0 O3 I u1 F u% Q7 G; Y UserStartSector = GetSector(APPLICATION_ADDRESS); 0 v% D- ~! s, Q+ Z, L; q 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 */ % G0 o7 }. K, v, Q( i# f( O$ R FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);; ?4 ?% O; h5 t8 V } return (0); } ' F0 R% c( E/ a# q; A ' d+ N) } T" s7 [, h ( A, a% {6 d( N9 h' ] 这个函数需要修改一下,标红的两句是新加的: void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)2 ]8 P* v7 K1 i4 s5 n { N' F5 }# q! }7 [7 e uint32_t tmp_psize = 0U;8 h2 ]2 X( o9 I1 N /* Check the parameters */4 V& V2 ~1 ?4 v* R1 I v7 q# l2 p7 E assert_param(IS_FLASH_SECTOR(Sector));& i5 K. o0 i# h* f1 t c assert_param(IS_VOLTAGERANGE(VoltageRange));% ~% }$ p) I# R; |0 y k2 Q# A f ? FLASH_WaitForLastOperation(0xFFF);- x% Y' \7 \; s* y; {4 Z if(VoltageRange == FLASH_VOLTAGE_RANGE_1) { tmp_psize = FLASH_PSIZE_BYTE; }: F. e1 A9 \* \9 t else if(VoltageRange == FLASH_VOLTAGE_RANGE_2) {$ n$ J G& K7 V0 X5 V6 B tmp_psize = FLASH_PSIZE_HALF_WORD; } else if(VoltageRange == FLASH_VOLTAGE_RANGE_3) { tmp_psize = FLASH_PSIZE_WORD; }; v. ^8 o( O2 ~# I else+ j& h- Z: m6 E3 G9 E4 i {$ c9 I, U W2 V* U* w tmp_psize = FLASH_PSIZE_DOUBLE_WORD; }- f& o2 Z( m/ k: f6 _ , I% Q3 g' I2 V2 N FLASH_WaitForLastOperation(0xFFF); /* If the previous operation is completed, proceed to erase the sector */! e! o+ H! x% Y# Z! w" V: B CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); FLASH->CR |= tmp_psize; CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);0 f) O% Z; {; ~( O" ^; k5 p4 n, Z' n FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos);# }: F+ {9 A* U! h7 | FLASH->CR |= FLASH_CR_STRT;1 c/ K) X5 Y9 i- @8 ?" w } # f; h9 x: f8 X" y! r; k# E 6 g" y0 A" R$ R4 g 其它修改,串口修改: void SerialPutChar(uint8_t c) { HAL_UART_Transmit_IT(&huart1, &c,1); while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET); } 3 e7 k* x8 t! [4 o ) |, t( I+ I d' g3 S uint32_t SerialKeyPressed(uint8_t *key) {! K+ w/ H. l P$ a8 e% l- [ * ?6 N- s) V# {% d- S if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK)4 i7 Q% P3 P% {' d& l {- J. u! D+ G; e" t return 1;+ P+ `3 W% x) c% v5 L8 W7 w } else { return 0; [4 r5 s' Z: g, b( N# z+ F }7 H* g. w: c* _$ u & _9 M. C# b( Y4 M& A* U }. a% T: s }: z- h: A 在修改完成确认没有错误了,就需要如下操作:' _% B5 H, N0 M ^, Q 修改main函数: int CmpStr(const char *data,const char *data1,int index1,int index2,int length);% u/ a! {+ y3 @$ e* R+ r7 S #ifdef __GNUC__ * Y% ~9 Z0 ~5 H+ Q+ ?7 Q #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)& u. f8 w2 P/ V1 w0 m7 f #else ) h2 x$ x3 ]) j# |4 y# B #define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f) #endif4 i8 n2 @/ R. `' D# { 8 C2 A; `) D: E2 E PUTCHAR_PROTOTYPE E* I- J% e; V8 O {" m5 p6 w# y4 k HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF); return ch;$ a4 L: h$ E Q0 B } /* USER CODE END 0 */ /** * @brief The application entry point.+ Z/ _/ L2 g1 K u* T * @retval int */ int main(void), \9 d4 A4 {& ^- |$ _8 x# P a {1 ~& t( V( x. A$ H" L& p I$ k /* USER CODE BEGIN 1 */1 Q( C" m" E9 q) ]* P ^" f# w //FLASH_If_Init(); /* USER CODE END 1 */ : h7 m G% i& X4 H* ~8 u! g7 | /* MCU Configuration--------------------------------------------------------*/6 t, P7 z; t) q1 L: b+ }7 O . u7 T4 B' h+ l4 H" E% d /* Reset of all peripherals, Initializes the Flash interface and the Systick. */( W, R) S! r0 D HAL_Init(); /* USER CODE BEGIN Init */ uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义- Y1 Q8 c0 s+ b5 ?" H* w- Q& v /* USER CODE END Init */ /* Configure the system clock */! z9 \/ R" b, x) s7 O* n" x7 `# [ SystemClock_Config();* Y6 k! |) C7 K, C( A /* USER CODE BEGIN SysInit */6 [8 Z g7 g/ e) C" k: ~ 1 X8 O# S6 _- u2 M /* USER CODE END SysInit */ /* Initialize all configured peripherals */0 ~6 f" m$ Y9 X) d8 Z/ x/ U MX_GPIO_Init();5 w5 \6 s2 y6 P! V7 B8 `4 _9 { MX_USART1_UART_Init();9 ^5 Y: e2 y! z0 a /* USER CODE BEGIN 2 */ 3 [; m8 m2 q# p/ y2 |2 r /* USER CODE END 2 */ /* Infinite loop */ }$ I% f& L3 c' \& y0 o7 E% ` /* USER CODE BEGIN WHILE */ while (1) {0 t, @4 J( A, @- T" P6 H& g 4 h( e7 r1 S+ | Serial_PutString(mychar); if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK) {$ y9 E0 e4 h; n7 T0 @2 `) x if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义- M1 S- Q) a) C6 Z5 e# l& w { printf("正在等待数据文件下发......\r\n"); . K- A' I2 p- M' ^7 u: A" y FLASH_If_Init(); + v+ o6 Z' h& c% f, Q3 | //Main_Menu(); //FlashProtection = !FLASH_If_GetWriteProtectionStatus();0 x* u: L- k- g% _0 j& M2 I- L SerialDownload();: ]. V7 |0 v( f } * \7 ]4 o4 g" A& ~. L( i }4 ?$ Z% z+ i8 u; @4 Q+ Y2 m3 X3 w /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */0 A% O7 o: |, r: b$ ~ if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000) { Serial_PutString((uint8_t *)"start user Program!\r\n\n");2 X$ s& @4 y; H7 Y //HAL_Delay(100);;1 l7 Z" J; Q( [2 [ /* Jump to user application */0 l U: L3 p" { JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);9 G# B. z# K% X# z' g# B! q, X0 u+ C Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */# X8 Q/ A: z" U( v/ W __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);" i# \( }* B4 r- M4 H6 b- u1 _; r Serial_PutString((uint8_t *)"Start program execution......\r\n\n"); //HAL_Delay(100);) K! N+ q( k7 t' x4 t Jump_To_Application();+ D% R k5 ~, J5 l7 B5 B }' z* c6 U' f9 E2 Q2 A f# ?4 W. H else {: ?5 i: I4 u- p8 F1 s! ~ Serial_PutString((uint8_t *)"no user Program\r\n\n"); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */, b' m/ [ d4 j j }/ x* w' r2 ~3 R) r7 P * U4 r$ y1 O$ ^; V# z: Z9 p , J U( \8 ^% Z( t# J* o + i9 U* w) c" ^5 g' R; q% D int CmpStr(const char *data,const char *data1,int index1,int index2,int length)" @( K& P$ R( a) P( Q& X* d' O: J { //int temp = 0; for(int i = 0; i< length;i++) { if(*(data+index1+i)- *(data1+index2+i) >0)2 @* T( \4 J6 p$ p! g( c5 x# I" q0 J {$ t) g5 ~) T% V! n4 k; j: b; _ return 1; 0 I4 B- p @7 A0 ]6 a6 d }+ B1 P: P3 d9 T: M. L E if(*(data+index1+i)- *(data1+index2+i) <0) { return -1;- q: _/ s3 s( ]5 x8 j, q } }0 R; Q. b4 s ~/ S: @ return 0; } 好了,基本就这些,有问题留言,我有时间就回复。。。 如果有好的提议,可以一起探讨一下! |
謝謝分享 |
| 感恩分享 |
| 谢谢 分享 |
| 我用的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 官方根治方案
微信公众号
手机版