我使用STM32F103VET6进行IAP升级。
现在将512K的flash划分为以下四个区域:
0x8000000——0x800B400的45K为bootloader区,存放IAP升级程序。
0x800B400——0x8030C00的150K为APP1区,存放第一个app程序。
0x8030C00——0x8056400的150K为APP2区,存放第二个app程序。
0x8056400往后的区域为IAP升级标志区,存放IAP升级标志。
app程序中使用了ucos操作系统和STemwinGUI。
我遇到的问题是,同一个app程序烧录在APP1区和APP2区后,STemwin的图片显示函数:"GUI_DrawBitmap()"显示图片的速度不一样。APP1区的显示速度很快,但APP2区的显示速度就变得很慢,通常刷一张图片要730ms左右。而且经过我的测试,APP2在flash的烧录位置越靠后,这个刷图函数就越慢。
在app程序中除了这个刷图慢的问题外其他功能都正常。
可以确保正常的app程序中配置没问题,应为已经测试过了。两个APP程序的唯一区别就是在main函数开头是用了SCB->VTOR = FLASH_BASE | 0xB400;来偏移中断向量表。
如果不使用IAP升级,把APP程序从0x8000000地址开始烧,APP程序就正常运行STemwin也没有任何问题。
想问一下大家有没有遇到过类似的问题或者能帮我提供一些解决思路,谢谢
以下是IAP的升级函数
void app_updata (uint16_t app_**) {//传参为APP固件上次烧写标志
u16 j=0;
u16 temp;
uint16_t app_num = 0;
u32 fwaddr = FLASH_APP1_ADDR;//当前写入的地址
u16 u;
int i = 0;
char pathbuf[30];
if (app_** == APP_1) { //上次从一区起的,这次烧二区
fwaddr = FLASH_APP2_ADDR;
strcpy(pathbuf, APP2_NAME);
}
else if (app_** == APP_2) { //上次从二区起的,这次烧一区
fwaddr = FLASH_APP1_ADDR;
strcpy(pathbuf, APP1_NAME);
}
mount_flash();
res_flash = f_open(&fnew, pathbuf, FA_OPEN_EXISTING | FA_READ );//打开外部flash中的固件
if (res_flash == FR_NO_FILE) {
if (app_** == APP_1) {
printf("无固件升级包,跳转到APP一区执行\r\n");
iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码
}
else {
printf("无固件升级包,跳转到APP二区执行\r\n");
iap_load_app(FLASH_APP2_ADDR);//执行FLASH APP代码
}
}
else if (res_flash == FR_OK) {
recordsize = f_size(&fnew);
app_num = recordsize / READ_SIZE;
if (recordsize != 0) {
printf( "打开固件%s成功,字节数为:%ld\r\n", pathbuf, recordsize);
printf ("准备开始固件升级!\r\n");
for (i = 0; i < app_num; i++) { //读固件数据
res_flash = f_lseek(&fnew, i * READ_SIZE);
memset(app_buf, 0, READ_SIZE);
res_flash = f_read(&fnew, app_buf, READ_SIZE, &fnum);
u8 *dfu = app_buf;
for(u = 0; u < READ_SIZE; u += 2)
{
temp = (u16)dfu[1] << 8;
temp += (u16)dfu[0];
dfu += 2;//偏移2个字节
iapbuf[j++] = temp;
if(j == 1024)
{
j = 0;
STMFLASH_Write(fwaddr, iapbuf, 1024);
fwaddr += 2048;//偏移2048 16=2*8.所以要乘以2.
}
}
printf("固件升级中:读到%d字节,还剩%ld字节\r\n", READ_SIZE, (recordsize - (i + 1) * READ_SIZE));
}
//读剩余的不满1024的字节
res_flash = f_lseek(&fnew, app_num * READ_SIZE);
memset(app_buf, 0, READ_SIZE);
res_flash = f_read(&fnew, app_buf, recordsize % READ_SIZE, &fnum);
u8 *dfu = app_buf;
for(u = 0; u < recordsize % READ_SIZE; u += 2)
{
temp = (u16)dfu[1] << 8;
temp += (u16)dfu[0];
dfu += 2;//偏移2个字节
iapbuf[j++] = temp;
}
STMFLASH_Write(fwaddr, iapbuf, j);
printf ("最后读到%ld字节\r\n", recordsize % READ_SIZE);
if (app_** == APP_1)
f_unlink("0:/iCasa_multimeter_2.bin"); //删除固件包
else f_unlink("0:/iCasa_multimeter_1.bin");
// unmount_flash();
f_close(&fnew);
beep_en(); //蜂鸣器响一声代表固件升级完成
delay_ms(100);
beep_dis();
if (app_** == APP_1) {
Test_Write(FLASH_BAK_ADDR, APP_2); //往flash写入标志,表示当前写入的是那个APP区
printf("固件升级完成,准备跳转至APP二程序!\r\n");
iap_load_app(FLASH_APP2_ADDR);//执行FLASH APP代码
}
else {
Test_Write(FLASH_BAK_ADDR, APP_1); //往flash写入标志,表示当前写入的是那个APP区
printf("固件升级完成,准备跳转至APP一程序!\r\n");
iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码
}
}
else { //打开文件为空
if (app_** == APP_1) {
printf("固件包为空,跳转到APP一区执行\r\n");
iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码
}
else {
printf("固件包为空,跳转到APP二区执行\r\n");
iap_load_app(FLASH_APP2_ADDR);//执行FLASH APP代码
}
}
} //f_open出错
else
printf("打开固件包失败");
}
|