基于Ymodem协议的stm32f405rgt6+CubeMx+IAP在线升级

目录

一、CubeMX的配置

1.IAP

2.APP

二、移植Ymodem官方代码

1.文件移植

2.MDK文件、路径添加

3.修改代码

(1)删除不必要的代码

(2)修改IAP代码

(3)修改APP代码

三、烧录、测试


准备工作:

1.STM32F4开发板

2.USB转串口工具

3.MDK Keil5

4.CubeMX

5.secureCRT上位机软件

6.en.stsw-stm32067官方固件库


工程下载地址:

Ymodem_IAP_F405_CubeMx+secureCRT上位机软件


一、CubeMX的配置

需要配置IAP和APP两个工程,这两个工程的配置都比较简单

1.IAP

打开CubeMX软件,选好芯片型号,这里我的芯片型号是STM32F405RGT6

配置时钟

配置主时钟,我配置的是内部时钟,主频为168MHz

配置串口

我这里配置的是串口1,对应引脚为PA9和PA10,波特率为115200,串口采用轮询的方式通讯,不采用中断的方式,故不配置串口中断,其他默认。

生成代码

H和C文件分开,配置完成后,生成代码,为后续IAP移植修改作准备

2.APP

需要再配置一个APP工程,做一个简单的APP,就是让一个LED灯不断闪烁。

这里简单的配置了PB12口为输出,作为LED灯,其他配置过程这里就省略了。

二、移植Ymodem官方代码

1.文件移植

打开之前生成好的IAP工程目录,在该目录下新建一个Ymodem的文件夹

打开我们从官网下载好en.stsw-stm32067官方固件库,将en.stsw-stm32067->STM32F4xx_AN3965_V1.0.0->Project->STM32F4xx_IAP下的incsrc文件夹中的部分文件复制到新建的Ymodem的文件夹中

复制完的Ymodem的文件夹内容如下,一共8个文件

2.MDK文件、路径添加

打开IAP的MDK工程,添加一个Ymodem组,将Ymodem文件夹中的.c文件添加进去

添加Ymodem文件夹中的.H文件的路径

3.修改代码

完成12步后编译工程会报很多错误,需要修改代码

(1)删除不必要的代码

打开common.h文件,删除#include "stm324xg_eval.h" ,这个头文件是官方用在一个官方的开发板上的,我们用不到,故删之

(2)修改IAP代码

  • common.c文件

打开common.c文件,在193行有报错,这里官方用的不是HAL库,而且官方用的开发板的接口有不同的定义,因此,我们根据自己的实际情况修改下面的代码

我们将这个函数修改如下,并且要添加一个头文件,从这个函数的内容可知,主要实现接收一个字节

/** @addtogroup STM32F4xx_IAP* @{*//* Includes ------------------------------------------------------------------*/
#include "common.h"
#include "usart.h"   //添加的头文件
/* Private typedef -----------------------------------------------------------*/
/*** @brief  Test to see if a key has been pressed on the HyperTerminal* @param  key: The key pressed* @retval 1: Correct*         0: Error*/
uint32_t SerialKeyPressed(uint8_t *key)
{if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET){*key = (uint16_t)((&huart1)->Instance->DR & (uint16_t)0x01FF);    return 1;}else{return 0;}
}

同样,修改下面的代码

修改成这样

/*** @brief  Print a character on the HyperTerminal* @param  c: The character to be printed* @retval None*/
void SerialPutChar(uint8_t c)
{USART_SendData(USART1, c);while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE) == RESET){}
}

common.c末尾添加代码,添加void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)函数

//添加代码
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{/* Check the parameters */assert_param(IS_USART_ALL_PERIPH(USARTx));assert_param(IS_USART_DATA(Data)); /* Transmit Data */USARTx->DR = (Data & (uint16_t)0x01FF);
}

common.h添加声明void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);

/* Exported functions ------------------------------------------------------- */
void Int2Str(uint8_t* str,int32_t intnum);
uint32_t Str2Int(uint8_t *inputstr,int32_t *intnum);
uint32_t GetIntegerInput(int32_t * num);
uint32_t SerialKeyPressed(uint8_t *key);
uint8_t GetKey(void);
void SerialPutChar(uint8_t c);
void Serial_PutString(uint8_t *s);
void GetInputString(uint8_t * buffP);//添加声明
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 
  • flash_if.c文件

修改FLASH_If_Init(void)

修改如下

void FLASH_If_Init(void)
{ HAL_FLASH_Unlock();/* Clear pending flags (if any) */  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);}

修改FLASH_If_Erase(uint32_t StartSector)函数

修改成HAL库的方式,修改如下:

/*** @brief  This function does an erase of all user flash area* @param  StartSector: start of user flash area* @retval 0: user flash area successfully erased*         1: error occurred*/
uint32_t FLASH_If_Erase(uint32_t StartSector)
{uint32_t UserStartSector;uint32_t SectorError;FLASH_EraseInitTypeDef pEraseInit;/* Unlock the Flash to enable the flash control register access *************//* Get the sector where start the user flash area */UserStartSector = GetSector(APPLICATION_ADDRESS);pEraseInit.TypeErase = TYPEERASE_SECTORS;pEraseInit.Sector = UserStartSector;pEraseInit.NbSectors = GetSector(USER_FLASH_END_ADDRESS)-UserStartSector+1 ;pEraseInit.VoltageRange = VOLTAGE_RANGE_3;if (HAL_FLASHEx_Erase(&pEraseInit, &SectorError) != HAL_OK){/* Error occurred while page erase */return (1);}return (0);}

修改FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data ,uint32_t DataLength)函数

修改成如下:

/*** @brief  This function writes a data buffer in flash (data are 32-bit aligned).* @note   After writing data buffer, the flash content is checked.* @param  FlashAddress: start address for writing data buffer* @param  Data: pointer on data buffer* @param  DataLength: length of data buffer (unit is 32-bit word)   * @retval 0: Data successfully written to Flash memory*         1: Error occurred while writing data in Flash memory*         2: Written Data in flash memory is different from expected one*/
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data ,uint32_t DataLength)
{uint32_t i = 0;for (i = 0; (i < DataLength) && (*FlashAddress <= (USER_FLASH_END_ADDRESS-4)); i++){/* Device voltage range supposed to be [2.7V to 3.6V], the operation willbe done by word */ FLASH_ProgramWord(*FlashAddress, *(uint32_t*)(Data+i));  /* Check the written value */if (*(uint32_t*)*FlashAddress != *(uint32_t*)(Data+i)){/* Flash content doesn't match SRAM content */return(2);}/* Increment FLASH destination address */*FlashAddress += 4;}return (0);
}

flash_if.c末尾添加如下函数

void FLASH_ProgramWord(uint32_t Address, uint32_t Data)
{/* Check the parameters */assert_param(IS_FLASH_ADDRESS(Address));/* If the previous operation is completed, proceed to program the new data */CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);FLASH->CR |= FLASH_PSIZE_WORD;FLASH->CR |= FLASH_CR_PG;*(__IO uint32_t*)Address = Data;
}

flash_if.h添加void FLASH_ProgramWord(uint32_t Address, uint32_t Data)声明

/* Exported functions ------------------------------------------------------- */
void FLASH_If_Init(void);
uint32_t FLASH_If_Erase(uint32_t StartSector);
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data, uint32_t DataLength);
uint16_t FLASH_If_GetWriteProtectionStatus(void);
uint32_t FLASH_If_DisableWriteProtection(void);//添加声明
void FLASH_ProgramWord(uint32_t Address, uint32_t Data);
#endif  /* __FLASH_IF_H */

修改 FLASH_If_GetWriteProtectionStatus(void)函数

修改如下

/*** @brief  Returns the write protection status of user flash area.* @param  None* @retval 0: No write protected sectors inside the user flash area*         1: Some sectors inside the user flash area are write protected*/
uint16_t FLASH_If_GetWriteProtectionStatus(void)
{uint32_t UserStartSector = FLASH_SECTOR_1;/* Get the sector where start the user flash area */UserStartSector = GetSector(APPLICATION_ADDRESS);/* Check if there are write protected sectors inside the user flash area */if ((*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS) >> (UserStartSector/8)) == (0xFFF >> (UserStartSector/8))){ /* No write protected sectors inside the user flash area */return 1;}else{ /* Some sectors inside the user flash area are write protected */return 0;}
}

修改FLASH_If_DisableWriteProtection(void)函数

修改如下

/*** @brief  Disables the write protection of user flash area.* @param  None* @retval 1: Write Protection successfully disabled*         2: Error: Flash write unprotection failed*/
uint32_t FLASH_If_DisableWriteProtection(void)
{__IO uint32_t UserStartSector = FLASH_SECTOR_1, UserWrpSectors = OB_WRP_SECTOR_1;/* Get the sector where start the user flash area */UserStartSector = GetSector(APPLICATION_ADDRESS);/* Mark all sectors inside the user flash area as non protected */  UserWrpSectors = 0xFFF-((1 << (UserStartSector/8))-1);/* Unlock the Option Bytes */HAL_FLASH_Unlock();/* Disable the write protection for all sectors inside the user flash area */FLASH_OB_DisableWRP(UserWrpSectors, FLASH_BANK_1);/* Start the Option Bytes programming process. */  if (HAL_FLASH_OB_Launch( ) != HAL_OK){/* Error: Flash write unprotection failed */return (2);}/* Write Protection successfully disabled */return (1);
}

需在末尾处添加 FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks)函数

HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks)
{HAL_StatusTypeDef status = HAL_OK;/* Check the parameters */assert_param(IS_OB_WRP_SECTOR(WRPSector));assert_param(IS_FLASH_BANK(Banks));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(50000);if(status == HAL_OK){ *(__IO uint16_t*)OPTCR_BYTE2_ADDRESS |= (uint16_t)WRPSector; }return status;
}

并在flash_if.h添加函数声明HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);

/* Exported functions ------------------------------------------------------- */
void FLASH_If_Init(void);
uint32_t FLASH_If_Erase(uint32_t StartSector);
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data, uint32_t DataLength);
uint16_t FLASH_If_GetWriteProtectionStatus(void);
uint32_t FLASH_If_DisableWriteProtection(void);//添加声明
void FLASH_ProgramWord(uint32_t Address, uint32_t Data);
HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks);#endif  /* __FLASH_IF_H */

修改GetSector(uint32_t Address)函数

修改如下:

/*** @brief  Gets the sector of a given address* @param  Address: Flash address* @retval The sector of a given address*/
static uint32_t GetSector(uint32_t Address)
{uint32_t sector = 0;if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0)){sector = FLASH_SECTOR_0;  }else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1)){sector = FLASH_SECTOR_1;  }else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2)){sector = FLASH_SECTOR_2;  }else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3)){sector = FLASH_SECTOR_3;  }else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4)){sector = FLASH_SECTOR_4;  }else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5)){sector = FLASH_SECTOR_5;  }else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6)){sector = FLASH_SECTOR_6;  }else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7)){sector = FLASH_SECTOR_7;  }else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8)){sector = FLASH_SECTOR_8;  }else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9)){sector = FLASH_SECTOR_9;  }else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10)){sector = FLASH_SECTOR_10;  }else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11))*/{sector = FLASH_SECTOR_11;  }return sector;
}
  • ymodem.h

ymodem.h文件添加头文件#include "stdint.h"

#include "stdint.h"
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __YMODEM_H_
#define __YMODEM_H_
  • main.c文件

在main.c文件添加头文件#include "menu.h"

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "menu.h"

main()函数添加  FLASH_If_Init()和 Main_Menu ()函数

int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */FLASH_If_Init();Main_Menu ();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

编译一下,已经没有错误了

(3)修改APP代码

打开APP工程,while(1)添加如下函数

int main(void)
{/* USER CODE BEGIN 1 */SCB->VTOR = FLASH_BASE | 0x4000; //中断向量表偏移/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_12);HAL_Delay(1000);}/* USER CODE END 3 */
}

从IAP的flash_if.h的宏定义可以看出,这里的APP起始地址为0x08004000 

生成bin文件,复制

fromelf.exe --bin -o "$L@L.bin" "#L

修改FLASH烧录地址

设置完成后编译一下,生成bin文件

三、烧录、测试

打开secureCRT上位机软件,选好端口,设置好波特率,去掉RTS/CTS的勾,点击连接,如下图

点击选项,选择会话选项,弹出如下窗口,按下图设置好,点击确定

将IAP代烧录到开发板,代码开始执行后,如下图

在下方窗口输入1,此时串口不断接受到'C',如下图所示

选择传输,点击发送Ymodem

选择添加好APP生成的bin文件,点击确定

等待一段时间,等待擦除flash,就会完成传输,此时,在下方窗口输入3,即可运行APP

至此,全部工作已结束

其他待更新。。。。。。

基于Ymodem协议的stm32f405rgt6+CubeMx+IAP在线升级相关推荐

  1. STM32F103代码远程升级(三)基于YModem协议串口升级程序的实现

    文章目录 一.YModem协议简介 二.YModem的数据格式 1.起始帧的数据格式 2.数据帧的数据格式 3.结束帧的数据格式 4.文件传输过程 三.基于Ymodem协议串口升级程序的实现过程 1. ...

  2. ymodem android,【安卓相关】蓝牙基于Ymodem协议发送bin文件,对硬件设备进行升级。...

    最近做的一个安卓项目是使用蓝牙基于Ymodem协议传输bin文件,实现对硬件设备进行升级. 做的过程中遇到了不少困难,用我这半吊子的语文水平,记录一下吧 怎么办,平时对各种文件传输协议真的是知之甚少啊 ...

  3. STM32 IAP 在线升级原理全解析

    点击左上角的"关注",定期更新 STM32 最新资讯,总有你想要的信息! STM32 IAP 在线升级原理全解析 1. 什么是 IAP?    IAP(In-Application ...

  4. 51单片机IAP在线升级

    51单片机IAP在线升级 爱矽半导体E85F3325单片机IAP在线升级教程,此处可查看更新及demo下载 文章目录 前言 一.ROM资源 二.KEIL有关知识 1.BL51连接器: 2.LX51连接 ...

  5. CRC校验原理及STM32 IAP在线升级程序

    CRC校验原理: 什么是CRC校验? CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能,对数据 ...

  6. STM32F429实现USB通过IAP在线升级

    1.目标 1.实现STM32对U盘文件的读取. 2.实现STM32拓展外部SDRAM. 3.实现STM32拓展外部Flash. 4.实现内存管理. 5.实现Fatfs文件系统,读写U盘和外部Flash ...

  7. 基于串口通信的DSP应用程序在线升级方法

    摘  要:为解决特殊场合DSP程序升级困难的问题,以TMS320F28035为例,介绍了一种基于串口通信的适合于TMS320C2000系列DSP实现程序更新的在线升级方法.描述了该在线升级方法的基本思 ...

  8. LPC2478(22)IAP在线升级

    目录 1.开发环境 2.特性 3.IAR编译器的相关文件 3.1.icf文件 3.2.IcfEditorFile文件内容 3.3.ddf文件 3.4.board文件 4.IAP相关 4.1.软件复位 ...

  9. Cortex-M3单片机的IAP在线升级上位机和下位机

    最近有个项目要做在线升级功能,我也是第一次做,把学习的过程总结下,希望能够帮助到 其他人吧.本篇博客主要介绍两个部分,下位机和上位机. 首先说下要实现功能: 1.上位机能够把APP的bin文件烧写进下 ...

最新文章

  1. layer的一种用法,自己画出弹出框样式
  2. 第41周星期四及Spring学习小结
  3. mysql测试spring事务是否生效
  4. math.js:灵活强大的JavaScript数学库
  5. 基于SQLite+EF6实现一套自己的Key-Value存储管理工具包(3)
  6. javascript弹出窗口总结
  7. Selenium Grid
  8. iOS开发-集成一网通支付
  9. php如何锁定表,PHPExcel冻结(锁定)表头的简单实现方法
  10. Ubuntu 下挂ISO到虚拟光驱的方法
  11. sklearn实战之逻辑回归与制作评分卡
  12. 图书馆管理系统 13-架构设计
  13. Linux vi精确匹配
  14. Mac m1 配置OpenCV (C++)
  15. ue4超级跳、do once、技能冷却时间
  16. 软件外包公司工作好不好,以下情况可考虑
  17. 原生Android 极光推送收到通知后自动点亮屏幕
  18. PMP考试 项目启动会和项目开工会议的区别(转载)
  19. 计算机中英语单词翻译,计算机有关的英语单词及翻译
  20. 2021-09-10 LeetCode_Java:1-5

热门文章

  1. linux服务器 自动重启 问题排查
  2. 富士最快计算机,高速处理 富士推出X RAW STUDIO转换软件
  3. H5实现可拖动的360度环拍物品展示(1)
  4. 如何将div上下居中,左右居中 有五种(width height定,width height不定 尺寸不固定)
  5. 杜邦分析模型 java_1.杜邦分析法的核心指标是(  )。
  6. Android res\values-v26\values-v26.xml:9:5-12:13: AAPT: error: resource android:attr/colorError not f
  7. 攻防世界_MISC_练习区_刷题记录
  8. 深入浅出:FFmpeg 音频解码与处理AVFrame全解析
  9. 用Word2003也能给文档加上稿纸(转)
  10. 2021-06-27 记录最近刷过的数论题(整除分块,MillerRabin素性检测,积性函数,重数)