对于很多人来说,BootLoader并不是一个陌生的词,甚至会经常用到它。因为在很多情况下我们都需要BootLoader程序,比如我们需要对系统在线升级时就需要它,还有当我们需要在外部存储器中运行程序时也需要用到它。在这里我们就来设计一个应用于STM32系列MCU的BootLOader程序。

1BootLoader的基本原理

既然我们想要实现一个面向STM32的BootLOader程序,那么首先我们必须来了解一下BootLOader程序的基本原理。

顾名思义,BootLOader程序肯定是要实现系统的引导,这是BootLOader程序的基本功能。对于STM32系列MCU来说,系统启动后都会从内部Flash存储器的起始地址开始执行程序。然后进入应用程序并按既定的顺序执行下去,这时BootLoader与应用程序是一体的,具体如图所示:

但有些时候,我们希望应用程序并不是直接运行,如我们希望对系统实现IAP的时候;或者我们希望应用程序并不在我们的内部Flash中运行;又或者应用程序虽然在内部Flash运行,但我们希望应用程序从我们指定的内部Flash地址运行等等。在这些时候我们就需要一个单独的BootLoader程序。系统首先启动BootLoader程序,系统准备就绪后进入到应用程序执行,具体如图所示:

在上图中,我们实际上将应用程序存储在内部Flash的指定位置,这样做当然是为了实现我们某种需求,如系统IAP。当然我们也可以让应用程序存储于外部Flash中,然后BootLoader程序跳转到外部Flash去执行应用程序,不过前提是外部Flash内购执行程序。具体过程如下:

当然,这只是一种示例,对于不同的存储器我们只需要修改地址就可以了。至于在BootLoader程序中要实现的功能就看使用情况了。原则上我们可以添加我们任意想要的功能,如硬件检测、系统升级等等。

2、目标BootLoader设计

我们的目标是实现一个面向STM32的BootLoader程序。那么接下来我们就设计如何实现一个面向STM32的BootLoader程序。

2.1Flash规划

我们以STM32F407IGT6为目标MCU,这款MCU具有1M的Flash和192K的SRAM。我们将Flash划分为2个部分,一个是启动程序区(0x0800 0000 - 0x0800 3FFF )大小为16K Bytes,剩下的为应用程序区(0x0800 4000 - 0x080F FFFF)。具体分配如下图:

我们让BootLoader程序占用16K的存储空间。但它是可以操作整个Flash存储空间的。

2.2BootLoader程序结构

我们来考虑一下BootLoader程序的结构问题。我们设计BootLoader程序的主要目的就是为了对应用程序进行升级。那么在BootLoader程序中主要需要实现哪些功能呢?有几个方面是必须要包括的,一是基本的配置,如时钟等,我们在主程序中实现;二是对Flash的操作,我们升级应用程序肯定会对Flash进行查处和写入操作;三是跳转控制程序,我们最终是需要去执行应用程序的,跳转功能必不可少。当然根据不同的需求可能会有其它的需要。具体如下图所示:

上图中,我们除了签署的三项基本实现外,还添加了IAP文件的获取功能。这部分功能也是需要的,但在不同的模式下可能会有较大区别。因为获取文件的方式可以是各类通讯如以太网口、串口等。也可以是各类存储器,如SD卡、U盘等。所以这一功能虽然必不可少但实现方式则非常灵活,在后续实现中,我们具体问题具体分析。

3、目标BootLoader实现

我们已经确定了Flash的划分,也基本明白了BootLoader的基本工作流程。在接下来我就来讨论一下究竟怎么实现一个BootLoader程序。

3.1BootLoader编码

我们知道芯片上电时先运行BootLoader程序,然后跳转到应用程序区执行应用程序。所以我们在编写BootLoader程序时我们首先判断系统是否有IAP的需求,如果有IAP请求则进入IAP模式,完成后再跳转到应用程序执行,如果没有IAP请求则直接跳转到应用程序执行。具体流程如下:

关于IAP的处理在不同的情况下会有不同的处理方式,在这里我们主要看一看跳转控制程序。首先定义应用程序的首地址并声明一个函数指针类型。具体如下:

#define  ApplicationAddress  0x08004000    //应用程序首地址定义

typedef void (*pFunction)(void);        //定义跳转函数指针类型

可能有人要问问什么定义这样一个函数指针类型,因为我们最终是跳转到Reset_Handler函数,所以必须要一个可以指向这个函数的函数指针。接下来我们就可以实现跳转程序了。

/*跳转到应用程序处理函数*/
static void JumpToApplication(void)
{uint32_t StackAddr;           //应用程序栈地址uint32_t ResetVector;         //应用程序中断向量表的地址pFunction JumpToApp;          //定义跳转函数指针__set_PRIMASK(1);    //关闭全局中断StackAddr = *(__IO uint32_t*)ApplicationAddress;              //0x08004000;ResetVector = *(__IO uint32_t*)(ApplicationAddress + 4);      //0x08004004;if((StackAddr&0x2FFC0000)==0x20000000)        //检查栈顶地址是否合法.{__set_MSP(StackAddr);                       //初始化应用程序栈指针JumpToApp = (pFunction)ResetVector;           JumpToApp();}
}

3.2、应用程序处理

实现了BootLoader的编码后,要想正确的跳转到App运行,我们还需要对App作相应的修改。重要的修改有2处。如果应用程序是裸机程序则在配置时钟前我们需要打开全局中端。

/*开启全局中断,在BootLoader中关闭的*/

__set_PRIMASK(0);

同时,还需要修改中端向量表的偏移量地址。对于我们所使用的STM32F07可直接在system_stm32f4xx.c文件中修改就可以了。

#define VECT_TAB_OFFSET  0x4000 /*!< Vector Table base offset field.

实现了上述修改并不能达到我们想要的目的,我们还需要在开发环境中做必要的修改。以我们使用的IAR EWARM V8.4为例。修改icf文件中对中断向量表和Flash存储区域的设定。具体如下图:

完成上述配置后我们下载应用程序和BootLoader程序就可以实现正确的跳转了。

4、小结

本篇中,我们只是实现了一个简单的BootLoader程序。下载到目标MCU后实现了跳转,应用程序也正常运行,说明我们的设计是正确的,后续可在次基础上添加各种功能实现相应的IAP应用。

需要注意的是在BootLoader程序中我们关闭了全局中断,在应用程序初始化系统时钟之前一定要记得打开全局中断,否则SystemTick不能工作会产生硬件故障(hardfault)。不过如果App是运行在RTOS上,则打开中断可能会出错,这一点需要注意。

欢迎关注:

嵌入式IAP开发笔记之一:面向STM32的BootLoader程序相关推荐

  1. 嵌入式系统开发笔记0_0:目录

    本系列文章将向大家介绍嵌入式系统开发的各方面知识. 本系列文章所介绍的知识和内容,除电路图设计外,其它均采用开源系统,所以你不会在这个系列文章中看到Keil.IAR等软件. 本系列文章涉及C.C++. ...

  2. 嵌入式系统开发笔记2:Linux的主流发行版本

    本系列文章将向大家介绍嵌入式系统开发的各方面知识. 本文将向大家介绍Linux的主流发行版本. 本文为转载文章,原文网址:Linux各个发行版本对比与简介 首先我们要能够清晰的区分Linux系统内核与 ...

  3. 嵌入式系统开发笔记80:应用Qt Designer进行主界面设计

    前言   本篇文章讲解PyQt的基本使用方法,我们将应用Qt Designer来设计一个主界面,学习完本篇文章的内容后,你将获得如下技能.   (1)在VS Code中启动Qt Designer    ...

  4. 设备文件BSP及嵌入式驱动开发笔记

    PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘.目前又不当COO,还是得用心记代码哦! BSP及嵌入式驱动开辟笔记 第一讲嵌入式系统基本概念 以应用为中央,以计算机 ...

  5. 嵌入式系统开发笔记25:win10防火墙打开特定端口

    本系列文章将向大家介绍嵌入式系统开发的各方面知识. 本文将向大家介绍dakaiwin10防火墙特定端口的方法. 1.引言 win10上位机编写程序,启动TCP服务器应用程序,并绑定1000端口:lin ...

  6. 嵌入式系统开发笔记105:下载程序到STM32开发板

    文章目录 前言 1.启动FlyMcu 2.倒入映像文件 3.设置选项 4.连接开发板 5.下载程序 6.复位后运行 前言   本文介绍如何将编译好的映像文件下载到STM32开发板. 1.启动FlyMc ...

  7. USB应用开发笔记之一:STM32上实现USB主机读写U盘

      在项目应用中,经常会有对外交换数据的需求.USB接口读写U盘无疑是一种颇为方便的选择.在这一篇中,我们就来讨论如何在STM32上实现USB主机读写U盘文件的方法. 1.应用概述   在我们的产品上 ...

  8. 嵌入式系统开发笔记91:认识ARM微控制器架构

    文章目录 前言 一.ARM 二.ARM微控制器的市场占有率 1.95%的智能手机 2.90%的平板电脑 3.96%的硬盘驱动器 4.85%的无人机 5.83%的数字电视 6.75%的工业机器人 三.A ...

  9. iOS开发笔记--基于面向协议MVP模式下的软件设计

    传统模式下的开发 MVC MVVM 基于面向协议MVP的介绍 MVP实战开发 说在前面:  相信就算你是个iOS新手也应该听说过MVC的,MVC是构建iOS App的标准模板.随着时间的推移,在iOS ...

最新文章

  1. RecyclerView嵌套TextView时显示文字不全的解决方法之一
  2. sql 以a开头的所有记录_#9#猴子聊数据分析之常见的SQL笔试题和面试题(下)
  3. Android system server之WatchDog看门狗分析
  4. Android自定义View实践 空气质量检测 pm2.5
  5. 打印机可以打印不能扫描怎么弄_为什么打印机可以通过电脑打印可不能扫描呢...
  6. Linux 权限、磁盘操作命令-Linux基础环境命令学习笔记
  7. 产品经理须知 | API接口知识小结
  8. c3p0与dbcp的异同
  9. python安装软件win10_在win10上安装Python和Tensorflow
  10. Rust : async、await 初探
  11. 千元喜提“随身影院”荣耀8x Max,告诉你移动刷剧是种什么体验?
  12. 史上最全的数据链路层基础知识详解
  13. 网络技术-Cisco路由器
  14. wps的ppt放映时不能完全全屏的解决方法
  15. 小米市场魅力所在?你读懂小米了么?
  16. 如何用pycharm将.ui文件转换为.py文件(内含出错解决方法)
  17. 咸鱼Micropython— machine库
  18. pytorch:如何从头开始训练一个CNN网络?
  19. 批量图片格式转化——gif、jpg、png三种格式的图片相互转化
  20. 如何光盘启动安装操作系统

热门文章

  1. 国科大高级人工智能9-模糊数学和遗传算法
  2. WCF进阶:将编码后的字节流压缩传输
  3. 用机器指令和汇编指令编程(修改版)
  4. Apache网站服务
  5. 【HTML5】Server-Sent服务器发送事件
  6. 2015年2月12日——不懂点
  7. 【转载】贝叶斯决策论
  8. 配置tomcat_Tomcat 配置必备的 10 个小技巧,让你轻松玩转Tomcat
  9. matlab 带有下标的赋值维度不匹配_远见另类资产管理体系下的核心系统搭建
  10. php调用文章标题,zblogphp标题格式的标签调用详细说明