一、知识点

  • 1、BootLoader就是单片机启动时候运行的一段小程序,这段程序负责单片机固件的更新,也就是单片机选择性的自己给自己下程序。可以更新,也可以不更新,更新的话,BootLoader更新完程序后,跳转到新程序运行;不更新的话,BootLoader直接跳转到原来的程序去运行。
  • 2、BootLoader更新完程序后并不擦除自己,下次启动后依然先运行BootLoader程序,又可以选择性的更新或者不更新程序,所以BootLoader就是用来管理单片机程序的更新。
  • 3、在实际的单片机工程项目中,如果加入了BootLoader功能,就可以给单片机日后升级程序留出一个接口,方便日后单片机程序更新。当然,这就需要创建两个工程项目,一个为BootLoader工程,一个为APP工程。
  • 4、BootLoader工程生成的.hex或者.bin文件通常下载到ROM或Flash中的首地址,这样可以保证上电后先运行BootLoader程序。而APP工程生成的.hex或者.bin文件则下载到ROM或Flash中BootLoader后面的地址中。也就是说,存在ROM/Flash中的内容是分为两部分的。
  • 5、要实现在同一个ROM/Flash中保存两段程序,并且保证不能相互覆盖,则需要在下载程序时指定地址。如在Keil下,可以进行如下的调整。

  • 6、实际上,在STM32系列的单片机中,Flash本身就是分扇区的,一个扇区16KB的样子,具体可以查看手册。那么就可以用从第一个扇区的首地址开始下载BootLoader的程序,而从第二个扇区的起始地址开始下载APP程序。如下为STM32F4系列芯片的Flash模块。

  • 7、单片机上电之后开始执行BootLoader程序,这是单片机会检测用户是否有升级应用程序(APP)的请求,具体表现有很多种,例如检测内存卡,Nand Flash中是否包含升级文件,串口/I2C/SPI等外设接口是否传来升级文件。据说还有使用GSM来升级的。
  • 8、所谓的升级,就是将ROM/Flash中存储APP程序的扇区内容擦除并写入新文件。例如一次固件升级的过程可以是:1、单片机上电执行BootLoader,2、BootLoader查找升级文件,3、若找到文件,擦除Flash中的部分扇区(存APP的),4、在擦除的扇区写入升级的文件,5、写入完成,读取数据检验是否出错,6、若数据一致,升级成功,删除升级文件,7、BootLoader程序跳转到APP程序执行。删除升级文件是为了下次上电后不再进行升级。
  • 9、所谓的跳转,可以理解程序指针的改变,变为指向APP程序扇区的起始地址。

二、部分代码

  • 1、主函数
int main(void)
{
HAL_Init();//STM32初始化
SystemClock_Config();//时钟配置
System_GPIOInit();//IO口配置 #ifdef BOOTLOAD_DISPLAY_ENABLE
SystemColorInit();//显示屏配置
#endif System_LoadUpdateFile();//升级函数
while (1)
{ }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 2、升级函数
void System_LoadUpdateFile(void)
{
uint8_t res;
if(bNandFlash_Error)//如果NandFlash错误,串口打印错误信息,跳转到用户程序
{
d_printf("NandFlash_Error jump\n");
BootLoad_Jump();//跳转函数
return;
}
if(bNo_FileSystem)//如果没有文件系统,串口打印错误信息,跳转到用户程序
{
d_printf("no file system jump\n");
BootLoad_Jump();//跳转函数
return;
}
if(f_open(&File, (char *)UPDATE_FILE_PATH, FA_READ)==FR_OK)//如果存在升级文件,开始执行升级
{
d_printf("update\n");
if(BootLoad_Program())//是否写入成功
{
f_close(&File);//关闭升级文件
res=f_unlink((char *)UPDATE_FILE_PATH);//删除升级文件
d_printfhex(res);d_printf("\n");
res=f_unlink((char *)UPDATE_DIR_PATH);//删除升级目录
d_printfhex(res);d_printf("\n"); BootLoad_Jump();//跳转函数
}
else
{
HAL_FLASH_Lock();//锁定Flash
d_printf("update fail\n");
f_close(&File);//关闭升级文件
BootLoad_Jump();//跳转函数
}
}
else
{
d_printf("jump\n");
f_close(&File);
BootLoad_Jump();
}
}
  • 3
  • 3、重写Flash函数
uint8_t BootLoad_Program(void)
{
uint32_t BaseAddress=APPLICATION_ADDRESS;//APP地址
uint32_t i,br,datacnt=0;
uint8_t data8;
GlobalPtr32=(uint32_t *)BootBuff;
HAL_FLASH_Unlock();//解锁Flash
if(BootLoad_Erase()==false)//擦除Flash
{
return false;
}
d_printf("size:");d_printfhex32(File.fsize);d_printf("\n");
while(1)
{
f_read(&File,BootBuff,8192,(void *)&br);//读取升级文件
for (i=0;i<(br>>2);i++)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, BaseAddress, GlobalPtr32[i]) == HAL_OK)//写入升级文件
{
BaseAddress = BaseAddress +4;
}
else
{
d_printf("program err\n");
return false;
}
}
datacnt+=br;
if(datacnt>=File.fsize)//写入完成
{
break;
}
}
d_printf("verify\n"); //验证Flash中的内容与升级文件是否一致
f_lseek(&File,0); //若一致代表升级成功
datacnt=0; //若不一致代表升级失败
BaseAddress=APPLICATION_ADDRESS;
while(1)
{
f_read(&File,BootBuff,8192,(void *)&br);
for (i=0;i<br;i++)
{
data8 = *(__IO uint8_t*)BaseAddress;
if (data8 != BootBuff[i])
{
d_printf("error!\n");
return false;
}
BaseAddress ++;
}
datacnt+=br;
if(datacnt>=File.fsize)
{
break;
}
}
HAL_FLASH_Lock();//锁定Flash
return true;
}
  • 4、跳转函数(从BootLoader中跳转到APP的main函数)
void BootLoad_Jump(void)
{
/* Check Vector Table: Test if user code is programmed starting from address
"APPLICATION_ADDRESS" */
d_printfhex32((*(__IO uint32_t*)APPLICATION_ADDRESS));d_printf("\n");
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS +4);
d_printfhex32(JumpAddress);d_printf("\n");
HAL_Delay(100);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
}
}

STM32 BootLoader升级固件的更多相关文章

  1. STM32 IAP 固件升级设计/U盘升级固件

    源:STM32 IAP 固件升级设计/U盘升级固件 固件升级的基本思路是: 将stm32 的flash划分为两个区域: 1.Bootloader区:存放bootloader的代码,bootloader ...

  2. Stm32 Bootloader整理

    Stm32 Bootloader整理 一.        基本概念 1.IAP IAP是In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User ...

  3. stm32 Bootloader设计(YModem协议) (转)

    源:stm32 Bootloader设计(YModem协议) 相信很多人都希望,不开盖就可以对固件进行升级吧,就像手机那些.下文中的bootload就来实现这样的功能. 前段时间有项目关于Bootlo ...

  4. 基于IAP和网口升级固件

    基于IAP和网口升级固件 一.      需求引入 现有嵌入式设备:基于ARM Cortex-M3处理器.带以太网通讯功能. 为减少设备维护成本节省宝贵的时间和金钱,须要设计网口升级固件功能. 本文描 ...

  5. JLINK固件丢失或升级固件后提示Clone的解决办法

    J-LINK V8固件烧录指导 J-LINK 是使用过程中,如果内部固件意外损坏或丢失,请参考下面操作步骤说明,重新烧录JLINK固件. 安装固件烧录软件 请ATMEL官方网址下载AT91-ISP下载 ...

  6. 关于JLINK固件丢失或升级固件后提示Clone的解决办法

    本人用的JLINK仿真器(某宝上买的),在使用新版KEIL时,提示要升级固件,升级后就出现JLINK is Clone的提示.在网上找了许多关于修复的资料,都觉得不是很好.经过本人反复试验,总算找到比 ...

  7. scp传入固件,sysupgrade xx.bin升级固件

    scp传入固件,sysupgrade xx.bin升级固件

  8. 实现乐鑫esp8266的无线OTA升级,实现远程在线升级固件

    代码地址如下:http://www.demodashi.com/demo/12994.html 一.前言: 写了这么多的8266博文,一直以满意100%的心态去敲写代码固件烧录,以致很少出现 bug ...

  9. hackrf one环境搭建以及升级固件

    一.环境配置 操作系统: Ubuntu 18 硬件:hackrf 第一步 配置国内源 备份 /etc/apt/sources.list 文件 sudo mv /etc/apt/sources.list ...

随机推荐

  1. 如何系统学习C 语言(上)之 基础篇

    大话C 语言(一) 初识C 语言 老实说,上大学之前我根本不知道什么是C 语言,所以当初学校开设这门课时,我是充满了好奇,所以当初我翻阅了大量的C 语言入门书籍,千篇一律,都是从一些概念.术语和理论讲 ...

  2. Ubuntu Python2 和 Python3 共存 切换

    例如 你写了代码 创建一个文件 在终端 vim test.py 然后写入代码 print "hello world" 接着运行代码 python test.py 会输出 hello ...

  3. linked-list-cycle leetcode C++

    Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using ex ...

  4. Luogu P1850 [NOIp2016提高组]换教室 | 期望dp

    题目链接 思路: <1>概率与期望期望=情况①的值*情况①的概率+情况②的值*情况②的概率+--+情况n的值*情况n的概率举个例子,抛一个骰子,每一面朝上的概率都是1/6,则这一个骰子落地 ...

  5. 重学STM32---(九)之CAN通信(一)

    目录 1.CAN 是什么 2.CAN 特点 3.错误状态的种类 4.总线拓扑 5.CAN 协议 1.CAN 是什么   CAN 是 Controller Area Network的缩写(以下称为 CA ...

  6. 关于axios 的responseType类型的设置

    responseType值的类型可为如下 axios请求下载导出一个文件,请求成功时返回的是一个流形式的文件,需要设置responseType: 'arraybuffer',但是请求失败的需要返回的是 ...

  7. Tcpdump 常用命令、参数记录

    一.介绍 一个关于Centos  Tcpdump 的个人工作总结. 二.参数介绍: 1. -i:   指定要进行抓包的网卡 2.-s0 :表示每个报文的大小是接收到的指定大小,如果没有这个选项,则超过 ...

  8. The Ninth Week (Lucklyzpp)

    The Ninth Week  (Lucklyzpp) 1.简述DNS服务器原理,并搭建主-辅服务器. [10:36:39 root@lucklyzpp ~]#vim /etc/named.conf ...

  9. layui表格-template模板的三种用法

    问题情境: layui中将数据库数据通过layui table渲染到前端表格,非常简单,但是如果数据库存储的信息不能被直接展示,项目中该页面有好几个这样的字段,会员类型,支付类型,会员时长还有平台类型 ...

  10. 用C++实现俄罗斯方块(Tetris)游戏

    我是一个C++初学者,控制台实现了一个俄罗斯方块游戏. 代码如下: //"俄罗斯方块"V1.0 //李国良于2017年1月20日编写完成 #include <iostream ...