STM32 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、所谓的跳转,可以理解程序指针的改变,变为指向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();
    }
}
时间: 2024-08-08 20:44:41

STM32 BootLoader升级固件的相关文章

基于IAP和网口升级固件

基于IAP和网口升级固件 一.       需求引入 现有嵌入式设备:基于ARM Cortex-M3处理器.带以太网通讯功能.为降低设备维护成本节省宝贵的时间和金钱,需要设计网口升级固件功能. 本文描述了基于IAP和网口升级该嵌入式系统的方法,其中处理器为NXP公司的ARM Cortex-M3,开发环境为IAR Embedded Workbench for ARM. IAP( In Applicatin Programming)在应用编程,一般指MCU可以通过通信端口(UART口.网口等)从外部

《GK101任意波发生器》升级固件发布(版本:1.0.2.build124)

一.固件说明: 硬件版本:0,logic.3 固件版本:1.0.2.build124 编译日期:2014-08-19 ====================================== 二.固件版本说明: 1.在系统标签中添加显示设置 可以设置系统的亮度和主题 2.在系统标签中添加同步功能 可以控制同步输入.同步输出.同步相位 3.修复直流偏置中的问题 修正:在设置直流偏置为+5V时,输出波形参数不正确 ====================================== 三.

《GK101任意波发生器》升级固件发布(版本:1.0.1build803)

一.固件说明: 硬件版本:0,logic.3 固件版本:1.0.1.build803 编译日期:2014-08-06 ====================================== 二.固件版本说明: 1.添加猝发,同步等功能 ====================================== 三.固件下载 链接: http://pan.baidu.com/s/1kTA5eIj 密码: nuw1 ======================================

rtthread stm32在线升级

目录 bootloader 制作bootloader 使用bootloader APP 制作带有ymodem_ota功能的APP 打包APP固件并执行OTA 芯片型号:STM32F103VET6(100个引脚),主频 72MHz,512KB FLASH ,64KB RAM 仿真调试:J-LINK rtthread官方文档:https://www.rt-thread.org/document/site/application-note/system/rtboot/an0028-rtboot/#ot

STM32 V4.0固件库学习(一)环境准备

之前很是惭愧,写了几篇,虽然嘴上说太忙,还是懒病发作,就停了.没有养成好习惯. 还有一个想吐槽下,这个传图片好麻烦啊啊啊 估计之前也是因为这个停了... 虽然还是对之前公司的项目非常感兴趣,因为地域缘故,今年来还是换了工作,这边项目还没开始,陆陆续续到现在也有好几个月时间, 也看了很多东西.回头看看,啥记录也没有,也不知道是不是现在年纪大了,感觉啥东西也没记住.看了点啥也不知道了.这次重新下决心, 争取能够每天记录一下.最少也得把这个事情做完,以此勉励自己. 本人之前ARM7 M0 M3 430

四轴飞行器Bootloader和固件的更新

在四轴飞行器中,为了方便用户后期对飞行器进行固件升级,一般都采用了Bootloader技术.所谓Bootloader就是指单片机启动后首先运行的一段代码,它的最主要功能就是用于检查用户是否要更新飞控固件.如果是,则进入飞控固件更新进程,如果否,则直接运行当前的飞控固件.此外,有的Bootloader里面也包含进了一些基本的硬件检测功能,如果硬件检测失败,就不进入飞控功能.通常,Bootloader都要配合飞行器的上位机软件来使用. 下面以圆点博士小四轴飞行器为例进一步对Bootloader进行说

stm32打怪升级之瞥眼定时器

定时器TIM------->DMA(不用看功能直接忽略介绍) 外部中断得开启复用功能 定时器TIM)时钟源:stm32时钟系统框图(需要下载)外部中断得开启复用功能实验目的:定时1s让灯亮库:定时用到了stm3210x_tim.h库模版:工程模版+TIM3_IRQHandler模版 流程1.复制工程模版2.打开工程模版在app中新建文件定时器3.新建time.h和time.c文件添加至app定时器中4.在time.h文件中写入声明voidtime_init(void),且修改#define _T

Mac上TFTP服务器的配置和为TP-Link升级固件

1.TFTP协议 简单文件传输协议Trivial File Transfer Protocol (TFTP)是一个基于UDP协议的简单的.低开销的文件传输协议,允许客户端get或者put文件到远程主机上.由于它开销极效,所以TFTP被用于引导计算机,例如没有大容量存储器的路由器.这就是为什么很多路由器都用tftp作为升级的方式.这个协议很有意思,如果感兴趣,请参考如下两个网址: 中文wiki  或者 英文wiki RFC 1350 THE TFTP PROTOCOL (REVISION 2) 2

海信电视 LED55K370 升级固件总结【含固件下载地址】

最早电视买回来,感觉垃圾软件太多,root后,删软件不小心删除了桌面,导致没桌面. 用ADB装了点软件,凑合可以用. 后来装了悟空遥控,然后装了沙发桌面,不影响使用了. 最近海信不停推送更新系统,改手动更新都还是推送,而且关不掉,想更新又更新不了(root后就不能自动更新了)不更新又电视不能用.烦躁啊! (这里有个技巧,如果不更新系统可以插鼠标,或者悟空遥控鼠标模式,点下屏幕旁边,那个提示更新的对话框就会隐藏,若实在无固件更新,只能这样做) 然后网上找了42K370固件装了,依然不能更新.天理啊