一,技术概要
bootloader如果实现自升级网上已经有很多资料,这里不再做过多描述,这里主要记录STM32F105VCTdemo版,利用USB接口Host实现升级文件读取,然后实现自升级功能。
二,IAP MX配置
1:
2:
3:配置时钟,demo使用的是8M外部晶振。
4:选择调试口模式,配置tick
5:配饰串口通信,波特率115200
6:配置USB接口
7:配置FATFs
配置注意事项:
1)CODE PAGE (Code page on...Simplified Chinese GBK)选择支持中文目录
2)USE LFN (Use Long Filename) 如果配置Disabled,读写文件名称不超过6个字符,这样生成的执行文件非常小,不超过20K,如果选择支持长文件名,执行文件将达到200K,这里可以根据需求自己选择。
8:USB—HOST配置
9:时钟配置
10:工程配置
11:代码生成
注意:不会自动生成flash_if.c相关函数,需要手动去ST库去拷贝。
12:添加关键代码
重要点:
1)配置APP跳转地址#define APPLICATION_ADDRESS (uint32_t)0x0800C000
2)升级文件放置U盘根目录下APP.bin,以bin文件格式存储。
uint32_t Len = 0xFF;
uint16_t FramesLen = 0;//最后帧长度
char FilePath[] = "0:/APP.bin";
// char FilePath[] = "0:/USBHost.bin";
switch(UDiskState)
{
case FileSysInit: //文件系统初始化
{
if(f_mount(&USBFatFs_iap, "", 1)!=FR_OK)//判断是否挂载
{
return ;
}
UDiskState = OpenFile;
break;
}
case OpenFile: //打开文件
{
// f_mount(&USBFatFs_iap, "", 0);//挂载
if(f_open(&MyFile_iap,FilePath,FA_OPEN_EXISTING|FA_READ) != FR_OK )//打开文件,如果不存在则失败
{
f_close(&MyFile_iap); //关闭文件
f_mount(NULL, "", 0); //卸载
return ;
}
FileSize = f_size(&MyFile_iap);//获取文件大小
WriteInteger = FileSize/WriteUSBLen;
WriteRemSIG = FileSize%WriteUSBLen;
Write_Count = 0;//清空次数
UDiskState = FlashEraseData;
break;
}
case FlashEraseData:
{
Flash_IfErase(FLASH_APP1_ADDR,FileSize);
UDiskState = UDiskWriteData;
break;
}
case UDiskWriteData://读取数据并执行IAP
{
if((WriteInteger > 0)&&(Write_Count < WriteInteger))
{
if(f_read(&MyFile_iap,FileReadBuf,WriteUSBLen,&Len) != FR_OK)//读取指定长度的数据到RAM
{
f_close(&MyFile_iap);
f_mount(NULL, "", 0);
return ;
}
FLASH_If_Write(((WriteUSBLen*Write_Count)+FLASH_APP1_ADDR),( uint32_t*)FileReadBuf,WriteUSBLen/4);//更新FLASH代码
Write_Count++;
}else
{
if(WriteRemSIG != 0)//有剩余数据
{
FramesLen = FileSize-(Write_Count*WriteUSBLen);//得到最后一次写入的长度
if(f_read(&MyFile_iap,FileReadBuf,FramesLen,&Len) != FR_OK)//读取指定长度的数据到RAM
{
f_close(&MyFile_iap);
f_mount(NULL, "", 0);
return ;
}
FLASH_If_Write(((WriteUSBLen*Write_Count)+FLASH_APP1_ADDR),( uint32_t*)FileReadBuf,FramesLen/4);//更新FLASH代码
}
f_close(&MyFile_iap);//关闭文件
f_mount(NULL, "", 0);//断开连接
Write_Count = 0;
UDiskState = FileSysInit;
FLASH_If_Erase(UPGRADE_FLAG_ADDRESS);/*clear app update flag*/
//if(((*(__IO uint32_t*)(UPGRADE_FLAG_ADDRESS)))==0x08000000)
App_Jump();//执行FLASH APP代码
}
}
default:break;
}
三 APPdemo程序
跟IAP工程一样的配置方法,不同点:
1:APP rom地址偏移量要跟IAP跳转地址一样,注意:如果自己不实现printf函数采用库方式实现打印一定要勾选Use Micro LIB。
2:代码中修改偏移地址。
3:编译完成后需要把HEX文件转换成BIN文件,网上工具非常多。
四 流程展示
上电直接读取U盘APP.bin文件,一次读取256byte,然后依次写入APP区域,直到bin文件写完,完成后直接跳转到APP区域执行APP程序。
五:问题
1:调试:
烧录完IAP+APP后需要调试时,下载程序的范围需要设置。
2:跳转
IAP后再跳转到APP无法启动有几种情况:
RCC初始化问题:
tick时钟问题