STM32F1 IAP在线升级功能实现(使用串口)及心得

这篇具有很好参考价值的文章主要介绍了STM32F1 IAP在线升级功能实现(使用串口)及心得。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

公司产品要求,需要做一个能远程升级程序的功能,找了很多例程,大多都是需要按键来完成操作的,而我需要的是通过串口发送指令来完成,于是东拼西凑最后还是用了四天的时间勉强做出来

整个功能需要的程序是两个部分。一个是IAP程序,一个是APP程序。对于IAP程序和APP原理方面的内容就不再过多赘述。直接从操作开始吧。

IAP程序

写IAP程序之前首先得配置程序的起始地址和大小。这里根据个人情况而定,我这里单片机flash大小是512k,所以IAP程序选择分配的大小是64k。
stm32 串口升级程序,STM32F1,stm32,单片机,arm

点击魔术棒,然后在选择target,设置起始地址(start)和大小(size),IAP程序起始地址都是从0x8000000开始的,大小就是0x10000也就是64k啦。
在这里我参考了原子哥的源码和一位大神的分享,原子的资料一搜一大堆,这里就仅贴出大佬的链接
stm32 IAP 程序编写心得
有了前车之鉴,做起来也稍显得心应手,这里的flash操作的函数和IAP功能函数都是拿来主义了,原子IAP例程里拿来就可以用。主要工作还是针对main函数,这里直接贴出源码:

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "stmflash.h"
#include "iap.h"
 
#define ADDR_CodeWriteFlag  0X08070000		//设置跳转标志位保存地址
#define ADDR_JumpToIAPFlag  0X08070001
int main(void)
{	
	u16 IAPFlagBuf[2];
	u16 RxDataCount=0;				//串口接收到的数据计数
	u16 RxDataLength=0;				//串口接收到的数据长度
	u16 AppCodeLength = 0;		//接收到的app代码长度
	u8  RxCmdFlag = 0;				
	u8  AppRunFlag = 0;				//应用程序运行标志
	u16 JumpToAPPFlag;									//跳转至APP程序标志位
	u16 JumpToIAPFlag;									//跳转回IAP标志位
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	JumpToAPPFlag = STMFLASH_ReadHalfWord(ADDR_CodeWriteFlag); //读取APP写入标志位,判断是否已有程序
	JumpToIAPFlag = STMFLASH_ReadHalfWord(ADDR_JumpToIAPFlag);
	uart_init(9600);					//串口初始化为9600
	delay_init();	   	 				//延时初始化 
	IAPFlagBuf[0] = 0x11;
	IAPFlagBuf[1] = 0x00;
	
	printf("提示:输入send发送bin文件!\r\n");
	while(1)
	{
		if(JumpToAPPFlag != 0x11)			//判断是否已有APP程序,如果已有,跳转至APP程序运行
		{
			if(JumpToIAPFlag == 0x11)		//判断是否从APP程序跳转回来,如果是擦除已有APP程序
			{			
				JumpToIAPFlag = 0x00;		
			}
			if(USART_RX_CNT)			//如果有数据进来
			{
				if(RxDataCount == USART_RX_CNT)				//串口没有再收到新数据
				{
					RxDataLength = USART_RX_CNT;
					if(RxCmdFlag == 0 && RxDataLength == 4)	//接收到IAP指令
					{
						if(USART_RX_BUF[0] == 's' && USART_RX_BUF[1] == 'e' && USART_RX_BUF[2] == 'n' && USART_RX_BUF[3] == 'd')//判断是否为IAP指令
						{
							RxCmdFlag = 1;							//接收到更新APP代码指令,标志位置1
							RxDataLength = 0;						//清空指令长度,防止影响后面计算APP代码大小
							printf("准备接收app程序,请添加bin文件!\r\n"); //准备好接收bin文件,等待用户添加
						}
						else
						{
							CodeUpdateFlag = 0;
							AppCodeLength = 0;
							printf("指令错误!\r\n");	//未接收到IAP更新指令,其他任何串口发送数据都认为指令错误
						}
					}
					
					else if(RxCmdFlag == 1 && RxDataLength > 10)//接收APP程序
					{
						CodeUpdateFlag = 1;												//代码更新标志位置位,用于应用程序代码接收完成后写FLASH
						RxCmdFlag = 0;
						AppCodeLength = USART_RX_CNT;
						printf("APP程序接收完成!\r\n");
						printf("程序大小:%dBytes\r\n",AppCodeLength);
					}
					
					else
					{
						RxDataLength = 0;
						printf("文件或指令错误!\r\n"); //如果代码大小不足10Bytes,认为没有正确添加bin文件
					}
					RxDataCount = 0;
					USART_RX_CNT = 0;
				}
				else 
				{
					RxDataCount = USART_RX_CNT;
				}
			}
			
			delay_ms(10);											//给以串口中断的时间,判断是否接收完成
			
			if(CodeUpdateFlag)								//代码更新标志位置位
			{
				CodeUpdateFlag = 0;
				if(AppCodeLength)
				{
					printf("程序更新中...\r\n");
					if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)					//判断代码合法性
					{	
						printf("正在下载程序!\r\n");
						iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,AppCodeLength);	//新代码写入FLASH  
						AppRunFlag = 1;
					}
					else 
					{
						printf("程序更新失败,请检查bin文件是否正确!\r\n");
						printf("跳转到原有应用程序!\r\n");
						iap_load_app(FLASH_APP1_ADDR);								         //执行FLASH APP代码
					}
				}
				else 
				{
					printf("没有程序可以更新!\r\n");
				}								 
			}
			
			if(AppRunFlag)																//App运行标志置位
			{
				printf("开始运行程序!\r\n");
				delay_ms(10);                        
				if(((*(vu32*)(FLASH_APP1_ADDR + 4)) & 0xFF000000) == 0x08000000)		//判断代码合法性
				{	 
					AppRunFlag = 0;
					STMFLASH_Write(ADDR_CodeWriteFlag,IAPFlagBuf,2);		   //写入APP代码标志
					//RCC_DeInit(); //关闭外设
					//__disable_irq();
					iap_load_app(FLASH_APP1_ADDR);								         //执行FLASH APP代码
				}
				else 
				{
					printf("应用程序错误!\r\n");  
				}									   
			}
		}
		else
		{
			printf("已有一个应用程序!\r\n");
			printf("开始运行程序!\r\n");
			delay_ms(10);
			iap_load_app(FLASH_APP1_ADDR);										//执行FLASH APP代码
		}
	}
} 

  1. main函数中,选择一块不使用的flash区域来保存跳转标志位。
    stm32 串口升级程序,STM32F1,stm32,单片机,arm
    我选择的是0x8070000开始的区域,整个flash大小是512k也就是0x8080000,所以最后我又留了64k的大小来存放,所以留给APP程序的就是0x08010000到0x08070000的地址,也是就384k大小空间,记住这个0x08010000到0x08070000,后面APP程序要考。

  2. 每次进入main函数都要先读这个地址的值,若等于0x11则直接跳转到APP,因为在跳转APP之前是要对这个地址进行写0x11的,所以跳转到APP后这个地址是0x11,开机启动会自动进入APP。
    stm32 串口升级程序,STM32F1,stm32,单片机,arm
    到此似乎思路就清晰了,原子通过按键来操作接收,下载。我这里通过指令来接收下载,其他的判断栈顶地址的合法性,看两遍代码也能明白了。

APP程序

接下来就是APP程序的操作部分了。
要从IAP跳转到APP,APP的程序也需要修改。首先就是程序的起始地址和大小。
stm32 串口升级程序,STM32F1,stm32,单片机,arm
前面的IAP从0x8000000到0x8010000,所以我们的APP程序只能从0x8010000开始,而0x8070000到0x8080000又要保存跳转标志位,那么APP的地址就只能是0x8010000到0x8070000了,既然这样,那就拉满吧,所以大小设置我选择0x60000。
然后就是输出bin文件了,要用串口传输不能用hex文件,所以在USER界面
选择如图所示操作,方框里填的是E:\keil5\ARM\ARMCC\bin\fromelf.exe --bin -o …\output\Project.bin …\output\Project.axf 注意有空格,当然这个也得根据自己的文件位置更改。
stm32 串口升级程序,STM32F1,stm32,单片机,arm
下一步就是更改偏移地址了,这里只需要在主函数里加
SCB->VTOR=FLASH_BASE|0x10000; 即可,我这里偏移0x10000
stm32 串口升级程序,STM32F1,stm32,单片机,arm
到此就能编译生成bin文件,通过IAP程序,使用串口来完成升级了。
但是后续要升级怎么办,我们还得从APP跳转到IAP来。所以在APP程序中还需要接收指令来跳转到IAP去。
stm32 串口升级程序,STM32F1,stm32,单片机,arm
这里Receive_Data_Point3是接收到的字节长度,我设置的跳转指令是APPTOIAP!共9位。
然后就是跳转前还需将存放标志位得地址写入0x00,前面IAP中会对该地址得值进行判断是否是0x11,是的话就又跳回来了。然后有大佬踩坑后,得知跳转到IAP直接用NVIC_SystemReset(); 即可。
stm32 串口升级程序,STM32F1,stm32,单片机,arm
到此就基本完成了。
第一次写博客,也是为了记录和学习。语言不通顺还请多谅解,如有错误的地方也请多加指正。同时有疑问的同学也可以评论留言,欢迎讨论交流。

可能出现的问题解决方法:
在后续的测试中发现,串口接收bin文件时还没接收完就进入到了写入flash的动作,导致有很大的概率程序升级失败。分析了半天原因可能是,接收缓存在10ms内没收到数据就默认接收完毕进入写入跳转了,我使用的9600波特率,在将下图中的延时增加到100ms后,没有再出现问题了。
stm32 串口升级程序,STM32F1,stm32,单片机,arm文章来源地址https://www.toymoban.com/news/detail-686537.html

到了这里,关于STM32F1 IAP在线升级功能实现(使用串口)及心得的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32F407串口IAP远程升级程序

    相关代码和工程文件链接:https://pan.baidu.com/s/1wN4THWJwqzjjIe7e2TENBA?pwd=o86o 提取码:o86o         STM32代码烧录主要有三种:ICP、ISP、IAP。         ICP(In Circuit Programing),在电路编程,通过JTAG或者SWD接口进行程序的烧录,就是平时利用ST-Link或者J-Link烧录程序;       

    2024年02月10日
    浏览(99)
  • GD32单片机远程升级下载,手机在线升级下载程序,GD32在线固件下载升级,手机下载程序固件方法

            GD32、STM32单片机,是我们最常见的一种MCU。通常我们在使用STM32单片机都会遇到程序在线升级下载的问题。         GD32/STM32单片机的在线下载通常需要以下几种方式完成:       1、使用ST/GD提供的串口下载工具,本地完成固件的升级下载。        2、自行完成系统

    2024年02月02日
    浏览(49)
  • 在线升级:OTA升级的原理和实现方式

    目录 1、OTA 在线升级 2、实现方式 3、操作方式 3.1、后台式升级 3.2、非后台式式更新 4、STM32 的在线升级 4.1、划分 Flash 区域 4.2、实操1 - Flash空间地址的划分 4.3、实操2 - 设置工程 4.4、实操3 - 接收固件更新包 4.5、实操4 - 拷贝程序至Flash 4.6、实操5 - 跳转至 App 应用程序 4.7、特

    2024年02月01日
    浏览(42)
  • 【STM32 IAP技术实现】适合小白“食用”(以STM32F103C8T6为例)

      想必大家对 单片机烧录 一词都不陌生,就是将程序下载到我们的板子(MCU)里面。常见的烧录方法有用Keil下载,或者是编译出Hex文件通过烧录软件(上位机例如:muisp、flymcu)、烧录器软件(例如:J-LINK、ST-LINK)烧录,从程序的角度来看通过烧录,它被“更新”了。

    2024年02月03日
    浏览(70)
  • STM32 IAP应用开发——通过USB实现固件升级

    什么是IAP? IAP(In-Application Programming) 指MCU可以在系统中获取新代码并对自己重新编程,即可用程序来改变程序。在应用编程(IAP)是用户的应用代码对片内Flash存储器进行擦除/编程的方法。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就

    2024年02月12日
    浏览(35)
  • 【STM32】IAP升级01 bootloader实现以及APP配置(主要)

    通过之前的了解 之前的了解,我们知道实现IAP升级需要两个条件: 1.APP程序必须在 IAP 程序之后的某个偏移量为 x 的地址开始; 2.APP程序的中断向量表相应的移动,移动的偏移量为 x; 默认条件下的起始地址 默认的条件下,图中 IROM1 的起始地址(Start)一般为 0x08000000,大小

    2024年02月03日
    浏览(37)
  • GD32F4XX IAP升级

    这里使用的是GD32F405RG,flash 为1M(0x08000000 - 0x080FFFFF),具体参考官方手册 因为每个芯片的falsh大小不一样,地址划分根据实际flash大小和自己的设计去分配就好, 自己的址划分如下 : BOOT_ADDRESS:0x08000000 - 0x08003FFF     16k(扇区0) APP_ADDRESS:0x08004000 - 0x0807FFFF     512k-16

    2024年02月12日
    浏览(33)
  • 基于STM32F1以及STM32CubeMx实现串口中断通讯(字符串发送与接收)

    首先选好自己的板子并打开软件设置,本实验基于STM32F103ZET6实现,打开软件后如图: 打开外部高速晶振,然后接着配置时钟: 将时钟频率修改为72MHz,接着设置接线方式为SW 接下来需要使用串口中断通讯,打开我们的串口设置并打开中断 这里波特率设置为115200,数据位为

    2024年02月09日
    浏览(37)
  • STM32 IAP应用开发——通过串口/RS485实现固件升级(方式1)

    什么是IAP? IAP(In-Application Programming) 指MCU可以在系统中获取新代码并对自己重新编程,即可用程序来改变程序。在应用编程(IAP)是用户的应用代码对片内Flash存储器进行擦除/编程的方法。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就

    2024年02月10日
    浏览(32)
  • STM32 IAP应用开发——通过内置DFU实现USB升级(方式2)

    什么是IAP? IAP(In-Application Programming) 指MCU可以在系统中获取新代码并对自己重新编程,即可用程序来改变程序。在应用编程(IAP)是用户的应用代码对片内Flash存储器进行擦除/编程的方法。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就

    2024年02月07日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包