查看原文
其他

关于USB DFU IAP例程移植的两个话题

stmcu 茶话MCU 2022-09-11

前言

在STM32 的系列产品中,很多型号都带有USB 接口,为使用USB 来进行代码升级提供了便利。这些型号中又有很大一部分可以通过芯片内部SystemMemory 中的Bootloader 直接进行USB DFU 升级,具体哪些型号支持USB DFU,可参考应用笔记AN2606《STM32 微控制器系统存储器自举模式》。

不过,有些型号虽然有USB,但是SystemMemory中的Bootloader 并不支持USB DFU,比如STM32F102 /STM32F103、或者Bootloader V2.x 的STM32F2xxx、STM32F303等等,或者用户希

望通过不同的触发方式进入bootloader 来进行USB 下载,比如接收一串编制好的数据来触发。那么,就要使用USB DFU IAP 了。

关于如何使用USB DFU IAP 的简要说明,可参考另一份文档《利用USB DFU 实现IAP 功能》。在这里,主要介绍在利用USB DFU IAP 例程进行移植时,需要注意的两个地方。

 

问题一

某客户在其产品的设计中,使用了STM32L073RBT6。客户在开发过程中,使用STM32L0Cube 库中的STM32L073Z_EVAL的DFU_Standalone 进行代码移植,完成后在使用DfuseDemo 软件烧写用户代码时发生了错误。

 

调研

1.1.了解问题

客户在开发中使用了STM32L0Cube 库STM32Cube_FW_L0_V1.7.0,对里边的

\Projects\STM32L073Z_EVAL\Applications\USB_Device\DFU_Standalone例程进行修改,以应用于用户板。客户已经根据硬件上的区别,对LED 灯和按键的I/O 口配置做了相应的修改,并在main.h 中使能了USE_USB_CLKSOURCE_CRSHSI48,因为其使用STM32L073 内部的48MHz振荡作为USB 时钟源。客户编译通过后,使用ST-Link 将其下载到STM32L073RBT6中。然后断开ST-Link,使用USB 进行连接,PC 可以认到“STM Devicein DFU Mode”。打开Dfuse Demo 软件,也可发现已经识别到STM32L073 处于DFU Mode。

但是,当用户选择了“Verify after download”,并点击“Choose”按键选择用户代码.dfu 文件后,并点击“Upgrade”进行烧写,发现弹出了提示发生错误的对话框,如下:

1.2.问题分析

STM32L073Z_EVAL 开发板使用的芯片型号为STM32L073VZT6,其Flash 容量为192KB,地址从0x08000000 到0x0802FFFF。而客户所使用的STM32L073RBT6,其Flash 容量为128KB,地址从0x08000000 到0x0801FFFF。检查项目中的usbd_conf.h文件中的代码,客户并未作任何修改,也就是说,以下两个定义没有根据实际的型号进行修改:

 

/* Startuser code address:ADDR_FLASH_PAGE_120 */

#defineUSBD_DFU_APP_DEFAULT_ADD 0x08003C00

 

/*Startaddress of latest flash page: ADDR_FLASH_PAGE_1535*/

#define USBD_DFU_APP_END_ADD0x0802FF80

 

USBD_DFU_APP_DEFAULT_ADD 和USBD_DFU_APP_END_ADD定义了用户代码空间的开始页和结束页。从这可以看出,用户代码是从0x08003C00 开始的,也就是第120 页,而结束于第1535 页。STM32L073VZT6从第0 页到第1535 页共1536 页,每页128 Bytes。客户使用的是STM32L073RBT6,总共才1024 页。显然,这里对USBD_DFU_APP_END_ADD的定义并不对,需要修改为第1023 页的地址。

1.3.问题解决

将usbd_conf.h 中的USBD_DFU_APP_END_ADD修改为第1023 页的地址:

/* Startaddress of latest flash page: ADDR_FLASH_PAGE_1023 */

#defineUSBD_DFU_APP_END_ADD 0x0801FF80

问题解决,USB DFU 可以下载代码了。别急,接着往下看第二个话题。


问题二

在上面问题的解决过程中,有没有注意到Dfuse Demo 界面中显示“1536 sectors”?这明显不对,来看看怎么修改。

调研

2.1.了解问题

在Dfuse Demo 界面中,双击“1536 sectors”,可以看到Internal Flash 的详细信息,如下:

2.2.问题分析

从上图可以了解到,实际上这里所定义的Sector的大小为128Bytes,也就是STM32L073 的Page,所以这里的Sector定义与STM32L073 的参考手册定义的Sector 是不一样的,不要造成误解。在RM0367 中,每128Bytes 为1 个Page,每32 个Page 才是1 个Sector。所以不要误会了。在这个Mapping 窗口中,也可以看到地址0x08003C00之前的空间为Read only,也就是Bootloader 所处的空间为只读,以避免对这部分代码的重写。而后面的空间,也就是用户代码所处的空间为Read/Write/Erase。

这些信息是从哪里来的呢?其实它来自于usbd_dfu_flash.c 里边定义的描述符FLASH_DESC_STR,如下:

#define FLASH_DESC_STR "@Internal Flash /0x08000000/120*128 a,1416*128g"

来解释一下这个描述符的内容:

0x08000000 为起始地址。“a”代表的是Read-only,“g”代表Read/Write/Erase。也就是说,“a”所指明的区域为Bootloader 的空间,“g”所指明的区别为用户代码空间。大小由前面的数字决定,星号“*”前面的为Sector 的个数,后面的为Sector 的大小,这里的意思就是从0x08000000 开始,前面120 个Sector(每个Sector 为128 字节)为Read-only,后面1416 个Sector(每个Sector 为128 字节)为Read/Write/Erase。

 

再举另外一个例子,在\Projects\STM32L053C8-Discovery\Applications\USB_Device\DFU_Standalone\Src下的

usbd_dfu_flash.c 是这样定义的:

#define FLASH_DESC_STR "@Internal Flash/0x08000000/28*01Ka,36*01Kg"

它的意思就是前面28 个Sector(每个Sector 为1KB)为Read-only,后面36 个Sector(每个Sector 为1KB)为Read/Write/Erase。因为在这个例子中,用户代码起始地址为0x08007000。在Dfuse Demo 的界面中,你也将看到只有64个Sector,双击打开后能看到每个Sector 为1KB。

搞明白了这个事,就知道如何去修改这个描述符FLASH_DESC_STR,让它符合STM32L073RBT6的大小。

 

2.3.问题解决

STM32L073RBT6 有1024 页,每页128 字节,所以需要修改描述符FLASH_DESC_STR 定义如下:

#define FLASH_DESC_STR "@Internal Flash/0x08000000/120*128B a,904*128B g"


话题延伸:

如果用户代码空间的定义是这样的:

/* Start user code address:ADDR_FLASH_PAGE_120 */

#define USBD_DFU_APP_DEFAULT_ADD 0x08003C00

/* Start address of latest flash page: ADDR_FLASH_PAGE_1023 */

#define USBD_DFU_APP_END_ADD 0x0801FF80

但是描述符FLASH_DESC_STR 的定义修改为:

#define FLASH_DESC_STR "@Internal Flash /0x08000000/28*01K a,100*01K g"

那会发生什么情况呢?

将Bootloader程序编译后烧写到STM32L073 中,然后使用USB 接口进行连接,打开Dfuse Demo。首先,可以看到界面中显示的就是128 Sectors,双击打开,每个Secotor 大小为1KB。

接下来,来烧写一个用户代码,从0x08003c00 地址开始的。在Verify 时,就会弹出错误的对话框:

验证在0x08003C00 的地址就已经发生了错误:烧录文件该地址的数据为0x58,但是读回来的是0x00。这是因为我们把描述符FLASH_DESC_STR错误地定义成了前面28KB 为Read-only,也就是从0x08007000 开始才是可读/可写/可擦除的。所以,在0x08007000 之前的空间是不可擦除和写入的,也就导致了这样的情况。

这个延伸话题也只是为了强调这个描述符FLASH_DESC_STR的重要性。

结论

使用USB DFU IAP 参考例程进行移植的时候,Bootloader 的空间以及用户代码的空间的定义都需要根据具体的STM32芯片型号进行调整修改。


=============================================

往期话题链接:

1、ARM-MDK环境下从CCM RAM执行程序的介绍

2、STM32 CAN过滤器的几个术语

3、关于STM32定时器周期性地触发ADC的介绍

4、基于STM32应用的几个电源相关问题的案例分享

5、关于读取STM32 RTC 日历值不更新的话题


扫描或长按二维码可关注公众号

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存