什么是IAP
IAP( In Application Programming)即在应用编程,可以让用户使用自己的程序对MCU的中的运行程序进行更新,而无需借助于外部烧写器。
正常情况下,我们通过烧录器将程序烧录在起始位置为0x0800 0000的flash中,芯片中只有一个程序。而要实现IAP的功能,芯片中需要存储至少两个程序,第一个bootloader程序(起始位置依旧为0x0800 0000),通过该程序进行跳转主程序app。
实验介绍
IAP升级程序,可以在bootloaer接收新程序,也可以在主程序中接收,各有优缺。本次实验,采用的是bootloader中接收,接收前,擦除主程序位置的数据,然后将接收到的数据依次重新写入~~。
flash的内存分配:
bootloader :0x0800 0000--0x0800 1FFF
主程序:0x0800 2000--
本次时之前网上下载的,有配套的上位机,正好可以使用,所以就移植过来。
一些需要大致了解的基础
- 芯片flash如何擦除写入,GD32对应的是FMC(可以参考我前一篇报告https://aijishu.com/a/1060000...)
2.中断向量表
我了解的比较粗糙,具体可以去搜索引擎查找。
大概的意思就是MCU内的各个中断存储的位置。单片机启动后,会在中断向量表中读取各个中断的位置,然后才能正常调用, 中断向量表的存储位置为:0x08000004
使用bootloader跳转到主程序后,如果要正常运行,必须重新设置中断向量表的偏移。我们这个程序偏移了0x2000。
使用的函数:nvic_vector_table_set( NVIC_VECTTAB_FLASH , 0x2000); //设置中断向量表偏移
3.如何实现程序跳转
这个我讲不清楚,具体就看代码吧,抄来就能用的
- 中断的关闭和开启
bootloader在跳转到主程序前,需要先关闭总中断。
主程序开始前,需要重新开启总中断。同时bootloader中用到的中断最好deinit()一下,再重新init(),避免出错。
__set_PRIMASK(0); //开启所有中断
__set_PRIMASK(1);//关闭所有中断
实验过程
1.烧录bootloader程序
2.对主程序进行改造,使得程序可以正常运行。
2.1 设置中断向量偏移和重新开启总中断
注意:必须写在int main(){}函数内的前两行,如下图
2.2 在魔术棒中设置一下偏移地址为0x0800 2000,这样烧录的程序不会覆盖掉前面的bootloader,生成的bin文件也起始地址也是在0x0800 2000。
2.3 设置生成bin文件
我的keil安装在D盘,请你根据自己的实际安装位置,重新设置一下路径。
`D:\Keil_v5\ARM\ARMCC\bin\fromelf.exe --bin --output=@L.bin !L`
3.重新编译一下主程序,可以改下串口的输出内容,作为升级前后的区分。
4.打开上位机,开始升级。
点击程序升级按钮,找到你生成的bin文件位置,选中后,按一下开发板上的Reset按键,程序就会自动开始升级。升级大致过程就是,上位机将bin文件拆分成N个包,然后通过串口发送到单片机,单片机接收并校验通过后,将数据写入flash。
实验现象
升级前,循环输出app1
升级后,循环输出app2
注意:升级完成后,也需要按一下Reset键
所有的代码请自行下载:
链接: https://pan.baidu.com/s/1n4BE...