IAP烧写和OTA程序跳转总结

IAP没接触的时候感觉挺高大上的,还有对flash也是模模糊糊,做完IAP例程后才知道好简单,下面总结下自己遇到的几个问题,分享给大家。

1.固定法则

1)设置APP程序的起始地址和存储空间大小

分配好,bootloader的的起始地址0x08000000(M3),size的大小,然后分配好APP的起始地址,size大小,注意分配的不要去重叠两个的空间。

2)设置中断向量表的偏移量

设置SCB->VTOR或者*((volatile uint32_t*) 0xE000ED08)

3)设置编译后运行fromelf.exe生成.bin文件

如何设置:
1.设置为 fromelf --bin -o “$L@L.bin” “#L” ,当然也可以使用上面那种绝对路径的方式,需要看指定fromelf文件的路径
在这里插入图片描述
2.输入D:\keil\ARM\ARMCC\bin\fromelf.exe --bin -o output\Project.bin output\Project.axf直接指定地址
在这里插入图片描述

4)如果bootloader里头有中断关闭它

				__disable_irq();建议先关闭中断在跳转,关闭之后千万要记得在APP函数中打开,不然可能会导致APP函数运行不下去的情况

5)判定栈顶地址

下面的图是我截取别人的,这句可加可不加,保险起见加上为好
在这里插入图片描述
直接上跳转代码:(拿去直接用)
千万记得,APP中要打开irq

void execute_firmware(uint32_t addr)
{
	USART1_DEBUG("execute_firmware\r\n");
	__disable_irq();
	if(((*(uint32_t*)addr)&0x2FFE0000)==0x20000000)
	{
		JumpAddress = *(uint32_t*) (addr);
		__set_MSP(JumpAddress);//把堆栈指针复位了,然后再跳转到APP。APP开始运行,APP也占有全部
		//RAM,它不用再关心IAP是否会占用堆栈或变量,因为IAP不会再运行了(当然可能有的RAM里面是还有数
		//据存在的,比如IAP中的变量和堆栈数据等,但APP运行时会重新初始化它自己的变量,不用关心之前的
		//数据是什么,同时堆栈的时候也会先入栈再出栈,先前的数据会被覆盖)
#ifdef __UART_EN__
			USART1_DEBUG("MSP_Address = 0x%x xxxx\r\n",JumpAddress);
#endif
		JumpAddress = *(uint32_t*) (addr + 4);
#ifdef __UART_EN__
			USART1_DEBUG("Jump_Address = 0x%x xxxx\r\n",JumpAddress);
#endif
		Jump_To_Application = (pFunction) JumpAddress;
		//Remap_Vector set the VTOR register
		*((volatile uint32_t*) 0xE000ED08) = addr;
		Jump_To_Application();
	}	
}

这边描述一下为什么if((((uint32_t)addr)&0x2FFE0000)==0x20000000)需要这一条?
答:这是为了保证app的数据执行是在0x20000000开始的,所以这句话的意思是保证app程序执行ram是有效的!
为什么是0x2FFE0000?
这是针对64K RAM的,保证ram在0x10000以内!

那为什么向量表地址是0xE000ED08?
这个可以在.s文件中查看,启动代码中有描述

讲一讲__set__MSP?
答:“__set_MSP”函数原型为:
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack);
该函数是ARM定义好的内核功能函数之一:设置主栈指针,该函数以存在于头文件(cmsis_armcc.h)的形式提供给各芯片厂商、IDE等使用(不是哪个芯片厂商或IDE特有的)。
简单说,一般需要包含形如“CMSIS\Include”的路径(针对多IDE环境可能导致包含交叉而找不到定义)。可以搜索相关路径(在mdk-arm中)找到cmsis_armcc.h所在的路径,然后明显的包含该路径即可。

2.编写bootloader时的坑

1.我在写入flash的时候犯了一个致命性的错误,就是没有调用flash读写接口,去直接用赋值的方法去写入可想而知,肯定失败。内部flash可以直接用解引用去读取,但是不能直接写入,要先擦除后,
在调用写接口写入。而外部的flash是有时序的,一般都需要接口去读写。

2.在读取地址里的数值的时候,只要地址里的数值有改动,就需要重新去读取

3.在OTA的时候,替换APP程序

这个时候就需要使用两个地址,然后进行OTA地址中数据的搬运,具体流程:在这里插入图片描述
流程就是:先读取OTA_Write_Address里的数据,copy到Application_write_Address地址里头,然后清除OTA_Write_Address地址里的数据,最后跳转执行Application_write_Address。
注意点:1.就是OTA_Write_Address里的数据是哪边来的
1)在APP应用程序中,接收数据,然后写入进去
2)在bootloader中接收数据写入,本例程就是直接在bootloader中接收串口数据直接写入到
OTA_Write_Address地址中,做实验用
2.注意数据的完整性,通常情况下要对接收到的数据进行校验比对,我写的例程中并未加
网页最上面是我的例程,芯片是GD32303

  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mhj258258

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值