历史上的今天
今天是:2025年01月07日(星期二)
2019年01月07日 | STM32F103C8T6在线升级 IAP
2019-01-07 来源:eefocus
stm32程序每次执行都会从基地址0x800 0000开始执行。IAP程序升级的执行是在bootloader引导文件执行后,进行加载、跳转APP程序。所以每次上电后进入BootLoader判断是否需要升级,如果升级则接受bin文件,如果不升级则直接跳转app程序。
BootLoader和app程序的FLASH大小需要根据自己的程序情况自由的分配大小就可以了。
代码:根据正点原子的例程进行修改的
1、由于BootLoader引导程序比较小,我设置的flash大小为0x1800

2、iap函数:由于STM32F103C8T6程序存储容量是64KB,每页的大小为1K字节即1024,所以iapbuf数组设置为512。
代码如下:
#include "stmflash.h"
#include "iap.h"
iapfun jump2app;
u16 iapbuf[512];
//appxaddr:应用程序的起始地址
//appbuf:应用程序CODE.
//appsize:应用程序大小(字节).
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
{
u16 t;
u16 i=0;
u16 temp;
u32 fwaddr=appxaddr;//当前写入的地址
u8 *dfu=appbuf;
for(t=0;t { temp=(u16)dfu[1]<<8; temp+=(u16)dfu[0]; dfu+=2;//偏移2个字节 iapbuf[i++]=temp; if(i==512) { i=0; STMFLASH_Write(fwaddr,iapbuf,512); fwaddr+=1024;//偏移1024 } } if(i) STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去. } //跳转到应用程序段 //appxaddr:用户代码起始地址. void iap_load_app(u32 appxaddr) { if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法. { jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址) MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) jump2app(); //跳转到APP. } } 3、BootLoader函数 : 首先判断app代码的首地址是否为0x0800 000,是则进入app,否的话进行引导区。 判断app代码栈顶是否为0x2000 000,不是则进入升级模式,代码如下,其中FLASH_APP1_ADDR=0x8001800 while(1) { if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX. { iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码 } if((((*(vu32*)FLASH_APP1_ADDR)&0x2FFE0000)!=0x20000000)) { printf("/***** No APP! *****/ \r\n"); printf("stm32f103c8t6在线升级 \r\n"); printf("选择对应的app bin文件 \r\n"); printf("输入 A 发送bin文件 \r\n"); printf("输入 E 进入app \r\n"); while(1) { if(USART_RX_CNT) { if(oldcount==USART_RX_CNT)//新周期内,没有收到任何数据,认为本次数据接收完成. { applenth=USART_RX_CNT; oldcount=0; USART_RX_CNT=0; if(applenth > 100) { printf("用户程序接收完成!\r\n"); printf("代码长度:%dBytes\r\n",applenth); } } else oldcount=USART_RX_CNT; } delay_ms(10); if(USART_RX_BUF[0] == 'A') { if(applenth) printf("\r\n 请发送bin文件 \r\n"); app_bin = 1; applenth=0; } else if(app_bin) { if(applenth) { printf("开始更新固件...\r\n"); printf("Copying APP2FLASH..."); if(((*(vu32*)(0X20000400+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX. { iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码 printf("Copy APP Successed!!"); printf("固件更新完成!\r\n"); applenth = 0; app_bin = 0; } } } if(USART_RX_BUF[0] == 'E') { if(applenth) printf("\r\n 将要执行APP \r\n"); app_enter = 1; applenth = 0; } if(app_enter) { printf("开始执行FLASH用户代码!!\r\n"); if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX. { iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码 }else { printf("非FLASH应用程序,无法执行!\r\n"); printf("Illegal FLASH APP!"); } } } } } 4、bootloader下进去之后,后面该是app程序了。 5、app程序就比较简单了,首先设置flash向量便宜地址0x1800 其次配置程序的启动地址 6、编译后keil下载程序就可以了,或者通过串口按照自己编写的步骤进行下载。 发送 A 提示 请发送bin文件 下面以次打开选择bin文件并发送,会打印出接收的字节数跟更新固件 最好发送E,会有开始执行提示。或者单片机直接复位也可以直接执行app,到此app在线升级完成。






史海拾趣
|
海地地震中 我的亲身经历证明中国的设备最抗震 (转载自新浪博客—海地通讯日记) 距离海地地震已经9天了,在这9天里,我经历了无数次余震,也通过网络深深感受到祖国的关怀。但是由于忙于抢修和维护通讯设备,所以一直没有时间来和大 ...… 查看全部问答> |
|
1.网上经常看到有人说设三极管的直流放大系数为多少多少 怎么直流放大系数还能自己设置的?不是固定的吗? 2.三极管数据手册上的hfe怎么会有最大最小值?我要取值的话 该取多大的hfe? 望各位兄弟进来探讨探讨 &nb ...… 查看全部问答> |
|
我很久前买了个44B0开发板,没怎么动,现在拿出来玩玩。 想请教一个简单的问题,我想把ADS生成的HEX文件烧写FLASH后,重新启动,能够让程序跳转到SDRAM里运行,跟设置RO BASE 和RW BASE 有关系吗?怎么去实现FLASH程序到SDRAM的跳转?我运行的是跑 ...… 查看全部问答> |
|
我们的设备驱动是用windriver写的,在没有安装过windriver的机器上发布的话要用其提供的wdreg这个工具来安装windriver核心的驱动以及设备的驱动。 可是在XP下,设备连上PC后,设备管理器中显示是USB mass storage,这时如果用wdreg装驱动的话是装不 ...… 查看全部问答> |
|
我在不同的网站上下载了quartus10.0 和11.0版本,安装时点击setup.exe后一点反应也没!!防火墙也关过,也试过以管理员省份运行都是一样的效果!!! 那位朋友知道这是咋回事 ???/… 查看全部问答> |
|
关于竹林的记忆都是美好而鲜活的,午后光线在竹子之间穿梭,微风轻掠带来沙沙竹叶声,还能看到斑驳光影在闪烁摇动跳舞,此刻感觉宛如看到时光畅游,与大自然一同自由呼吸,竹丝坚韧柔软。全身上下散发着大自然的亲和力。设计师为了把这种自然的美妙 ...… 查看全部问答> |
|
c8051F340怎么接收一串数据?数据由PC上的串口助手发送,波特率19200 我的串口接收中断函数如下,8个字节的数据,一个一个的发,接收正常,但是8个数据一次全发给单片机,接收到数据就错了,要正常一次接收8字节该怎么整呢? ...… 查看全部问答> |




