1、理论分析
理论依据很重要,这里稍微介绍一下原理和数据的操作过程。实际实现U盘的IAP升级一共分为两个部分,一部分是bootloader程序,这部分需要使用烧录器或者串口烧写进芯片。另一部分是用户的APP程序,这部分是真正的设备需要执行的程序。实际操作过程就是芯片连接U盘后从U盘读取一部分bin文件的数据到RAM再写入到芯片的flash用户app区,然后循环这个写入过程直到将整个bin文件写入到芯片flash中。然后执行一条指令跳转到用户app程序区开始执行。另外用户app区执行时在systemInit初始化完成后需要将中断表偏移一个地址。实现U盘升级程序需要移植两部分代码,一个是U盘驱动代码,一个是FAT文件系统代码。同时将U盘格式化为FAT32格式,4k对齐。
2、bootloader关键代码
bootloader部分的关键代码如下,U盘的状态机和读取文件并写入到芯片flash的过程。IAP部分代码参考了原子哥的串口IAP代码,但发现直接使用跳转时无法执行。经过测试跳转之前必须要增加__ASM(“CPSID I”);这句关闭中断。但是很奇怪我曾经做过一个串口IAP的bootloader,不加这句是完全没问题的。这个很是让人费解啊。

//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
{if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)  //检查栈顶地址是否合法.{ __ASM("CPSID I");jump2app=(iapfun)*(vu32*)(appxaddr+4);      //用户代码区第二个字为程序开始地址(复位地址)                    __set_MSP(*(__IO uint32_t*) appxaddr);//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)jump2app();                                   //跳转到APP.}
}   int USBH_USR_Application(void)
{UINT Len = 0;u16 FramesLen = 0;//最后帧长度char FilePath[] = "0:/PROGRAM.bin";if(HCD_IsDeviceConnected(&USB_OTG_Core) != 0)//判断U盘连接{switch(UDiskState){case FileSysInit:    //文件系统初始化{if(f_mount(&fatfs, "", 0)!=FR_OK)//判断是否挂载{return 1;}UDiskState = OpenFile;break;}case OpenFile:      //打开文件{f_mount(&fatfs, "", 0);//挂载if(f_open(&file,FilePath,FA_OPEN_EXISTING|FA_READ) != FR_OK )//打开文件,如果不存在则失败{f_close(&file);      //关闭文件f_mount(NULL, "", 0);   //卸载USBDiskSig = USBDiskBreak;RunNumber = 0;return 1;}USBDiskSig = USBDiskLink;//U盘已连接,确认能够打开文件以后才认为U盘有效连接FileSize = f_size(&file);//获取文件大小WriteInteger = FileSize/WriteUSBLen;WriteRemSIG = FileSize%WriteUSBLen;Write_Count = 0;//清空次数UDiskState = UDiskWriteData;break;}case UDiskWriteData://读取数据并执行IAP{if((WriteInteger > 0)&&(Write_Count < WriteInteger)){if(f_read(&file,FileReadBuf,WriteUSBLen,&Len) != FR_OK)//读取指定长度的数据到RAM{f_close(&file);f_mount(NULL, "", 0);USBDiskSig = USBDiskBreak;RunNumber = 0;return 1;}iap_write_appbin(((WriteUSBLen*Write_Count)+FLASH_APP1_ADDR),FileReadBuf,WriteUSBLen);//更新FLASH代码Write_Count++;}else{if(WriteRemSIG != 0)//有剩余数据{FramesLen = FileSize-(Write_Count*WriteUSBLen);//得到最后一次写入的长度if(f_read(&file,FileReadBuf,FramesLen,&Len) != FR_OK)//读取指定长度的数据到RAM{f_close(&file);f_mount(NULL, "", 0);USBDiskSig = USBDiskBreak;RunNumber = 0;return 1;}iap_write_appbin(((WriteUSBLen*Write_Count)+FLASH_APP1_ADDR),FileReadBuf,FramesLen);//更新FLASH代码}f_close(&file);//关闭文件f_mount(NULL, "", 0);//断开连接Write_Count = 0;UDiskState = FileSysInit;if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.{
//                        RCC_DeInit();//关闭外设
//                        __set_PRIMASK(1); //关闭总中断iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码}else //非FLASH应用程序,无法执行!{USBDiskSig = USBDiskBreak;RunNumber = 0;}}}default:break;}}else{f_close(&file);f_mount(NULL, "", 0);return 1;}return 0;
}

3、用户APP程序关键代码
此部分是用户APP的初始化代码,代码中必须要添加中断向量表偏移和打开中断。偏移量需要根据自己定义的用户APP地址修改。本人程序使用IAR编译器编译,所以用户APP程序配置如下图:

void ALL_Init(void)
{SystemInit();  //系统时钟源配置 NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x6400);//设置中断向量表偏移__ASM("CPSIE I");//打开中断ChipDeInit();//芯片外设复位NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
}

实际这里配置就是修改了stm32f105xC.icf文件中的以下部分:

/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08006400;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08006400;
define symbol __ICFEDIT_region_ROM_end__   = 0x0803FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x2000FFFF;

整个程序的源码在我的资源中可以找到地址如下。
https://download.csdn.net/download/u010552215/12016457

STM32F105实现U盘IAP升级程序相关推荐

  1. 完成MSP430的IAP升级程序(总结)

    这几天测试写好的IAP升级程序,真是一个糟,能将程序下载进去,但无法运行. 经过各种测试,修改终于找到了问题的原因,现在大致总结下我在写IAP程序的时候 遇到的问题和解决方案.首先要实现单片机的IAP ...

  2. stm32 模拟U盘IAP升级 与 FAT16文件系统

    如果用的MCU有USB接口,那么使用模拟U盘升级程序,不失为一个好办法,因为 第1,模拟U盘,不需要驱动,也不需要上位机,现场操作非常方便, 第2,USB传输速度快,升级过程耗时少,且可靠. 这项技术 ...

  3. 基于STM32的IAP升级程序

    基于STM32的IAP升级程序 IAP介绍 功能设计 硬件设计 软件设计 软件设计流程如下 完整程序 具体实现 设计功能程序 IAP实现程序 主程序 后续 IAP介绍 IAP(In Applicati ...

  4. STM32F103 通过SD卡IAP升级程序,带MD5校验,(带源码)可在实际项目中使用

    一.将APP程序从SD卡搬运到MCU中 首先从sd卡通过FAFTS文件操作系统打开程序文件,然后记录下复制开始地址和程序文件大小 fileOperionResult = f_open(&upd ...

  5. 电子产品如何使用IAP方式升级程序

    目录 1.ICP.ISP和IAP的概念 2.IAP升级程序的原理 3.IAP升级程序的流程 4.IAR环境下IAP的实现 4.1.BootLoader程序设计 4.2.User Application ...

  6. 关于STM32单片机IAP升级中if(((*(__IO uint32_t*)ulAddr_App) 0x2FFE0000) == 0x20000000)语句的理解

    没有标题 初见if(((*(__IO uint32_t*)ulAddr_App) & 0x2FFE0000) == 0x20000000) 语句理解 语句功能 为什么ulAddr_App里存的 ...

  7. 现场升级方案:LPC1788采用U盘方式进行程序IAP升级功能的实现

    现场升级方案:LPC1788采用U盘方式进行程序IAP升级功能的实现 闲来无事,总结一下前段时间做过的U盘升级项目.一个新手的成长之路在于善于总结,生活也是一样扯远了,我准备了两个软件环境,一个带操作 ...

  8. RT-thread应用讲解——通过U盘升级程序固件

    RT-thread应用讲解--通过U盘升级程序固件 目录 RT-thread应用讲解--通过U盘升级程序固件 前言 一.挂载U盘 二.使能OTA 三.U盘升级代码 四.运行测试 五.结束语 前言 我前 ...

  9. 21.国民技术N32G45X例程之-U盘模式IAP升级固件

    21.国民技术N32G45X例程之-U盘模式IAP升级固件 文章目录 前言 一.准备工作 1.国民技术N32G45X提供的库 2.下载本作者原创BIN文件合成软件 3.为什么要合成BIN文件? 二.U ...

最新文章

  1. Yii2 中cookie的用法(2)
  2. poj1236-Tarjan算法
  3. RSA攻击手法及相应例题解析
  4. 血管分割技术文献综述
  5. 写给小白的Python之006:数据类型之列表
  6. Please use torch.load with map_location=torch.device(‘cpu‘),If you are running on a CPU-only machine
  7. oracle归档切换,oracle 切换归档方式
  8. matlab怎么画map图,用MATLAB自带的worldmap及相关函数画地图
  9. 改命术:怎么赚50万以上的问题
  10. 形参和实参的储存单元是否一致?
  11. 【English】十大词性之感叹词(感叹句)
  12. Ubuntu18.04录屏并生成gif图片
  13. 逻辑回归分类器(linear_model.LogisticRegression)
  14. 华为路由器和交换机的简单命令
  15. swift新手进阶30天一 自定义上图片下文字的UIButton的几种方式
  16. cmd的发送 mmc_mmc/sd 卡介绍
  17. Teamcenter之RCP的简单创建与运行
  18. 《数据结构》(一)时间复杂度和空间复杂度(超硬核八千字)
  19. 微信手气红包算法 php,PHP实现微信/QQ手气红包,随机算法分享
  20. 好用的录音转文字方法

热门文章

  1. 龙岗区-横岗188工业区城市更新旧改,基本拆除平整
  2. 数字城市网络安全指数白皮书 附下载
  3. 注册机原理(x64dbg)
  4. 计算机组成原理之CPU的构造和原理
  5. ISO9001认证周期是多久?
  6. 记录unity视频选择与播放_IOSAndroid
  7. 【调试笔记】韦东山:在100ask_imx6ull上移植使用六轴传感器ICM20608
  8. 搜狗输入法遇到生僻字的一些用法
  9. RTSP直播延时的深度优化
  10. Potato靶机测试