STM32 BootLoader升级固件

STM32 BootLoader升级固件BootLoader 关于 Bootloader 从书上的文字描述 很难理解这个名词是什么 有什么用 这次用到了 算是有了更进一步的认识 一 知识点 1 BootLoader 就是单片机启动时候运行的一段小程序 这段程序负责单片机固件的更新 也就是单片机选择性的自己给自己下程序 可以更新 也可以不更新 更新的话 BootLoader 更新完程序后 跳转到新程序运行 不更新的话 BootLoader 直接跳转到

BootLoader

关于Bootloader,从书上的文字描述,很难理解这个名词是什么,有什么用。这次用到了,算是有了更进一步的认识。

一、知识点

  • 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、所谓的跳转,可以理解为改变程序PC指针,指向APP程序扇区的起始地址。

二、部分代码

  • 1、主函数
int main(void) { 
    HAL_Init();//STM32初始化 SystemClock_Config();//时钟配置 System_GPIOInit();//IO口配置 #ifdef BOOTLOAD_DISPLAY_ENABLE SystemColorInit();//显示屏配置 #endif System_LoadUpdateFile();//升级函数 while (1) { 
    } } 
  • 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、重写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 ) == 0x) { 
    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(); } } 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214588.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午3:54
下一篇 2026年3月18日 下午3:54


相关推荐

  • 《JavaScript 模式》读书笔记(6)— 代码复用模式1

    我们有开始进入新篇章了。这篇内容主要讲代码复用模式,实际上代码复用,就是继承啊,原型啊,构造函数啊等等这一类的内容。对于前端进阶来说,是很重要的基础知识。这一篇内容会对原型、继承有很深入的讲解。我也

    2022年3月25日
    45
  • 推荐一个Oracle数据库学习网站

    推荐一个Oracle数据库学习网站推荐一个我个人的 Oracle 数据库学习网站 比较系统性的整理 会持续更新的网站 网址 Oracle 基础教程 http www oraclejsq com article 010100110 htmlPL SQL 教程 http www oraclejsq com plsql 010200446 html 转载于 https www cnblogs com hf131

    2026年3月26日
    2
  • wx.login报40029

    wx.login报40029error:40029:invalidcode,rid:61c28073-488240c7-666b1fc2

    2022年5月22日
    81
  • [Java Web – 3A] – Spring MVC开发注意事项

    [Java Web – 3A] – Spring MVC开发注意事项

    2021年9月15日
    56
  • m3u8文件合并 app(m3u8合并失败)

    电脑端合成m3u8方法利用.bat文件步骤如下手机端PC端利用.bat文件bat文件是dos下的批处理文件。批处理文件是无格式的文本文件,它包含一条或多条命令。它的文件扩展名为.bat或.cmd。在命令提示下输入批处理文件的名称,或者双击该批处理文件,系统就会调用cmd.exe按照该文件中各个命令出现的顺序来逐个运行它们[1]。使用批处理文件(也被称为批处理程序或脚本),可以简化日常或重复性任务。入侵者常常通过批处理文件的编写来实现多工具的组合入侵、自动入侵及结果提取等功能。链接:百度百

    2022年4月13日
    311
  • vmware15最新激活码2021_在线激活

    (vmware15最新激活码2021)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月22日
    81

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号