相当部分的 STM32芯片都带USB模块,有时我们会考虑利用STM32芯片的USB模块进行程序代码的下载或升级。USB协议中有专门针对设备固件升级的类协议,即可以通过DFU类协议进行产品固件的加载或更新。
关于STM32产品的DFU程序下载和升级,ST官方有相关的资料文档。
有个用户手册UM0412详细介绍了如何利用ST官方软件工具DfuSe进行相关编程操作。顺便提醒下,下载DfuSe安装包解压运行DfuSe_Demo_Vxx_Setup.exe之后,还不算安装完成,还得安装针对DfuSe的WINDOWS环境下的驱动程序。如果你运行DfuSe_Demo_Vxx_Setup.exe时使用默认路径的话,该驱动程序的位置一般就在下图方框所指的路径,选择合适.INI文件。
当你见到设备驱动程序成功安装的提示时,PC端的安装才算完成。至于DFU文件的准备操作这里就不再赘述,手册讲得很清晰。
这里要额外提醒的是,利用DFU方式对STM32 程序代码加载或更新有两种模式,即ISP模式和IAP模式。
所谓ISP模式就是指MCU芯片出厂时内部已集成了DFU相关自举驱动代码,利用它并借助USB接口即可将用户应用程序下载进芯片。不妨以STM32F4xx 为例来介绍,下图是STM32F4xx自举模式配置及内部系统存储器的描述。
可以看出,STM32F4XX系列芯片的系统存储器内集成了相关DFU驱动,支持ISP模式下的DFU方式进行用户代码加载或升级。此时,BOOT配载在system memory模式,你只需准备好相关的用户程序代码,借助上面的DfuSe工具即可完成用户程序的下载。之后,将BOOT配置为用户模式,即main flash memory模式。
当然,并不是所有带USB模块的STM32 芯片内都集成了相关DFU自举驱动,或者说即使集成了但你并不想使用它。那你就可以换个模式,即IAP模式。自行编写DFU相关自举驱动程序,然后通过调试设备下载到芯片里,之后通过该DFU驱动并借助DfuSe工具完成用户程序的更新或下载。此时boot配置是用户模式,即main flash memory模式。这点跟上面的ISP模式不一样的。
对于各STM32系列IAP的参考代码,在ST官方网站都有,基本可以拿过来就用。需要修改的地方主要是触发源,比方按键,再就是要跳转的用户程序起始地址,以及编译时相关内存地址的调整。
为了比较,我们顺便看看STM32F1系列系统 内部存储区自举程序的介绍:
很明显,对于STM32F1系列,只有互联型子系列[STM32 F105/STM32F107]支持通过DFU方式实现ISP编程。而其它STM32F1芯片即使带USB模块,若想利用DFU方式编程就只能自行编写DFU自举驱动,通过IAP模式实现用户程序的下载或升级。
几年前在这个地方,我就被折腾了一次。我首先是拿ST官方的评估板STM3210C EVAL用ISP方式测试DFU功能,没问题,一路畅通。后来某客户借了块STM32F1的评估板[当时我以为也是STM3210C EVAL],他使用ISP方式测试这个DFU功能,奇怪得很,怎么也不成功。我跟他回复确认说这个功能测试过肯定没问题。后来反复沟通,发现他拿的那块评估板是STM3210E EVAL,主芯片是STM32F103ZE,而我之前测试的评估板的主芯片是STM32F107VC,后者是F1系列中的互联型,前者则不是。只怪当时手册看得不细,加上这两种评估板长相也很雷同。
其实,利用USB接口来加载程序跟利用UART接口加载程序的流程是类似的,只是接口、协议有差异而已。实现方式可以是ISP,也可以是IAP。具体实现方式要结合芯片内部集成的相关自举驱动和实际应用需求来考虑。
最后提醒下,在对STM32F1/F2/F3/F4/F0几个系列的芯片作IAP应用时,F0系列跟其它系列不一样,它没有中断矢量定义寄存器SCB_VTOR,所以在相应的用户APP代码开始处要先做SYSCFG外设时钟的使能开启和中断矢量的拷贝操作。相关参考代码如下:
int main(void)
{
uint32_t i = 0;
/* Relocate by softwarethe vector table to the internal SRAM at 0x20000000 ***/
/* Copy the vector table from the Flash(mapped at the base of the application
loadaddress APPLICATION_ADDRESS) to the base address of the SRAM at 0x20000000. */
for(i = 0; i < 48; i++)
{
VectorTable[i] = *(__IOuint32_t*)(APPLICATION_ADDRESS + (i<<2));
}
/* Enable the SYSCFG peripheral clock*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Remap SRAM at 0x00000000 */
SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
/****************下面书写你的应用代码 **********************/
其它操作跟其它几个系列一样,该怎么操作怎么操作。