你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【实战经验】USB DFU IAP例程移植的两个话题

[复制链接]
zero99 发布时间:2017-4-5 17:53
USB DFU IAP 例程移植的两个话题
# d9 y5 H- V8 J1 _5 S, S
前言7 i6 ^0 k0 P0 _" d
在STM32 的系列产品中,很多型号都带有USB 接口,为使用USB 来进行代码升级提供了便利。这些型号中又有很大一部分可以通过内部System Memory 中的Bootloader 直接进行USB DFU 升级,具体哪些型号支持USB DFU,可参考应用笔记AN2606《STM32 微控制器系统存储器自举模式》。有些型号虽然有USB,但是System Memory 中的Bootloader 并没有支持USB DFU,比如STM32F102 / STM32F103、或者Bootloader V2.x 的STM32F2xxx、STM32F303,等等,或者用户希望通过不同的触发方式进入bootloader 来进行USB 下载,比如接收一串编制好的数据来触发。那么,就要使用USB DFUIAP 了。关于如何使用USB DFU IAP 的简要说明,可参考另一份文档《利用USB DFU 实现IAP 功能》。在这里,主要要谈的是在USB DFU IAP 例程进行移植时,需要注意的两个地方。" |. q( G( M2 s( _
8 F7 U1 v% j3 m4 U- P; R1 k

; l4 E! h% l% ]& w5 ?问题一
& N7 G; O- C& N, G6 f2 v某客户在其产品的设计中,使用了STM32L073RBT6。客户在开发过程中,使用STM32L0Cube 库中的STM32L073Z_EVAL的DFU_Standalone 进行代码移植,完成后在使用Dfuse Demo 软件烧写用户代码时发生了错误。
0 l1 D& u3 T  K+ B( v0 Z' _3 e
5 Z) N* ?( M7 @2 b( v6 ]6 E调研4 k0 o! [% l. F" K  J) M2 @
1.了解问题! x" e% r: u- _0 F
客户在开发中使用了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 Device in DFU Mode”。打开DfuseDemo 软件,也可发现已经识别到STM32L073 处于DFU Mode。
5 L1 Q: s3 v5 @/ t- e# ], `2 ~
11.jpg   S: ]9 X) T5 H+ e5 H4 y  y, M: P8 Q6 v
但是,当用户选择了“Verify after download”,并点击“Choose”按键选择用户代码.dfu 文件后,并点击“Upgrade”进行2 }- w9 ?, n0 g  f
烧写,发现弹出了提示发生错误的对话框,如下:( H5 U' z; ?, e+ w3 |0 Z  Z  X5 w
12.jpg ' h1 ~& `6 T0 x$ i

8 f( C: s( ~* m7 p5 ^% |0 v' Y2.问题分析1 t( X2 a8 c; y8 W3 {8 l, F6 l% x$ m. u
STM32L073Z_EVAL 开发板使用的芯片型号为STM32L073VZT6,其Flash 容量为192KB,地址从0x08000000 到0x0802FFFF。而客户所使用的STM32L073RBT6,其Flash 容量为128KB,地址从0x08000000 到0x0801FFFF。检查项目中的usbd_conf.h 文件中的代码,客户并未作任何修改,也就是说,以下两个定义没有根据实际的型号进行修改:
1 i( j- b, X; a4 X0 C0 H
13.png
4 B' l4 U4 R  W1 ?- D, O2 R: w - Q7 s/ }8 Q5 j2 M6 Q
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 页的地址。
: u. c2 k: {: o, U8 b4 y) F5 W7 i8 y$ T

$ w5 s: _  c/ E- ^0 e3.问题解决
* I) U8 y2 I% P. B( I3 z将usbd_conf.h 中的USBD_DFU_APP_END_ADD 修改为第1023 页的地址:: U" {! O1 {4 B: [+ P
14.png
" R4 ~- G# o5 E问题解决,USB DFU 可以下载代码了。可是别急,这样就已经修改好了吗?再来看第二个话题。3 D, ]5 C+ C  J3 U

9 x: u7 z' I7 p, G问题二6 u1 ]" ~/ M* E" h; \8 D, G& s
在问题的解决过程中,有没有注意到Dfuse Demo 界面中显示“1536 sectors”?这明显不对,来看看怎么修改。
5 R( P0 P2 I4 M$ d- t$ k0 ?调研
" r* L9 p9 g: V1 l/ y2 X, b1.了解问题8 J3 v) @% {( \; f* g  n" y2 a
在Dfuse Demo 界面中,双击“1536 sectors”,可以看到Internal Flash 的详细信息,如下:4 F+ ~! [  x1 L5 W
15.jpg
! i7 N+ n6 G. t  W3 s* A
4 I/ j/ W0 n0 N9 T! M1 c- @2.问题分析
/ ?6 f' b& O3 T9 N. P从上图可以了解到,实际上这里所定义的Sector 的大小为128Bytes,也就是STM32L073 的Page,所以这里的Sector 定义与STM32L073 的参考手册定义的Sector 是不一样的,不要造成误解。在RM0367 中,每128Bytes 为1 个Page,每32 个Page 才是1 个Sector。所以不要误会就行了。在这个Mapping 窗口中,也可以看到地址0x08003C00 之前的空间为Readonly,也就是Bootloader 所处的空间为只读,以避免对这部分代码的重写。而后面的空间,也就是用户代码所处的空间为Read/Write/Erase。! Y9 H1 I' k! G* a
这些信息是从哪里来的呢?其实它来自于usbd_dfu_flash.c 里边定义的描述符FLASH_DESC_STR,如下:
/ L( ^/ _3 F8 p7 V% k2 M
16.jpg
6 `+ B) j) z2 B( |' z' Y6 W来解释一下这个描述符的内容:
' X5 H- v+ {1 m9 G3 t2 J4 z0x08000000 为起始地址。“a”代表的是Read-only,“g”代表Read/Write/Erase。也就是说,“a”所指明的区域为Bootloader 的空间,“g”所指明的区别为用户代码空间。大小由前面的数字决定,乘号“*”前面的为Sector 的个数,后面的为Sector 的大小,这里的意思就是从0x08000000 开始,前面120 个Sector(每个Sector 为128 字节)为Read-only,后
' P# B5 `1 L1 F$ o' l5 S面1416 个Sector(每个Sector 为128 字节)为Read/Write/Erase。
: _( k: Y* L* y) ]4 j7 i! r0 u$ B: D/ w- x: b: l) S! A$ L
: ]4 [$ _/ ?& D7 w. p  a' s
举另外一个例子,在\Projects\STM32L053C8-Discovery\Applications\USB_Device\DFU_Standalone\Src 下的3 }- r( P. n3 V9 H8 I  d. G
usbd_dfu_flash.c 是这样定义的:
/ W7 O( A: `5 F; z2 P: O
17.png 2 O6 m+ r$ `' E0 R9 k8 @! A
它的意思就是前面28 个Sector(每个Sector 为1KB)为Read-only,后面36 个Sector(每个Sector 为1KB)为Read/Write/Erase。因为在这个例子中,用户代码起始地址为0x08007000。在Dfuse Demo 的界面中,你也将看到只有64个Sector,双击打开后能看到每个Sector 为1KB。
2 T) m) i) K6 o- o4 k* Q1 w  z3 j6 K% {$ a% q  h4 z
# d2 _/ F9 ~: j1 x; W1 s- ^
搞明白这个事,就知道如何去修改这个描述符FLASH_DESC_STR,让它符合STM32L073RBT6 的大小了。/ X/ E& z& o2 L# T* t1 @# Z
, i" Y: R" Z, S  N2 ]0 _" r1 Z0 X
3.问题解决
3 l: g8 V/ A/ V9 a0 uSTM32L073RBT6 有1024 页,每页128 字节,所以需要修改描述符FLASH_DESC_STR 定义如下:
# m7 u$ D7 f3 ?  ^
18.png - z+ A% M, }) L0 H
- e! M) z0 k! d" g" V# ~* k
附加话题
3 ]% l  N3 C$ s. k: \' I5 i0 z如果用户代码空间的定义还是这样的:& [" I, c% A- q: N3 `- F
19.png
4 Y9 F( F+ }+ I  m, L但是描述符FLASH_DESC_STR 的定义修改为:! P% }$ C7 K" c
20.png 0 B" p$ |. R9 \# }
那会发生什么情况呢?7 j2 N5 F, g& J6 v( Z, `  M
将 Bootloader 程序编译后烧写到STM32L073 中,然后使用USB 接口进行连接,打开Dfuse Demo。首先,可以看到界面中显示的就是128 Sectors,双击打开,每个Secotor 大小为1KB。
( w6 m; W; ?* l0 M
21.png
4 c) P! Y( [5 @

9 X, U! I  p2 x接下来,来烧写一个用户代码,从0x08003c00 地址开始的。在Verify 时,就会弹出错误的对话框:
! ~$ x* x$ u  G' P+ O) ~ 22.png + {/ J8 ]( o" w% M+ ^% G% u
验证在0x08003C00 的地址就已经发生了错误:烧录文件该地址的数据为0x58,但是读回来的是0x00。这就是因为我们把描述符FLASH_DESC_STR 错误地定义成了前面28KB 为Read-only,也就是从0x08007000 开始才是可读/可写/可擦除的。所以,在0x08007000 之前的空间是不可擦除和写入的,也就导致了这样的情况。这个附加话题也只是为了强调这个描述符FLASH_DESC_STR 的重要性。- k9 h  _- |8 {* f/ d& m
* m3 H& y/ a. e9 r$ C/ O
结论% I5 l" w# X0 ?, I5 h
使用USB DFU IAP 参考例程进行移植的时候,Bootloader 的空间以及用户代码的空间的定义全部都需要根据具体的STM32型号进行修改。

2 H% k, t6 O, b! p3 i
8 h! D9 [( ?/ R2 k% D* s1 ^( M% [
& H. Y, q- A- G* c+ r
. p/ |' [; ^! R/ }4 U5 V- t  l+ K
USB DFU IAP例程移植的两个话题.pdf (272.47 KB, 下载次数: 97)
1 收藏 3 评论2 发布时间:2017-4-5 17:53

举报

2个回答
斜阳 回答时间:2017-4-5 21:54:34
好文章
dfr3602 回答时间:2020-12-24 12:52:22
目前STM32部分MCU已经集成USB驱动,方便。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版