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

【实战经验】STM32系列MCU模拟双盘符U盘的应用

[复制链接]
zero99 发布时间:2017-4-5 17:27
STM32系列 MCU模拟双盘符 U盘的应用

! H3 m, B3 O! S* N: J3 q应用背景
% a% V6 Y8 C3 m4 H客户使用STM32F429系列MCU,存储介质有两种,分别为SDIO连接TF-card,SPI Flash,目的是通过1个usb口连接到PC后,能够看到两个盘符,PC能够分别对TF-card和SPI Flash进行读写操作。
6 n. L& W/ @. v, k7 j* {7 J, b

- H' e$ u- \" b( T+ C7 T问题分析+ U( M) ?; s' @
抓包分析,出现STALL的情况
; N  o8 z& t# D$ a5 t
11.jpg 3 H1 X  [" r  Q
走读代码,发现函数
" b( d' H6 B: q+ Mstatic int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)7 F. {  K6 ?& k' x4 {# X% i
函数里面' s2 W5 E* t- J. f
if(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )& Z( _2 w1 p/ ^  @
if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)6 d3 j% ~: c. D9 y; }& ~! ~% F
if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)
' L- K8 d  E) z- f% o这几处如果不成功,就会返回,使得端点STALL!
" G+ u/ f5 [( v4 X% N/ s1 L
* @2 r' W/ N) q解决方案7 y* `; u. j# v* T  w% I8 R
考虑到客户使用的SPI FLASH,将block size设置为4096(而非通常意义上的512),因为这个SPI FLASH读写都是以4096Bytes为单位的。所以模拟利用stm32eval板,板上自带了tf-card的驱动,这时使用RAM模拟另一个盘,同时将其block size设为1024(容量有限,只要不是512即可),成功复现了客户的问题,走读代码,发现函数static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)% J. G* g" D+ R9 P* ~3 Y: C
函数里面
4 A( ~6 z4 m0 |  M4 Aif(((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) !=0 )1 _" Z4 w  C9 m5 ~0 ^
if( SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, hmsc->scsi_blk_len) < 0)5 X0 s  S- }0 c# z" ^8 A& d
if (hmsc->cbw.dDataLength != hmsc->scsi_blk_len)  q8 S/ W4 L- }( Y% h0 ~7 ?
这几处如果不成功,就会返回,使得端点STALL!0 x! R0 u0 d$ a% T7 g$ y
% ]( c7 a+ B( k4 T* d
继续跟代码,发现是这两个全局变量导致问题的(由于2个盘设定不一,导致使用混乱错误) hmsc->scsi_blk_size
2 s/ ?4 D* ]3 F  ~% I5 N5 \' |hmsc->scsi_blk_nbr
/ L6 r# }  B  [所以在读写的时候,需要对这两个全局变量进行重新赋值,如:; k+ D8 ^' z; _1 W& `, M) A
Switch (lun)
1 @/ x5 P. t+ Y/ H{( D" h( N. a6 g6 t4 A
     Lun 0: // TF-Card9 `$ W$ c6 X5 U$ s# [3 U4 R8 i
         hmsc->scsi_blk_size = 512 ;7 S- L2 b' q6 y# _. T* ]4 U
         hmsc->scsi_blk_nbr = tf-card_SIZE / 512 -1 ;
3 ]" G. v% M9 F$ R* @$ U" w0 |" m4 ?' Z% a! i4 O
        Break;
- ]8 s9 `1 y! F* h0 L+ |! T8 G' D+ r: ^$ E% N6 R
        Lun 1: // SPI-Flash5 E! b& O3 U% v/ O' r+ k
            hmsc->scsi_blk_size = 1024 ;
* @% V) C$ M, z" Q3 ~; Y0 n            hmsc->scsi_blk_nbr = 64 - 1; // use 64k RAM to simulate RAM-disk
: o/ t2 \1 i. V" K1 N; N$ C( q& P7 |0 {! g/ I7 Y, N; f
            Break;
; q& d( b* M8 c- b        Default:
: o3 O( H5 b: e  _& X( r8 D            Break;
7 H9 v+ I3 G" i& |0 O4 K8 @0 f}# ^# _0 o3 g& C
" V( s7 [+ k; a! f; M
附代码的使用 :! B/ D' F7 B2 v( {7 J9 W) N

1 {5 m8 k( q2 W/ W; X/ DSTM32Cube_FW_F4_V1.12.0\Projects\STM324x9I_EVAL\Applications\USB_Device
3 i# ]8 Q2 K& s0 g( L: [0 x
12.png ! C: ?) J+ D6 {2 X
MSC_2storage_test.7z
1 }* L; N  ]0 n  n3 l% `9 ^  I9 L! H& B& N1 ?
STM32Cube_FW_F4_V1.12.0\Middlewares\ST\STM32_USB_Device_Library\Class% U# r( v" n8 R2 f

7 Z& r2 z% p: y; vMSC.7z! z* w3 b' I2 q

% W/ P" F* ^$ o& T2 r总结
4 Z/ Z$ P/ q7 F8 {; N8 X6 W由于驱动本身只支持LUN 为1,当使用双盘符时,在usb device 端除了需要对LUN0 和LUN1 分开进行处理(读,写),还需要考虑一些全局变量,虽然在BOT 协议里,大部分值都是从PC 端,也就是HOST 端传下来的,但是会有一些全局变量并非如此,特别在两个LUN 的block size 不一致的时候,需要特别小心处理!
" B' }3 M  U# m1 Q, B2 W. y1 s
( q1 Q/ G# H* f: v3 X6 M7 _. \

0 v' g8 h$ ?& u/ n' b4 q STM32系列MCU模拟双盘符U盘的应用.pdf (210.48 KB, 下载次数: 181)
1 收藏 2 评论4 发布时间:2017-4-5 17:27

举报

4个回答
jinglixixi 回答时间:2017-4-5 18:09:45
已收藏,点赞!
arenas 回答时间:2017-4-6 09:40:57
感谢分享
jinshan2014 回答时间:2017-11-2 20:38:56
谢谢分享
pythonworld 回答时间:2017-11-3 07:24:40
谢谢分享!
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版