|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
对USB的初步了解
6 j; G* L0 K8 ~1、USB的优点:
- D6 E* R B& Z/ s- {1 r可以热插拔,即插上后可以自动识别; ! @* L8 v7 x$ A* ]* Y
. i% O! B O4 K% i4 I ! p# o, Z! `5 C0 P! t3 ]" ?" a
: q+ s2 V* `+ O) ?7 W! B系统总线供电,USB共有四根线,一根电源线,一根地线,一根D+线,一根D-线,D+和D-线是差分输入线;
7 U. h& ]* [5 q7 i1 R1 B! S! s3 [& T; e: h0 S1 y8 `
$ O: ?$ g7 C. ? y6 E2 m" R( e+ ~: y ]& w
可以支持多种设备,且扩展容易,通过HUB可以再一个主机上连接多个设备0 O2 p5 f% A/ w' z% `! P8 A
( ?. q9 ]4 v# M3 D9 T- F6 o传输数据的速度快,最快可达480Mbit/s5 r* M- b7 ^9 o
7 w- e3 V0 j; J$ c/ |+ A: z0 w6 d# E- ]; r) s
2 v, A t- P4 ? Z. c5 m% Z
方便的设备互联:在没有主机的情况下,实现点到点的通信(还可以实现主从互换)(USB OTG)/ x: x. {- l3 R' s+ L! A
4 D) x# j" M9 g4 `& J0 n; ]* \1 i. |6 m! y
$ J3 P, b, E9 Z% a( `0 `9 X$ P2、USB的基本规范:0 ?# g+ x6 W2 W8 a" I7 {" }
% G; r; A5 A) B9 hUSB1.0/1.1 & ~& g }) u( M+ p5 d8 G0 h
% f7 n, F$ Z6 g, n+ ]" V- b低速情况下1.5Mbit/s:键盘、鼠标等) d7 [- ]: T; B9 F* n' v' b2 p8 j7 c$ ?
全速情况下12Mbit/s:U盘、CD-ROM1 u; Z% c! f: }3 M% [
' t3 k# e! J7 U3 s8 o9 `2 f- a/ t2 }% c& l. L5 x& d- `8 x# n
/ r# H) b- B/ l) Q8 L4 _* B' A1 Z
USB2.0 $ @/ v) Q3 g0 Q( ^) [9 Q; L" S, s" {4 a& i* x( L1 j. q
高速达到480Mbit/s:音频设备、显示器等$ r& i5 x: l2 ]' ~5 e, i) u3 F n( m% s1 S
5 K: K8 V! H4 }6 H. o) p2 T/ K2 E3 u' ]$ Q9 N6 A3 M& K) U7 N9 P J
USB OTG
5 `* d7 T# z# k设备到设备的传输# f* d8 {/ S# R3 T' b5 L- h; e* C+ b1 R2 z; {
4 Y* @3 J; h+ V- d0 F7 _4 \& B& w" u% X& g1 ^* v* B
_5 p! {2 b! x8 u
/ W) K, c7 ]% ?2 {' L) F$ s3、USB设备类规范:, @% z4 b& w% D0 L+ n& c
大容量存储设备类(Mass Storage Device)U盘、CD-ROM等. z# a; Z( `- ^8 l; I
人机交互设备类(Human InteRFace Device)键盘、鼠标、游戏手柄% m' E3 x/ p1 a
语音设备类(Audio Device)麦克风、音响等, w% e E* s4 f1 b1 H" s
通信设备类(Communication Device)电话、调制解调器等2 |9 |6 T( L$ y9 F, k0 g: Y& q+ u
打印机设备类(Printer Device)打印机
+ I) H |% X+ x监视设备类(Monitor Device)显示器、摄像头等
( H! @) V" ]# a; }" A5 u/ \3 E# w/ n, B: B% h; K; b# W/ G7 V% j f4 D A: t
# R& J" _: Q" m; r& I# \% Q/ S3 u4、USB逻辑上分为3:信号层,协议层,数据传输层+ D% i' w$ a4 }: |5 V* [1 H! ]7 N& p( \4 ~
协议层:包是USB系统中信息传输的基本单位,所有的数据都是经过打包后在总线上传输的。* G! `" J/ E5 S7 Y3 W+ U5 v
4 `- e- U. f$ H4 S" G' a6 _& R
) h6 V/ b( O' r7 d7 F0 e5 j0 `
包由6部分组成:同步字段(SYNC);包标识符(PID);地址字段(ADDR);数据字段(DATA);检验字段(CRC);包结束(EOP)% s% z4 l6 A$ q4 o& P4 v
4 t% K3 I1 L3 n3 ~6 ?1 G$ q& r8 R$ o
' X" S" L% r" ~6 F* N, w4 b6 U" J/ z# Y4 s8 r$ j3 I- e) a9 |+ P
" r* C4 I/ L! f; T8 e包标识符(PID):令牌包(Token)(输出,输入,帧起始,建立),数据包(DATA)(数据,数据1),握手包(Handsnake)(确认,不确认,停止),专用包(Special)(前同步)5 K/ m, Z" {/ p8 J3 n5 i' T$ D, C$ {* G/ W; U
: s7 Q; M U1 u8 K8 f6 `2 ^! L1 [% Z( Z' R/ q0 W$ I) ]! g8 M
8 y* K" c( P! [# q' O% r$ m5、USB协议提供4种数据传输方式: f1 ^! X/ V y
6 i- X3 L, U" c' u$ R控制传输:突发,非周期性,由主机发起,用于命令和状态的传输& U P# l$ X: O& T, P3 g
& W. W. m& [+ G# O$ K6 q
2 P5 R$ H6 A, ~. l1 }4 a! t- F0 g% C3 \- s) @" Q* N" z
同步传输:周期性,持续性的传输,用于传输与时效相关的信息,并且在数据中保存时间戳的信息3 a$ F. d1 R1 |3 f4 z
F9 F6 ]" b4 m! @) ^
9 ]# { }- r( J$ E) s- U! N' A# P1 A1 L9 [
中断传输:周期性,低频率,允许有限延迟的通信
) c0 @" c6 {- a! L4 Q+ D
. x8 n# N: _+ q5 t$ e1 B, g$ B2 x# g
大容量的数据传输:非周期性,大容量突发数据的通信: g7 j9 @4 l0 d8 l2 Z5 x
3 G1 s% o0 _) L; {! G: D* }% {
/ y9 b$ d. k1 W6、USB描述符:' E" [7 o. q7 ?5 J5 L* r- d
1)设备描述符:描述设备的类型、厂商信息、USB的协议类型、端点的报数据的最大长度等,每个USB设备只有一个Device Descriptor: K! m/ z2 l4 N' }" J! T' ~* y: ^2 \; E, ?
6 @/ E- _* b& U: i9 W1 [6 T9 c4 p
) L- C2 E8 y. `5 I2 @2)配置描述符:每个配置描述符提供了设备特定的配置,描述了设备的接口和端点的性质、供电模式、设备的耗电) {- k1 e# c# b) z0 v6 @# X
w% a6 A4 L6 _* C( i
" Y2 q8 o4 b9 H
. X% p! C; w# w6 y5 G( t$ Q/ R3)接口描述符:描述了设备的不同接口的特性,例如,一个设备U盘的功能,又有键盘的功能,用两个接口描述符分别描述两个功能
' I5 j4 `2 h0 d, J% g5 W& T5 X9 D+ d" ]6 H( @; C: t" E
$ R6 W9 T0 P: R" D
- e J. V6 u: w% R) u4)字符串描述符:描述了设备制造商、设备名称、何序列号等信息6 ?6 W# s+ a+ `; N
( B! O( Q- n, d' U
) X. T' M) O# m, d6 B( J V& {. r v& F$ x& z) m( d2 L+ I
基于STM32制作USB的过程" Y& N! v* i' ~ z+ N% I: \' c
STM32的USB模块特性:# x: V: A. R% X8 o) g/ r P' e* Y1 {! l4 a* C8 @+ T
8 o2 V" ?. G; _- n. G( F, ~
遵循USB2.0全速设备标准, o! C$ ~* F9 N4 K1 L, S% q
+ b8 G& Y/ `* O" u8 Q6 l/ x
6 V0 }; @) p# U# p, t( Q0 K. v! v" X; u: T% m$ b: M. k
支持双向8个端点,8个IN端点和8个OUT端点(每个端点最大可使用512字节)
) @1 }$ V; [0 ^0 g) D( [- u" w8 H% b2 F6 Y
3 { ^# n: I3 W- |0 m
7 F! p6 o) F9 \: j[ 每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数]
% w1 v, r. }) h+ L& L9 c5 J, F8 Y6 P ~8 }
5 t; c- ?2 K5 B% _1 h5 d" `0 Y9 |8 t. x/ _! j, @8 x6 W. C; N/ z
# H+ f% F4 C* R1 t1 U' _( A% {( h硬件实现CRC自动生成/校验,NRZI编码/解码和bit-stuffing(位插入,位填充)' s" O: P: a$ m5 k( k0 m, I
% f t: h' H! H3 v1 G9 A5 u; t- O$ Q' r7 `) d/ V [, F' b5 K, }% _# D
% }9 ~# l+ U. G/ A5 K
支持控制传输、中断传输、大容量传输和同步传输四种传输方式0 v6 A7 M+ L d- K8 l+ P+ j5 a( G" C% V7 b: N+ B
k3 ^+ j* B/ B& { c: h1 ^6 I& c
* ]( W6 `5 @- t* r. {: D1 D# P
$ m" |2 a4 X" T, Z7 V, s, P( y支持USB的挂起和/唤醒
+ j$ \1 ]/ E7 S- l# M9 Q
6 S% ]# i; z7 F2 ~USB设备的实现过程
8 E6 n4 o. h* N2 {0 Y+ P( [系统初始化4 b/ e3 P7 c. g/ ?, ^! {
; b2 t3 V4 \2 i1 l1、 初始化系统时钟,设置USB时钟. O, d' s! X7 |8 m0 }) \6 h9 P; p6 W+ C
2、 配置USB中断,选择通道,设置优先级,使能中断! f$ W: I. M) V
% w4 m* }4 Z3 ]& P3、 配置GPIO( ]/ s" Y6 o D* _ P- }0 p
4、 USB的初始化,对描述符、设备的端点接口等的初始化
4 b+ y W$ s; V' \5、 FLASH的初始化, q' w; S/ d" V) R% S6 X; R6 s* I/ b; Q
9 `' @4 T5 j- |. J3 \2 m; d y! H- Y7 D; T% ]
6 @& S! D" y# m: T" H/ a一、 USB的枚举) C" _; E( O- C, s2 F5 w! F# h: E5 t
枚举过程就相当于主机和设备建立连接的过程(接头),Host向Device询问一些东西,Device将自身的设备类型,如何进行通信报告给Host,这样,Host就知道怎么对Device进行操作。
* r. S# c8 i; _0 _& h3 I 7 t* U: ]7 S5 E; p+ l7 L6 p: E% A7 E* Z$ t! Y5 D
在枚举过程中就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),此事件是特殊的OUT事件,数据方向Host->Device,SETUP事件数据长度固定为8。9 r2 q U3 x& k
" H# A/ N: B s. l S! B& a2 k: F+ s, o4 N& G7 }) Q/ H
9 O- @- o: v0 X+ u: Y
1、 在USB插入主机时,主机首先需要先对USB设备进行供电( H- T, m5 \) a# O+ P+ s5 z
* |2 @* J5 V4 u2 v* _4 ~9 |9 e6 a% ]( n2 d' u6 A9 V
2、 接着USB总线复位:6 O; t6 f, d7 G: U
# h0 Z1 |5 R& \5 p9 Q$ a8 u) ^设置分组缓冲区描述表起始地址;( s9 X+ I9 s' W7 O) @! O! j; |0 q! v' j4 n* F* i; m+ ?# A8 [! r, ?
初始化端点0,设置发送和接收状态。默认所有的设备地址和端口地址都会初始化为0.8 r2 N. [0 X# v" L* ?2 b( A( a) I$ o7 X }
6 Y; m8 s3 k9 k" t9 z
5 \5 S$ `3 C2 G- A% ]6 v7 ^. R4 O/ e" Z
3、 USB主机往端点0的0地址位置发送获取设备描述符的请求。$ w% D$ V6 F- o* v$ H8 J
5 @: L$ f* t3 r6 h/*发送请求属于控制传输的建立过程,控制传输包括建立过程,可选数据过程及状态过程,首先是主机发送一个令牌,其次是发送的数据,最后设备回应一个应答(握手包)*/$ `5 n8 I2 ?. b; N. U/ Y$ C* d! T- ?2 v3 X, t3 s8 E7 C5 u
, K6 L, {% e0 I8 I \0 d
4 e. b1 R+ R7 ?$ i3 M# p4、获取设备描述符信息
0 B7 _4 f; b3 U8 }( V4 f设备在接收到请求以后,首先需要对主机发送来的命令进行解析,并将要发送给主机的描述符信息填入USB缓冲区中,等待USB主机发送IN命令,主机在接收到设备发送来的ACK回应以后,发送IN令牌包,从而进入到数据过程,之前存储在USB缓冲区中的描述符信息发给主机,并等待主机的应答。主机在正确接收到设备描述符的信息时会返回一个确认信息。
s, V; z& @1 d# E) ~" e! u8 E
; E o5 J, Q' ?0 {+ x% Q; z1 i* O4 x% ~" s7 h. i
) B6 c' q |" s' i- U" L5、主机给设备分配一个新的地址+ A: X4 u$ H2 L3 d+ z
, @, [- R; f5 {: G该阶段是一个没有数据过程的控制传输。首先,在建立过程中主机往设备的端点0发送一个设备地址的请求,新地址在建立过程的数据包中。在建立过程之后直接进入到状态过程,在状态过程中,设备等待主机发送一个IN令牌包,收到IN令牌包后,设备就会返回一个数据包,如果主机确认该数据包正确接收,就会回应设备一个ACK,设备收到ACK之后启用新的设备地址
, j% O% j- B- P/ F% {- U- y p! _# j" C" F( q5 a. Z
& l( A2 ]( C5 X. q$ z Y% z% j7 w8 w
# C }1 e8 C. L2 s' s6、 主机重新获取设备描述符,配置描述符和字符串描述符(如果是HID还要获取报告描述符等): ~% P7 G, V) q) m
至此USB的枚举过程完成,主机可以根据枚举的过程了解到的设备信息对USB安装驱动程序,并对USB进行操作。4 d* _4 c3 \/ g' y+ K. J& K8 t& K) \
7 a4 |- p- I& B2 V K
& o) r) g- F/ |8 Z' ]1 F$ |3 w0 _6 E二、 对程序的分析9 E4 L7 M( o! N8 @% _: L9 x4 H
+ ]2 Q& c% `/ P" `- t# r: S& u1、 在Set_System()中首先配置了RCC时钟,在设置并开启USB的时钟RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
6 R! S6 R7 l3 e5 H) V* O8 b3 c9 Q; [1 H
0 f" O5 V& n3 u+ c/ _- w+ r) M: M3 f
2、 对USB的引脚的设置,主要设置上拉电阻,对于此STM32板子而言是设置PC13为开漏输出(GPIO_Mode_Out_OD)1 Q7 H7 o: |% W3 t% {. O
0 H: p+ ]; e8 |
& q& \3 }! `$ `$ V6 Q: I! g) Y8 m( _7 M" r$ I: P) V7 S9 b8 q
% y( j$ x5 h. V3 q3、 USB中断的设置,设置了USB_LP_CAN_RX0_IRQChannel中断,因为在USB传输的过程中使用的是控制传输过程: z, R5 f; l8 a8 }5 l* @
* a( K; H' {$ \8 s# O2 E0 ]7 u- E3 h
: O. _6 P9 \ O7 _/ D0 ]
4、 最后对USB的初始化,初始化USB的控制状态为IN_DATA状态,对一些需要使用的指针的初始化,包括设备信息,设备标准请求,设备的支持等的初始化,供枚举过程的使用
8 i& _# V" j ~" n7 w1 @7 W% v/ Y7 `- k1 Z
; i- k* o7 Q) y% L1 h& ]) P5 N; T
至此,对于USB设备的初始化过程已经完成,接下来进行USB的主要程序部分,也就是枚举过程。! Y* l5 @$ n# O% c
& A: K. W ?9 O+ M; `
* E, V, h; \7 O+ o4 H( y5 J
, a+ P1 x8 n# b T5 }, p6 n插上USB之后首先会进入中断过程,执行USB_Istr()函数中的操作,逐步进入枚举过程,接下来从中断操作开始分析6 t: `4 d* {/ \+ z& z% x! O% B" l; g+ d$ T4 ?
! X" k ]0 n: [; F' d. Z+ K; o6 y- O& @' }
6 Y" ~" u* \6 M3 ]' t! R1、 进入中断执行USB_Istr()函数后,首先获得中断的状态,因为在初始化阶段,首先先对USB进行了复位操作,所以直接可以进入Device_Property.Reset()函数进行复位操作。6 s9 E( R% A$ x' n6 ?- s- p* V3 O
/ d! R* I* r) J. j% \: H, b; C
# {1 L2 y& A3 N4 N& l得到USB的各类描述符值,设置报表地址为0x00,端点地址为0x00,又对USB的端点0和端点1的进行了初始化设置/*在usb_prop.c文件中*/7 e- n( {3 H- L. ~7 X7 W6 e8 [: x( D1 q, K& d4 @6 v
- |, }0 x- Z# V1 L
6 _4 d# t- S- ^+ A3 U8 w* Q9 ] u( |" m8 X, Q Z9 D+ I" H( ^1 E! E0 ]) _. p
2、因为在USB枚举的阶段是通过控制传输的传输过程来实现的,所以数据的发送接收,通过CTR_LP()中断进入的1 x4 T I) c6 k1 A% k4 I. D- U4 `4 {( X1 U# @5 L
1 a3 |# M' H( F' ~% u在这个函数中等待中断状态设置好,并且数据发送正确。然后检查是不是端点0的收发数据,因为在一开始枚举阶段首先是通过端点0来接收主机发来的数据,所以直接进入端点0的函数中if (EPindex == 0)。等地啊主机的IN命令if ((wIstr & ISTR_DIR) == 0),接着进入In0_Process();函数往主机中发送数据。进入In0_Process()函数以后首先要判断控制状态是IN_DATA、LAST_IN_DATA 、WAIT_STATUS_IN中的哪一个或者都不是。+ L$ T! W" m* T7 \7 S
" R4 Z% F- P2 E9 h2 n1 Z7 a. l5 X& f/ R4 R: `% n
+ l5 b: _6 c z" u2 O
; J* A1 W3 z2 f$ d3 c# |+ E* q等待数据的发送,假设是IN_DATA或LAST_IN_DATA,则进入数据发送阶段DataStageIn()函数,主要是发送开始存入缓存区中的数据,以描述符为主,发送给主机。! y6 w5 m! L- F) p
. K1 g! z; m/ f$ O @
! ], |$ ?; P0 R" }; g9 R' h2 a) x* ?) g' N8 {( `
3、在主机接收到USB发送来的数据之后,主机会重新给USB分配新地址,这是进入中断在轮询时会检测到((wEPVal & EP_CTR_RX) != 0)进入到USB的接收状态,接着会执行Out0_Process();的主机输出,USB接收状态。此数据输出主机的过程与上面数据输入主机的过程相类似。也会初始化数据包长,并根据数据长度来进行数据的接收状态。
) i, k+ O& D. \1 u2 n+ Y9 ?. w2 d
; g( w7 u( b- l8 Q* L% {5 ] ]数据从主机SB和数据从USB写入主机主要由UserToPMABufferCopy()MAToUserBufferCopy()两个函数来完成& j6 J! Z% c/ d: g* J, n; o6 {" O+ `+ Y. y0 ?5 ~2 b& Q: N( d- l
$ v' \( [ ^5 M( h# [
! c; d5 m: p1 @! `& z
/ W+ ~; ~' G: M3 o7 B4、接下来主机会以分配给USB的新地址来与USB进行数据通信。通信过程与之前相类似,只是不再使用端点0,而是使用新地址,非0端点的处理。9 m8 I6 _8 d! v& L; |0 M1 a% Q* V* A. w( A
7 m; g* {. b2 o. M6 P& |" i2 v接下来说一下USB不同的c文件的功能:
; _! y; \& H0 W% ]Usb_core.c枚举过程重要的函数在此列出,包括数据输出主机的函数DataStageOut()数据输入主机的函数DataStageIn(),非0数据包的建立Data_Setup0(),0数据包的建立NoData_Setup0(),还有主机发送的IN进程In0_Process(),主机发送的Out进程Out0_Process()。还有一些标准的配置函数,接口设置函数等等。
8 z5 a( _( ~8 l( ?; ^
! {* L/ m+ b3 q2 u6 m/ B9 t! @% ? i1 X
Usb_init.c这个c文件中只包含一个主要的函数USB_Init(),这里主要是对在usb_core.c中使用的重要指针的初始化,包括pinformation,pProperty和pUser_Standard_Requests这三个指针,另外就是在初始化状态时已经将usb的控制状态设置为IN_DATA状态。并将USB初始化为初始配置,上电,开始设备的状态为未连接状态等 ?9 e) K8 G0 Q+ r) y7 B) W9 V( i6 v, `- I
% s1 v, {0 j1 O' C" b2 _) j0 r" s0 B6 A" N% D1 G
9 |: L" Y% W6 T' ?& K- X; t/ i4 H' S! [9 Y0 [- j% p
Usb_int.c包含两个主要函数CTR_HP()和CTR_LP(),CTR_HP()用于处理高优先级中断,用于同步传输模式和批量模式(双缓冲区),CTR_LP()用于处理低优先级中断,用于控制传输,中断传输和批量传输(单缓冲区)。; c7 X% q$ E$ D0 f; w
/ ?& C5 L) y* k9 \: o" f( p
4 @) L/ v2 n- {1 t' O% E$ r
Usb_mem.c包含两个函数PMAToUserBufferCopy()和UserToPMABufferCopy(),是将PMA缓冲区的数据传给用户,和将用户缓冲区数据传给PMA缓冲区的主要数据传输过程。- I: c0 G' z- K! `+ f8 g9 R& x4 g+ `9 M# }& n9 @) ]# p- ]6 I
( h! w9 \; l) \& j& r+ `( ?& K- `+ C; W$ T2 i& G
1 [/ K: k0 k8 m5 f9 v
Usb_regs.c主要是调用宏,实现寄存器的操作,但是上层函数很少调用这些函数直接就是用宏。& O2 F& U6 Q. V, u' p% @3 |6 [+ [9 ~& z. n% ^: C- S4 G
+ j6 w. u5 j; u
( ?; }- P6 g8 s. _& e& P4 r' m3 Q
Usb_pwr.c主要是包括对一些电源的配置,包括USB上电PowerOn(),USB断电PowerOff(),挂起函数Suspend(),处理唤醒恢复操作Resume_Init(),状态机处理和恢复函数Resume(); h: K/ _. g8 |9 n- _6 Y+ I" m
7 ]5 K1 _6 S3 F8 \Usb_desc.c主要是对描述符的定义,有CustomHID_DeviceDescriptor[18],CustomHID_ConfigDescriptor[],CustomHID_ReportDescriptor[],CustomHID_StringLangID[],CustomHID_StringVendor[],CustomHID_StringProduct[],CustomHID_StringSerial[]。
! Z7 D9 T' C% c* VUsb_prop.c是对一些获得描述符的设置,还有复位和初始化的设置,主要的函数是CustomHID_init()和CustomHID_Reset()两个函数
* G/ k: H0 Y: C& f3 B4 ?1 D |
|