IAP-Bootloader | 基于STM32F407+STM32CubeMX - 通过按钮实现Bootloader程序与APP程序互相切换

一、前言


1.1、IAP与ISP

bootloader一般分为两种:

1、ISP - 使用ST芯片自带的bootloader程序实现APP程序的刷写,其优势是简单,可靠。

2、IAP - 自己编写一个bootlader实现APP程序的刷写,其优势是自定义,灵活性强。可以通过任意的通讯接口实现远程升级。

ISP的bootloader实战,可以参考之前我的以下文章:

bootloader | 基于STM32F407 - 使用STM32Cubeprogrammer的USB DFU进行固件烧写

bootloader | 基于STM32F407 - 使用STM32Cubeprogrammer的UART进行固件烧写

在学习IAP时,找到一些不错的资料:

【实战技能】单片机bootloader的CANFD,I2C,SPI和串口方式更新APP视频教程(2022-08-01)

BSP视频教程第17期:单片机bootloader专题,启动,跳转配置和调试下载的各种用法(2022-06-10)

【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000

下面文章是初学IAP的重点,文章是基于标准库解决问题,在HAL库上原理一样,只是处理方法改一下。(HAL库没有函数NVIC_SetVectorTable)

从启动程序(BootLoader)跳转到指定地址时(APP)出现问题的解决方法

文章后见会介绍如何在HAL库上处理这个问题(system_stm32f4xx.c文件),毕竟现在使用标准库的人比较少,且ST官方也不建议使用标准库了。

IAP的难点在于Bootloader跳转APP,有如下几点需要弄明白的:

  • .map文件的阅读
  • 中断向量表
  • STM32的启动流程
  • flash内存的分配

1.2、本次实验的目的

将自己编写的bootloader程序烧写进STM32芯片的FLASH地址0x08000000的起始位置,接着将APP程序烧写进STM32芯片的FLASH地址0x08010000起始的地址。
在这里插入图片描述

  • 点击按钮KEY1,bootloader程序切换至APP程序运行。
  • 点击按钮KEY2,APP程序切换至bootloader程序运行。
    在这里插入图片描述
    一共有两个程序,APP与BOOT(bootloader程序)。
    在这里插入图片描述
    学会bootloader与APP程序互相跳转的程序后,接着可以使用串口,CAN,SPI,I2C,网口等通讯接口升级APP程序了。

工程分享:

链接:https://pan.baidu.com/s/1ZeSxh10BbqqPjarWMkDbfQ?pwd=f2zz

提取码:f2zz

二、STM32CubeMX


STM32CubeMX配置初始的工程的步骤我就省去了,本例程只使用了简单的GPIO输出与GPIO读取,并没有复杂的外设。将百度云盘分享的工程下载下来直接查看配置即可。

三、MDK的设置


3.1、Bootloader工程

Flash起始地址: 0x8000000,其大小是0x10000(65536/1024 = 64K)
在这里插入图片描述
最后修改下载算法,将BOOT程序的下载地址限制在0x08000000 - 0x0800FFFF
在这里插入图片描述

3.2、APP工程

在这里插入图片描述
最后修改下载算法,将BOOT程序的下载地址限制在0x08010000 - 0x0803FFFF
在这里插入图片描述

四、代码


4.1、Bootloader工程

4.1.1、main.c

在这里插入图片描述
在这里插入图片描述
函数JumpToBootloader()是从安富莱那里直接拷贝过来使用的,比其他嵌入式厂家要专业。
我的APP程序是从FLASH内存的0x08010000开始,这个按照自己的内存分配修改一下即可。
在这里插入图片描述

4.1.2、system_stm32f4xx.c

这里非常重要!这里非常重要!这里非常重要!重要的事情说三遍!!!!!!
这个代码就是修改程序的中断向量表从内存FLASH哪里取出来,并初始化。bootloader程序的中断向量表在0x08000004里。后面会介绍为什么我知道bootloader程序的中断向量表是在内存0x08000004里边。
在这里插入图片描述
在这里插入图片描述
编译一下工程:
在这里插入图片描述

4.2、APP工程

4.2.1、main.c

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2.2、system_stm32f4xx.c

在这里插入图片描述
在这里插入图片描述
编译一下工程:
在这里插入图片描述

五、map文件确认程序flash的位置与中断向量表的位置

Keil工程的map文件如何打开,可以参考:
Keil | 解决Keil双击工程名无法打开.map的问题

5.1、Bootloader工程的map文件

5.1.1、确认flash的位置

在这里插入图片描述

5.1.2、确认中断向量表的位置

在这里插入图片描述

5.2、APP工程

5.2.1、确认flash的位置

在这里插入图片描述

5.2.2、确认中断向量表的位置

在这里插入图片描述
从两个工程的.map文件看来,flash与中断向量表的设置都是在预期。

六、下载两个程序到板子上


直接用MDK把两个工程都烧写进去,两个工程的FLASH地址设置不一样,所以不会互相影响。

下载bootloader程序。
在这里插入图片描述
下载APP程序。
在这里插入图片描述

七、观察板子


下载完两个程序进去后,板子重新上电。

首先,LED1在闪烁,LED2与LED3都是熄灭。表示正在运行bootlader程序。接着,按下KEY1。

按下KEY1后,LED1与LED2在闪烁,LED3常亮,表示此时正在运行的是APP程序。

当我们按下KEY2后,LED1在闪烁,LED2与LED3都是熄灭的。表示此时又返回运行bootlader程序了。

至此,实验成功!!!!
在这里插入图片描述

八、细节补充


8.1、为什么需要修改system_stm32f4xx.c的代码?

原因是程序跳转之后,还需要另外告诉程序中断向量表也需要跳转。比如bootloader跳转APP程序后,此时的中断向量表也需要指向APP程序的中断向量表,否则无法产生中断。

bootloader程序与APP程序都有自己的中断向量表。
在这里插入图片描述
修改system_stm32f4xx.c就是为了达到这个目的。实际上,从system_stm32f4xx.c上看,HAL也准备好了代码给我实现中断向量表的重新设置。

看下面代码:

VECT_TAB_BASE_ADDRESS被谁调用?往下看。
在这里插入图片描述
VECT_TAB_BASE_ADDRESS被函数SystemInit()调用了。
在这里插入图片描述
OK…那谁调用了函数SystemInit()?从下图看到,从STM32F407的启动文件找到,Reset_handler中断回调调用了SyetemInit( ),接着进入main()函数开始运行。
在这里插入图片描述
梳理完了,大概是这样的。。
在这里插入图片描述

8.2、不修改system_stm32f4xx.c的代码可以吗?

当然可以啊,我们修改system_stm32f4xx.c就是为了运行这个代码:
在这里插入图片描述
那么,我们在main()函数写入这个代码也可以的,如下图所示:
bootloader工程:
在这里插入图片描述
APP工程:
在这里插入图片描述

  • 17
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wallace Zhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值