STM32f103c8t6 IAP在线升级
设计思路:(自己理解的哈,如果有问题,欢迎大家提出来,一起学习哈)
首先程序每次执行都会从基地址0x0800 0000开始执行。IAP程序升级最重要的就是写BOOTLOADER程序,进行引导升级,加载,跳转app程序。每次上电后进入bootloader判断是否升级如果需要升级,就就收bin文件进行升级,如果不升级直接跳入原app程序执行。
bootloader和app程序的FLASH大小根据实际情况自己确定分配就可以了
下面是我自己画得一个流程图:主要介绍整个大的流程
bin文件的生成方法可以百度一下,网上很多的
代码:(我是根据正点原子的例程改的,代码只贴了重要部分,如果有需要的可以留言。因为注释会乱码,所以我把注释删了)
bootloader.c:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "stmflash.h"
#include "iap.h"
iapfun jump2app;
u16 iapbuf[1024];
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;
iapbuf[i++]=temp;
if(i==1024)
{
i=0;
STMFLASH_Write(fwaddr,iapbuf,1024);
fwaddr+=2048;
}
}
if(i)STMFLASH_Write(fwaddr,iapbuf,i);
}
void iap_load_app(u32 appxaddr)
{
if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)
{
__set_MSP(*(vu32*)appxaddr);
jump2app=(iapfun)*(vu32*)(appxaddr+4);
jump2app();
}
}
bootloader.h:
#ifndef __IAP_H__
#define __IAP_H__
#include "sys.h"
typedef void (*iapfun)(void);
#define FLASH_APP1_ADDR 0x08005000
void iap_load_app(u32 appxaddr);
void iap_load_appsram(u32 appxaddr);
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen);
#endif
main函数:
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "stmflash.h"
#include "iap.h"
int main(void)
{
u8 key;
u16 oldcount=0;
u16 applenth=0;
SystemInit();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
delay_init();
LED_Init();
KEY_Init();
printf("readyn");
while(1)
{
GPIO_SetBits(GPIOC,GPIO_Pin_13);
delay_ms(500);
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
delay_ms(500);
if(USART_RX_CNT)
{
if(oldcount==USART_RX_CNT)
{
applenth=USART_RX_CNT;
oldcount=0;
USART_RX_CNT=0;
printf("用户程序接收完成!rn");
printf("代码长度:%dBytesrn",applenth);
}
else
oldcount=USART_RX_CNT;
}
key=KEY_Scan(0);
if(key==WKUP_PRES)
{
if(applenth)
{
printf("开始更新固件库...rn");
if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)
{
iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);
printf("固件更新完成!rn");
}
else
{
printf("非FLASH应用程序!rn");
}
}
else
{
printf("没有可以更新的固件!rn");
}
}
if(key==KEY2_PRES)
{
if(applenth)
{
printf("固件清除完成!rn");
applenth=0;
}
else
{
printf("没有可以清除的固件!rn");
}
}
if(key==KEY1_PRES)
{
printf("开始执行FLASH!!rn");
if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)
{
__set_PRIMASK(1);
iap_load_app(FLASH_APP1_ADDR);
}
else
{
printf("非FLASH应用程序,无法执行!rn");
}
}
}
}
STM32f103c8t6 IAP在线升级
设计思路:(自己理解的哈,如果有问题,欢迎大家提出来,一起学习哈)
首先程序每次执行都会从基地址0x0800 0000开始执行。IAP程序升级最重要的就是写BOOTLOADER程序,进行引导升级,加载,跳转app程序。每次上电后进入bootloader判断是否升级如果需要升级,就就收bin文件进行升级,如果不升级直接跳入原app程序执行。
bootloader和app程序的FLASH大小根据实际情况自己确定分配就可以了
下面是我自己画得一个流程图:主要介绍整个大的流程
bin文件的生成方法可以百度一下,网上很多的
代码:(我是根据正点原子的例程改的,代码只贴了重要部分,如果有需要的可以留言。因为注释会乱码,所以我把注释删了)
bootloader.c:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "stmflash.h"
#include "iap.h"
iapfun jump2app;
u16 iapbuf[1024];
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;
iapbuf[i++]=temp;
if(i==1024)
{
i=0;
STMFLASH_Write(fwaddr,iapbuf,1024);
fwaddr+=2048;
}
}
if(i)STMFLASH_Write(fwaddr,iapbuf,i);
}
void iap_load_app(u32 appxaddr)
{
if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)
{
__set_MSP(*(vu32*)appxaddr);
jump2app=(iapfun)*(vu32*)(appxaddr+4);
jump2app();
}
}
bootloader.h:
#ifndef __IAP_H__
#define __IAP_H__
#include "sys.h"
typedef void (*iapfun)(void);
#define FLASH_APP1_ADDR 0x08005000
void iap_load_app(u32 appxaddr);
void iap_load_appsram(u32 appxaddr);
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen);
#endif
main函数:
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "stmflash.h"
#include "iap.h"
int main(void)
{
u8 key;
u16 oldcount=0;
u16 applenth=0;
SystemInit();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
delay_init();
LED_Init();
KEY_Init();
printf("readyn");
while(1)
{
GPIO_SetBits(GPIOC,GPIO_Pin_13);
delay_ms(500);
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
delay_ms(500);
if(USART_RX_CNT)
{
if(oldcount==USART_RX_CNT)
{
applenth=USART_RX_CNT;
oldcount=0;
USART_RX_CNT=0;
printf("用户程序接收完成!rn");
printf("代码长度:%dBytesrn",applenth);
}
else
oldcount=USART_RX_CNT;
}
key=KEY_Scan(0);
if(key==WKUP_PRES)
{
if(applenth)
{
printf("开始更新固件库...rn");
if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)
{
iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);
printf("固件更新完成!rn");
}
else
{
printf("非FLASH应用程序!rn");
}
}
else
{
printf("没有可以更新的固件!rn");
}
}
if(key==KEY2_PRES)
{
if(applenth)
{
printf("固件清除完成!rn");
applenth=0;
}
else
{
printf("没有可以清除的固件!rn");
}
}
if(key==KEY1_PRES)
{
printf("开始执行FLASH!!rn");
if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)
{
__set_PRIMASK(1);
iap_load_app(FLASH_APP1_ADDR);
}
else
{
printf("非FLASH应用程序,无法执行!rn");
}
}
}
}
举报