什么是IAP?
IAP(In-Application Programming) 指MCU可以在系统中获取新代码并对自己重新编程,即可用程序来改变程序。在应用编程(IAP)是用户的应用代码对片内Flash存储器进行擦除/编程的方法。这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到数据存储区,从而实现固件升级。
什么是BootLoader?
百度百科:在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。
实际上,BootLoader不仅仅在操作系统上使用,在一些内存小,功能应用较为简单的单片机设备上面也可以通过BootLoader来完成固件升级。
什么是DFU?
DFU全称为Download Firmware Update,是ST官方推出的一个通过USB接口进行IAP升级的方案,同串口ISP一样,他们都集成在了芯片内部的Bootloader区段,可以通过配置boot引脚来启动。
不过STM32内置DFU的型号都比较新,像STM32F4系列是有的,但是像F0和F1系列则没有,不过没有关系,如果你用的型号没有内置DFU程序,也可以通过CubeMX来快速生成和移植一个DFU功能程序到你的Flash中来使用。
使用DFU的优缺点?
使用DFU的好处是不用自己制作Bootloader,因为这部分代码在STM32出厂之前就已经做好并且烧录进去了,而且不占用用户代码的Flash,另外,在PC端我们也不需要专门定制一个上位机,因为官方就有专门的升级Tool以及USB驱动。
缺点是要改变boot引脚的电平,才能启动Bootloader,这样的话在应用场景上就有比较大的限制了。
所以,要根据项目的实际需求去选择合适的方案。
我之前也有发过一些关于STM32远程升级的文章,实现的方式有很多种,感兴趣的同学可以去看一下。
STM32固件升级系列合集:https://blog.csdn.net/ShenZhen_zixian/article/details/129074047
1 硬件介绍
我这里测试用的是STM32F407。
注意:F0和F1系列是沒有內置DFU的。
用到的硬件接口如下:
| 接口 | 引脚 | 作用 |
|---|---|---|
| USB | PA11 PA12 | (必要)通过USB连接PC端,用来传输固件以实现在线升级 |
| BOOT | BOOT0 BOOT1 | (必要)通过改变boot电平来切换运行模式 |
| 串口 | PA9 | (非必要)通过CH340连接到PC端,打印固件版本号,方便查看升级是否成功 |
| LED | PF9 | (非必要)方便查看代码是否跑起来了 |
BOOT引脚配置对应如下图:

1)主Flash
主Flash起始地址为0x08000000,它指的是STM32内置的Flash,通常我们烧录的代码就是存放在这个位置。
2)系统存储器
系统存储器起始地址为0x1FFF0000,这种模式启动的程序功能是由芯片厂家设置的,STM32在出厂时会这个区域内置一段BootLoader, 也就是我们常说的ISP程序, 这是一块ROM,出厂后无法修改。我们要使用的DFU就是放在这里。
3)嵌入式SRAM
嵌入式SRAM起始地址为0x20000000,既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。假如我只修改了代码中一个小小的 地方,然后就需要重新擦除整个Flash,比较的费时,可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后,在将程序下载到SRAM中。
2 环境搭建
2.1 Keil uVsion
关于STM32以及Keil的环境这里就不具体介绍了,网上教程也很多,不懂的同学自行查阅资料。环境搭建好之后需要准备一个能够正常运行的代码,用来测试我们后面的固件升级。
2.2 STM32CubeProgrammer
这个工具是用来烧录代码的,可以通过ST-Link、UART和USB下载。其中USB下载就是我们今天要讲的DFU模式。
STM32CubeProgrammer官方下载地址:https://www.st.com/en/development-tools/stm32cubeprog.html

根据自己的操作系统下载对应的安装包,然后直接安装即可。

提示:默认地址C:Program FilesSTM32CubeSTM32CubeProgrammerbin,如果安装完找不到应用程序的话可以在这个路径找到。
2.3 zadig
zadig是用来安装一个USB驱动的,只有安装好这个驱动,后面的升级流程才能正常进行,不然识别不到STM32的USB DFU模式。
这里先下载好软件,后面我们用到再安装。
下载地址请自行查阅,或者在我上传的链接下载也行。
zadig:https://download.csdn.net/download/ShenZhen_zixian/87570348
注:本文测试的时候,用的是v2.7.7版本。
2.4 检查USB驱动
1、让STM32进入系统存储器启动模式
也就是配置BOOT0引脚拉高,BOOT1引脚拉低。
提示:BOOT引脚的状态要在MCU启动之前配置好才能进入对应的模式,可以先配置BOOT引脚再上电,也可以在配置好BOOT引脚之后复位MCU。

2、检查和安装USB驱动
把STM32的USB连接到PC端,然后打开设备管理器,查看USB设备的情况。可能会出现以下几种情况。
1)能看到下图这个STM32 BOOTLOADER设备,并且没有黄叹号,说明驱动已经是安装好了的,可以直接跳到后面第3点了。
提示:因为前面安装STM32CubeProgrammer时会提示安装驱动,如果安装了,这时USB驱动可能就已经装好了。

2)能看到下图这个STM32 BOOTLOADER设备,但是有黄叹号,说明驱动异常,需要用zadig重新安装。

打开前面下载好的zadig,点击Install WCID Driver安装即可。

等待安装完成。

安装完成后可以在zadig上看到设备,打开设备管理器,也能看到一个没有黄叹号的STM32 BOOTLOADER设备。


3)能看到下图这个STM Device in DFU Mode设备,但没有STM32 BOOTLOADER设备,需要用zadig重新安装。

先卸载掉STM Device in DFU Mode设备。然后重新插拔USB线,之后会看到一个带黄色感叹号的STM32 BOOTLOADER设备。此时再按照前面的第2步操作即可。

不管是哪种情况,如果前面的驱动安装没有问题,连接上电脑之后可以在设备管理器也能看到一个STM BOOTLOADER设备,而且是没有黄色感叹号的。这样驱动就是OK的了。

3、打开STM32CubeProgrammer
如果驱动和接线都没问题,那么在STM32CubeProgrammer可以看到检测到STM32设备。
提示:如果没有找到设备,请检查前面的步骤。

至此,环境部分就搭建完成了。
3 固件升级
1、连接USB
把STM32的USB接入到PC端。

在STM32CubeProgrammer上连接设备。此时能读取到芯片的Flash。
注意读取的地址和长度,STM32的地址都是以0x08000000开始的,读取的长度就无所谓了,看你自己的需要。

2、导入hex或bin文件
打开要升级的固件(hex或bin都可以)。


打开后能看到固件存储的数据。

3、下载固件
点击“Download”,下载固件到STM32.

4、重启设备
升级完成后将BOOT模式要改成主Flash模式(BOOT0引脚拉低),然后重新上电或复位,即可运行新版本的代码。

至此,整个升级流程就走完了。
结束语
好了,关于如何通过STM32内置DFU实现USB升级就讲到这里,这种方式虽然限制较多,但在某些应用场景是很方便的,比如SB键盘,不需要自己编写Bootloader和上位机就可以实现固件升级,而且官方的升级渠道还稳定。其他应用场景就再另说,合适的才是最好的。
如果你有什么问题或者有更好的方法,欢迎在评论区留言。