|
这段时间用到STM32F417XXX一芯片做项目需要用到IAP进行串口在线升级,官方例程是利用了一个IO进行控制升级,我的想法是,使用STM32的串口控制升级,大约的流程如下:4 D; B4 r8 i& j% u& R; ~0 c 上电---->通过串口发送指定字符串------>自延时约200ms------>接收是否有上位机的指定字符串-------->如有进行升级,如无直接进行APP跳转。! J$ y- [- g3 A9 z: E" L0 V/ o0 c 首先我们下载了STM32F4xx_AN3965_V1.0.0作为初始例程,而且这个例程还有说明都一并放置到下载区了。 " Q' \3 j2 g8 o) H: Y: W; \ G 然后,我们首先生成了一个基于HAL的例程文件,只开启了UART1,其它的功能不用动 设置了时间为168MHz,然后生成了一个HAL库的代码。 r# t; S v6 R7 D 将STM32F4xx_AN3965_V1.0.0里面的 v9 R9 y5 _: J. J; c common.c. t* `+ e* u+ y* X) t' c flash_if.c menu.c ymodem.c 放置到Src文件夹中,头文件放置到inc文件夹中,在工程中将这几个文件添加到工程中(Application/usr文件夹上右键,add existiong .....) 在头文件中添加上头文件 #include "menu.h"& I9 n5 ?8 m! F& Y1 M5 z8 e4 g2 U #include "common.h"3 w$ V* [. A3 m& I #include "string.h"4 J6 D0 ~6 _1 b* Z$ J h7 W #include "stdio.h"4 P( P" }9 [4 e% M 2 _7 p* c: _5 Z) s4 ?. B, P 添加下面的这些外部定义 extern pFunction Jump_To_Application;* K& T3 `$ X( }; t3 ?) f, q6 U extern uint32_t JumpAddress;: L$ O `/ Q; f: I' X0 ? extern uint32_t FlashProtection; 编译后会出现一些错误,主要有: FLASH_Sector_x的报错,找不到这些,打到这些地方全部改成FLASH_SECTOR_X- e8 x) z2 F4 c0 G FLASH_Erase_SectorXX的报错,HAL中没有返回,相应更改一下:- e1 v. J) C+ @1 r: A3 J uint32_t FLASH_If_Erase(uint32_t StartSector)$ G7 G. N _* E; q/ R2 l+ x# D { uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;3 Y) u( s% y. w+ p, F: i$ x8 s /* Get the sector where start the user flash area *// V- m" Y& g- u! a, c$ ` UserStartSector = GetSector(APPLICATION_ADDRESS); n- A! p* L( J- g& ^ / ^2 j9 N8 G* Y6 ?3 C for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1) {* T$ P& u1 @$ s2 V/ q /* Device voltage range supposed to be [2.7V to 3.6V], the operation will be done by word */ 0 v$ B+ f A6 ?- ^ K9 V FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3); } 9 @1 S1 {: @7 L# ?" k" A8 N! s; n return (0);! X3 a" R8 h8 \" [) ~/ \; x } 6 X: M+ ~' g, b8 {3 b$ L: B" I 4 l% V9 k% w% C% `3 \5 b 其它的一些基本类似,解决办法都是是到: stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c和中找到对应的函数进行替换- N2 ]* P- a# C9 T 需要注意的是 有些函数: FLASH_Erase_Sector等,会出现一个默认定义的情况,这时只需要将本来声明到在stm32F4xx_hal_flash.c、stm32F4xx_hal_flash_ex.c中 void FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks);. X s- O1 }, h& A3 S% Y HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);* ]; m# _) _# V' P 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);1 q# s# }3 j: n/ k: R! ^' O% ] uint8_t FLASH_OB_GetUser(void); uint16_t FLASH_OB_GetWRP(void);2 \* t! H0 J% j$ u5 u" r/ x uint8_t FLASH_OB_GetRDP(void); uint8_t FLASH_OB_GetBOR(void); % o2 f0 @+ R! f0 Y3 i$ | 将这些声明直接放置到对应的头文件中去,同时将头文件包含到需要用*.c中。- m8 U/ r6 W! A$ _& F7 R, G 还需要修改这个函数 uint32_t FLASH_If_Erase(uint32_t StartSector)( U1 f6 Y9 u+ Y# v {$ t; g" [; A+ x5 p8 n1 d9 x! _ uint32_t UserStartSector = FLASH_SECTOR_1, i = 0;% I# H- d% f9 @1 `' l; _ /* Get the sector where start the user flash area *// Y, o% U+ r5 A7 M9 ?9 s UserStartSector = GetSector(APPLICATION_ADDRESS);2 c( F( R m6 B$ [; P5 s 8 ?4 g! T' }3 B+ `5 _8 [( S for(i = UserStartSector; i <= FLASH_SECTOR_11; i += 1)//原来是i+=8,查一下定义这里应该是+1$ R" ?5 B$ z$ A% [# Q {) P- K4 I+ k, V /* Device voltage range supposed to be [2.7V to 3.6V], the operation will% P3 |9 e6 t( H) X( n be done by word */ FLASH_Erase_Sector(i, FLASH_VOLTAGE_RANGE_3);9 j5 x: g( d5 I9 i! F$ g+ m. m } V( u( o) u3 l# I0 { return (0); }9 g0 @9 W8 k: o/ [ 5 ?6 ]8 I7 Z7 O2 S8 R / E: N& t* V: s/ M. M' Z 这个函数需要修改一下,标红的两句是新加的:+ Q/ p3 g% {3 k( `* O5 g- O+ e void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange) {) |2 D" G. x3 D& V uint32_t tmp_psize = 0U;, N4 m, K0 C; W* p: ^$ S# i / i, W7 c- B/ V /* Check the parameters */: }' |3 H9 v! B8 C- g assert_param(IS_FLASH_SECTOR(Sector)); assert_param(IS_VOLTAGERANGE(VoltageRange)); FLASH_WaitForLastOperation(0xFFF); if(VoltageRange == FLASH_VOLTAGE_RANGE_1) {% C, Y! p5 R5 h7 d! p tmp_psize = FLASH_PSIZE_BYTE; } else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)- k) G7 E8 P* m% Y; Z { tmp_psize = FLASH_PSIZE_HALF_WORD; } else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)! Q5 T& |$ P' x4 A" p { H# c" C7 X2 o% W1 a2 O+ I tmp_psize = FLASH_PSIZE_WORD;% a- a$ {5 G# g! C: H8 b& [( ~ } else& N( B2 k2 }8 F' Q$ a2 V { tmp_psize = FLASH_PSIZE_DOUBLE_WORD; } FLASH_WaitForLastOperation(0xFFF); /* If the previous operation is completed, proceed to erase the sector */; j; b4 d1 a) o! S( u. a* r, \. O CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); FLASH->CR |= tmp_psize; CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);& f7 N/ n0 v0 o9 X1 D FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos); FLASH->CR |= FLASH_CR_STRT; }5 f" ]; E- R8 Z" t2 |, } " T+ m7 @' X" q% e* v! m" K. T 8 B( @4 Z1 {7 y; y) m: R/ m3 ]. O 其它修改,串口修改: void SerialPutChar(uint8_t c) {; B1 d+ g7 I; J- k1 y HAL_UART_Transmit_IT(&huart1, &c,1);* m) x8 [/ X) l0 o4 x0 i3 ~ while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET);4 \, Q! P" ?# R. }, S) ~9 C. e! R }2 X/ w5 B7 E. ^% \: H, n8 P % }1 e9 r5 }9 _9 }! \0 m$ r uint32_t SerialKeyPressed(uint8_t *key) {0 k _. q" ~, F& W/ I 7 s* l9 k8 }6 }3 q if(HAL_UART_Receive(&huart1,key,1,0xFF) == HAL_OK) { return 1;6 }9 ?( `6 h M+ a g0 M } else { return 0;9 y7 u+ z- R: v: T/ \ } } 在修改完成确认没有错误了,就需要如下操作:0 r f* n" o) t4 ]. b 修改main函数:% i$ |6 b- v2 z6 p int CmpStr(const char *data,const char *data1,int index1,int index2,int length); ! l' T/ @* w p# o0 I #ifdef __GNUC__ W6 C* Z# X# h #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)+ q, y5 S& X7 Q+ P8 K #else #define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)& d' k! _9 B/ {8 R; [ 9 E) d& A2 N2 q: D #endif8 {6 `! _& f) {" }- e0 v4 v) W : D$ C7 U# L' V4 n& m' k' ~8 x1 C PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF); return ch; } /* USER CODE END 0 */ ' n: l5 _4 s1 [+ o% [+ U /** * @brief The application entry point. * @retval int */1 Z- r0 j$ A% o$ I int main(void) {! u+ L1 E' q+ X$ X /* USER CODE BEGIN 1 */; u% r# \0 A) [, |! U! V //FLASH_If_Init(); w+ q5 H4 w8 Q /* USER CODE END 1 */) K T4 ? B: r' @4 `" u : ?2 j4 D$ }0 t/ p6 A- }( e; e! J - R. z( {) H& Y0 R9 d /* MCU Configuration--------------------------------------------------------*/: f1 H/ o# ^; c' H7 T* t 3 z. b% X+ x# S4 j /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init();+ y m0 Q: G& ` /* USER CODE BEGIN Init */( o5 q0 h& Y4 c- g) i# {( X I uint8_t mychar[30] = "*****************\n\r";//上下交互的语句,请自定义* ]- m, ~' N h$ u K5 d$ s" { /* USER CODE END Init */; X3 Z2 Q# w' z4 n& l1 c / R; i% Y; L3 n( }# |; [ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ . w; c, B: b% e /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */! B# I3 D5 G) U% z$ Y /* USER CODE END 2 */ : w. \: m" j$ m$ s2 h6 G: ` /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) {5 k# w% K) m" s1 m% A Serial_PutString(mychar); if(HAL_UART_Receive(&huart1,mychar,16,0xFF) == HAL_OK)/ Q1 H. Z7 |% l5 T( N6 { {$ N N0 _* k7 A! X( N4 C if(CmpStr((char *)mychar,"**************",0,0,strlen("***********")) == 0)//标红的需要自已定义! e4 X6 l9 R6 w { printf("正在等待数据文件下发......\r\n");: y+ V2 ~. ]" {% P. i$ [ # g* Q+ c3 H1 [6 v; @ q: z$ Q) r1 q FLASH_If_Init(); " Q `) [9 G' f8 H. e& D //Main_Menu(); //FlashProtection = !FLASH_If_GetWriteProtectionStatus();9 j* _/ a! C6 e, l S" h l& R) a, t SerialDownload();" B: i# |* n+ C$ J } ; a; _6 S3 c. O- S% S6 e" v+ F1 g }. X* @4 A1 ]6 h/ i/ W& { /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */ if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)& Y6 Q( S7 B( r' x: w% g { Serial_PutString((uint8_t *)"start user Program!\r\n\n"); //HAL_Delay(100);;& C8 E* n. [' Q# _" A /* Jump to user application */ JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4); Jump_To_Application = (pFunction) JumpAddress;% ~, J- O. w6 w2 f" c: Z5 ]0 v /* Initialize user application's Stack Pointer */" }2 G9 m) k! j __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); Serial_PutString((uint8_t *)"Start program execution......\r\n\n"); x) S$ R, O3 h5 S //HAL_Delay(100);3 l: a( y9 P/ A: i: G Jump_To_Application();2 Q; M0 r$ s" E" ^5 ?" G! Q0 ^ }+ ?; J+ p, C7 m1 y- |( | ` else' Y; t' m$ _. Y8 T {; c) t3 l# v6 x3 P: R6 C0 D) _* v Serial_PutString((uint8_t *)"no user Program\r\n\n"); }) G3 z2 a$ g! ?3 h4 L" X; |$ R 6 W4 ]9 x" u: Z7 E( n! k j: ^3 ` /* USER CODE END WHILE */8 V, g5 n/ J4 e7 f1 E /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */: X* X' E1 @8 N( R9 X2 k& M }0 V3 u+ x/ v4 |# o$ c2 w: D , ` A6 M7 N; }4 q" X* C3 { # h7 ?( I# S1 \ ( h& [$ z; |7 P* _: ?5 v int CmpStr(const char *data,const char *data1,int index1,int index2,int length)7 \. G' o! [& {( F* ~ {* f4 u' {$ \9 O: I //int temp = 0; for(int i = 0; i< length;i++)! }( U% L' Q! z6 z/ Y; N! F { if(*(data+index1+i)- *(data1+index2+i) >0)8 E) Y. m5 ~( B0 ^( V1 Q5 v4 n+ p {6 i, R; G/ Z D l% {" Q4 F return 1; }% a6 E- G$ L, r5 Q- `9 [ if(*(data+index1+i)- *(data1+index2+i) <0) {" ?2 o0 K! _# b7 A7 Q' ^& i return -1;, F: U( A, N h g: n3 J6 q: f) ] } }+ L2 J* h- F9 G) m) f return 0; } 3 M0 F+ {. G( P; E B 好了,基本就这些,有问题留言,我有时间就回复。。。$ ^' ~1 p' ~1 s0 I- ] 如果有好的提议,可以一起探讨一下!7 }5 O) J9 O* _' ?, F E; U. c |
謝謝分享 |
| 感恩分享 |
| 谢谢 分享 |
| 我用的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 官方根治方案
微信公众号
手机版