一、芯片选择
STM32F103RCT6
FLASH容量:512K
RAM容量:48K
二、升级方式选择:
串口升级、网口升级、4G升级、SD卡升级等等。
1、SD卡升级属于升级文件事先存储在外部FLASH,不需要考虑获取升级文件的代码和升级文件存放的位置,直接读取升级即可。
2、串口升级、网口升级需要考虑升级文件的代码和升级文件存放的位置。
升级文件存放的位置有三种选择:
片内FLASH:在保证BootLoader程序和用户APP程序空间的情况下,将其防止在片内FLASH的开头的nK空间或结束的nK空间。
内部SRAM:但STM32F103RCT6的内部SRAM空间大小只有48K,只能存放不超过48K的代码。
电路上增加外部FLASH:将获取到的升级文件存储到外部flash,然后再从外部flash读取升级文件到用户APP区域。
三、程序分区:
确定好芯片和升级方式之后要对Bootloader程序和用户APP程序进行分区。
STM32内部FLASH起始地址为:0x8000000。
0X0800 0000~0x0800 8000,共32K字节,存放BootLoader程序。
0x0800 8000之后的128K空间,存放用户的APP程序。
四、代码接收与存储
以接收到内部SRAM为例,定义一个41K的串口接收存储数组
u8 USART_RX_BUF[41*1024] __attribute__ ((at(0X20001000)));
//接收缓冲,最大41*1024个字节,起始地址为0X20001000.
//在串口1接收中断中接收大小不超过41K的升级文件
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
if(USART_RX_CNT<USART_REC_LEN)
{
USART_RX_BUF[USART_RX_CNT]=Res;
USART_RX_CNT++;
}
}
}
五、代码更新
//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<appsize;t+=2)
{
temp=(u16)dfu[1]<<8;
temp+=(u16)dfu[0];
dfu+=2;//偏移2个字节
iapbuf[i++]=temp;
if(i==1024)
{
i=0;
STMFLASH_Write(fwaddr,iapbuf,1024);
fwaddr+=2048;//偏移2048 16=2*8.所以要乘以2.
}
}
if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.
}
六、跳转到用户APP程序区
//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
{
if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.
{
jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
jump2app(); //跳转到APP.
}
}