|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
对USB的初步了解1 y& }/ K8 n( T4 I% J
1、USB的优点:
( x& Q2 y0 N3 B. Z+ Q+ R- q7 r可以热插拔,即插上后可以自动识别; ! @* L8 v7 x$ A* ]* Y
9 v0 I) f6 [* c+ c2 l6 j5 p2 N6 p7 l ! p# o, Z! `5 C0 P! t3 ]" ?" a* t) N# o; V) T
系统总线供电,USB共有四根线,一根电源线,一根地线,一根D+线,一根D-线,D+和D-线是差分输入线;
+ d! m+ o2 [3 H8 W( R# D6 n& f! I/ J% m. H- v: ^
$ O: ?$ g7 C. ? y6 E2 m
, h1 _- E7 n4 q5 _6 ^可以支持多种设备,且扩展容易,通过HUB可以再一个主机上连接多个设备0 O2 p5 f% A/ w' z% `! P8 A% i/ { l9 m" {9 W
传输数据的速度快,最快可达480Mbit/s5 r* M- b7 ^9 o. J- y2 v% f1 H
3 A S* |& j. Z- _8 T5 c
/ K$ I3 H* _ r2 S: o5 W% E) s$ [方便的设备互联:在没有主机的情况下,实现点到点的通信(还可以实现主从互换)(USB OTG)
6 F6 ?# j+ U/ F1 U% S% F, t8 d& a4 D) x# j" M9 g4 `& J
1 g7 F' j: x; k0 U5 b
6 Q4 P+ V+ T0 D2、USB的基本规范:0 ?# g+ x6 W2 W8 a" I7 {" }
% ?* @; |8 @3 O, n+ t" V WUSB1.0/1.1 & ~& g }) u( M+ p5 d8 G0 h8 s: C- P9 R% I0 M4 I4 t1 d* K
低速情况下1.5Mbit/s:键盘、鼠标等) d7 [- ]: T; B9 F
4 c0 W. ^5 ]" J) r$ t全速情况下12Mbit/s:U盘、CD-ROM1 u; Z% c! f: }3 M% [
3 n( z" T& q0 x- N6 @5 C! W0 J, W. j) s& h. R! j: O- X( s# g
J4 Y6 F; A; `1 s9 V6 L3 e0 P
USB2.0 $ @/ v) Q3 g0 Q( ^) [9 Q; L" S. H6 L5 z. u) m2 x/ x6 O. [* g- t
高速达到480Mbit/s:音频设备、显示器等$ r& i5 x: l2 ]' ~5 e, i) u5 n! Q- M' ^/ [
7 @$ ~5 g0 {. O: M' @6 H. o) p2 T/ K2 E3 u' ]$ Q
9 @! [0 |8 j$ e/ IUSB OTG # |+ u( {0 |4 G' Q+ V
设备到设备的传输# f* d8 {/ S# R3 T' b5 L- h; e
! d' T( X/ S$ E$ h. l: t. _4 Y* @3 J; h+ V- d0 F7 _
6 C. G, z( D" ] _5 p! {2 b! x8 u
; ~0 R# K3 j( I6 s% ~) g# \9 ?3、USB设备类规范:
' ]" D3 ~1 x( j# d2 i大容量存储设备类(Mass Storage Device)U盘、CD-ROM等 m; A$ }- q$ H i: }9 q
人机交互设备类(Human InteRFace Device)键盘、鼠标、游戏手柄
7 b. A6 A+ r! d. @语音设备类(Audio Device)麦克风、音响等
* h2 u# U1 w4 v5 X2 F2 ^通信设备类(Communication Device)电话、调制解调器等
; y9 I$ w8 _5 r' q打印机设备类(Printer Device)打印机8 I2 F! M& X; E: M1 W( z
监视设备类(Monitor Device)显示器、摄像头等
8 _& o/ T% L+ U( @1 o# B4 L/ \3 E# w/ n, B: B% h; K; b$ U7 I" [/ W3 h: S, g8 i
& \/ ^) k8 b9 q5 x- D4、USB逻辑上分为3:信号层,协议层,数据传输层+ D% i' w$ a4 }: |5 V* [
8 o/ Q# a3 y/ }( S# E协议层:包是USB系统中信息传输的基本单位,所有的数据都是经过打包后在总线上传输的。
% h: s1 \4 i8 H A! f. F2 b4 `- e- U. f$ H4 S" G' a6 _& R
( L1 F' w2 z3 y; B; t. ~7 _; Z, v0 W( |7 J9 R4 A
包由6部分组成:同步字段(SYNC);包标识符(PID);地址字段(ADDR);数据字段(DATA);检验字段(CRC);包结束(EOP)% s% z4 l6 A$ q4 o& P4 v. E' \! G* Y' L/ Z
3 ~6 ?1 G$ q& r8 R$ o, N1 V* Y8 A) S# R2 g& U
4 b6 U" J/ z# Y4 s8 r$ j3 I- e) a9 |+ P) G6 X( u; k2 W/ i3 {5 S4 [& b* n
包标识符(PID):令牌包(Token)(输出,输入,帧起始,建立),数据包(DATA)(数据,数据1),握手包(Handsnake)(确认,不确认,停止),专用包(Special)(前同步)5 K/ m, Z" {/ p8 J3 n
2 N+ V' t- `4 `; V, h7 i3 C0 e7 X8 f, i% @; t8 G
! L1 [% Z( Z' R/ q0 W$ I) ]! g8 M
+ u. W- k# d5 ^$ j' m/ o& U' a$ @5、USB协议提供4种数据传输方式: f1 ^! X/ V y
$ V( x4 d+ o/ Z7 S' M1 L V控制传输:突发,非周期性,由主机发起,用于命令和状态的传输8 ]) A" G& c3 t
& W. W. m& [+ G# O$ K6 q& Y, k5 n# {! ^6 N/ P
& o' s* a5 l, b v
同步传输:周期性,持续性的传输,用于传输与时效相关的信息,并且在数据中保存时间戳的信息
. w Y1 S5 d: D* Z F9 F6 ]" b4 m! @) ^
6 \, T5 v5 j8 [1 X; X
. K) S# m" i; v: s7 F8 f中断传输:周期性,低频率,允许有限延迟的通信
8 Y1 l0 I8 n' d% F* M) n: p4 ~( Q! ]/ u" k( r/ H/ Z
) ^3 I% o- }& n. b/ h" U; O, s
大容量的数据传输:非周期性,大容量突发数据的通信
4 k) L, l" L( Z0 Z9 s6 N6 Y
2 i4 U, u$ ^, C1 c1 A
! m. k* a: Y H( R p( s% H6、USB描述符:
, @0 h ~+ ^' X \/ C1)设备描述符:描述设备的类型、厂商信息、USB的协议类型、端点的报数据的最大长度等,每个USB设备只有一个Device Descriptor: K! m/ z2 l4 N
7 {: V3 w; v# v# o* @9 l9 R
& ~% k, z0 C9 c9 Q# h, f
4 }% ^: G$ A4 A$ X" ^. M2 c( n" C K2)配置描述符:每个配置描述符提供了设备特定的配置,描述了设备的接口和端点的性质、供电模式、设备的耗电
9 j- F# q9 B0 q# o5 `2 }8 {
R5 }: p+ w% h! P- b" Y2 q8 o4 b9 H
2 v) U6 |% W4 F& y2 |# [3)接口描述符:描述了设备的不同接口的特性,例如,一个设备U盘的功能,又有键盘的功能,用两个接口描述符分别描述两个功能7 i! x7 a3 Z+ d+ r/ u: b( r9 T9 G
5 W& T5 X9 D+ d
0 i, M- B/ ], B. w9 y$ R6 W9 T0 P: R" D
( C8 R5 c* I$ ]) f1 l `$ ~4)字符串描述符:描述了设备制造商、设备名称、何序列号等信息( D) i; c( s7 ?6 U2 `5 }% m
6 ?9 }2 h7 L% t b
) X. T' M) O# m, d6 B( J V$ l9 l3 l5 T# [
基于STM32制作USB的过程" Y& N! v* i' ~& g8 |! _+ {2 } I2 G. i; w L
STM32的USB模块特性:# x: V: A. R% X8 o) g/ r# r& T6 `" W9 }! A* G4 z
+ { S/ ?9 C* O6 o+ d, A' x: p" _5 S遵循USB2.0全速设备标准
% B' a* g% r( u7 m+ L$ _3 b! ]+ b8 G& Y/ `* O" u8 Q6 l/ x+ s' Q% _1 V; }) _
+ J4 M0 w) \$ D# X# [
支持双向8个端点,8个IN端点和8个OUT端点(每个端点最大可使用512字节)9 M j" x. `$ t0 V% @ W5 [; p
0 g) D( [- u" w8 H% b2 F6 Y
1 Z2 g5 F" n* v& c8 Z3 P! N) E4 N. T/ O$ V
[ 每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数]
7 @6 e/ K& Z; ]7 I9 c5 J, F8 Y6 P ~8 }% R8 c4 T7 |: K5 }; x' l/ F; e. D
8 t. x/ _! j, @8 x6 W. C; N/ z6 S0 ^7 m# s- X- t: [: R1 _1 ]
硬件实现CRC自动生成/校验,NRZI编码/解码和bit-stuffing(位插入,位填充)' s" O: P: a$ m5 k( k0 m, I+ S5 v2 L0 p. j6 f( k1 r
1 G9 A5 u; t- O$ Q' r7 `/ [: k! q/ S8 j( _+ `. `
1 G8 v+ y9 O+ `9 I+ D' v支持控制传输、中断传输、大容量传输和同步传输四种传输方式0 v6 A7 M+ L d- K8 l+ P+ j5 a( G
0 N: k/ ]% h4 D0 v4 [8 g k3 ^+ j* B/ B& { c: h1 ^6 I& c! Q6 g* P/ w% y- X* ]% g! ~7 X
+ P- ?! ~( F. c" e' O" [- P
支持USB的挂起和/唤醒4 a' G1 Z# M4 w! S- U& I, J
' w5 U6 I+ e( s
USB设备的实现过程
9 y# ]9 V! ?. }/ @ R- J系统初始化4 b/ e3 P7 c. g/ ?, ^! {5 U2 E+ y2 \% I7 \) g1 D
1、 初始化系统时钟,设置USB时钟. O, d' s! X7 |8 m R+ H1 i+ y" b* I$ O* l1 I
2、 配置USB中断,选择通道,设置优先级,使能中断! f$ W: I. M) V
6 o( r& d# Y* |+ e5 u* W3、 配置GPIO6 w, ^7 z- ^$ U! Z; M
4、 USB的初始化,对描述符、设备的端点接口等的初始化* l1 [) M5 b0 G* Z1 o0 u
5、 FLASH的初始化, q' w; S/ d" V) R
' I% P( C9 c y4 u9 A+ Y; F. P) R6 q) g: m2 r
; d y! H- Y7 D; T% ]
4 O' Z @6 J1 h* u一、 USB的枚举
6 f# y+ F% V7 i& L$ |& U; O枚举过程就相当于主机和设备建立连接的过程(接头),Host向Device询问一些东西,Device将自身的设备类型,如何进行通信报告给Host,这样,Host就知道怎么对Device进行操作。0 B+ A5 i5 _( l! F+ `2 A( ^# f
7 t* U: ]7 S5 E; p7 E$ t' ], i0 X: a2 C; d1 I. P J1 C" `
在枚举过程中就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),此事件是特殊的OUT事件,数据方向Host->Device,SETUP事件数据长度固定为8。
& q9 a& {" Q: ]0 q; k+ s& g" H# A/ N: B s. l' W4 _/ f" Z+ ?0 j+ O; h
, z; T7 d6 h1 O6 ]0 `1、 在USB插入主机时,主机首先需要先对USB设备进行供电( I: j6 t. |" D
9 [0 N4 _. \: x" `' a
+ [3 G( y( K4 [) n G, |2、 接着USB总线复位:6 O; t6 f, d7 G: U. b5 o7 G; W8 \% Y1 b2 t
设置分组缓冲区描述表起始地址;( s9 X+ I9 s' W7 O) @! O! j; |0 q! v' j4 n9 C- V5 r% A" a) {' v4 D* y
初始化端点0,设置发送和接收状态。默认所有的设备地址和端口地址都会初始化为0.8 r2 N. [0 X# v" L* ?
B' p$ s8 q8 W2 r* U3 k7 l
' X8 ]$ b; }, W: ^( w5 \5 S$ `3 C2 G- A% ]* \' r0 b9 A0 `& D, d" O* w7 T
3、 USB主机往端点0的0地址位置发送获取设备描述符的请求。$ w% D$ V6 F- o* v$ H8 J5 T2 z# K" A& o! {" a: I
/*发送请求属于控制传输的建立过程,控制传输包括建立过程,可选数据过程及状态过程,首先是主机发送一个令牌,其次是发送的数据,最后设备回应一个应答(握手包)*/$ `5 n8 I2 ?. b; N. U/ Y$ C* d3 X2 x s2 M- }) `9 J
3 v' p+ P: X; S' ?
- F- r$ a8 Q X1 p# s& n9 V
4、获取设备描述符信息* B( L6 t( \3 b9 `, |) w
设备在接收到请求以后,首先需要对主机发送来的命令进行解析,并将要发送给主机的描述符信息填入USB缓冲区中,等待USB主机发送IN命令,主机在接收到设备发送来的ACK回应以后,发送IN令牌包,从而进入到数据过程,之前存储在USB缓冲区中的描述符信息发给主机,并等待主机的应答。主机在正确接收到设备描述符的信息时会返回一个确认信息。
1 b( o. D( o& c" \4 ^! ^ L8 f$ E1 b, o$ D& V8 G
* O4 x% ~" s7 h. i
; x4 D2 M9 I: R5、主机给设备分配一个新的地址+ A: X4 u$ H2 L3 d+ z
8 v9 e6 m4 C" A6 N5 G" G该阶段是一个没有数据过程的控制传输。首先,在建立过程中主机往设备的端点0发送一个设备地址的请求,新地址在建立过程的数据包中。在建立过程之后直接进入到状态过程,在状态过程中,设备等待主机发送一个IN令牌包,收到IN令牌包后,设备就会返回一个数据包,如果主机确认该数据包正确接收,就会回应设备一个ACK,设备收到ACK之后启用新的设备地址
; C' C8 O4 j3 j7 P2 O- T p! _# j" C" F( q5 a. Z( b8 {( {* m/ G& h) M
2 A7 {+ G- p$ B$ y! H
6、 主机重新获取设备描述符,配置描述符和字符串描述符(如果是HID还要获取报告描述符等)
) }) I2 @+ y& C9 d. Y% Y- g至此USB的枚举过程完成,主机可以根据枚举的过程了解到的设备信息对USB安装驱动程序,并对USB进行操作。
" m. R$ ]9 {% L9 ?* b7 a4 |- p- I& B2 V K
' K+ T9 ` S1 `$ A5 ?/ ~二、 对程序的分析9 E4 L7 M( o! N8 @% _: L9 x4 H
0 k1 ^, m/ s2 J1、 在Set_System()中首先配置了RCC时钟,在设置并开启USB的时钟RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);4 ]( F& c( g- ~ r9 R1 N- [+ d. [) L
( P! j7 p; N c0 f" O5 V& n3 u+ c
( p4 u) q4 D# v K7 v2、 对USB的引脚的设置,主要设置上拉电阻,对于此STM32板子而言是设置PC13为开漏输出(GPIO_Mode_Out_OD)1 Q7 H7 o: |% W3 t% {. O9 _) x( ?" s) P# Y1 `( h3 U
' j* P* U- R# g, ^! g) Y8 m( _7 M" r$ I: P) V7 S9 b8 q
8 z4 Y# C5 X' n3、 USB中断的设置,设置了USB_LP_CAN_RX0_IRQChannel中断,因为在USB传输的过程中使用的是控制传输过程: z, R5 f; l8 a8 }5 l* @: O- m* F2 G0 J' \% u+ r* E
8 j+ i7 x# Q) h# s) o- G
) _2 v+ _1 X. j4、 最后对USB的初始化,初始化USB的控制状态为IN_DATA状态,对一些需要使用的指针的初始化,包括设备信息,设备标准请求,设备的支持等的初始化,供枚举过程的使用
' V+ {) ^+ H- r8 Y$ R- ?, N; ?; O- I ]! W. y; l
& T; @- V6 ^2 N: M
至此,对于USB设备的初始化过程已经完成,接下来进行USB的主要程序部分,也就是枚举过程。
8 L5 d) ^! ?& e3 t6 O8 n5 \8 w( j
* E, V, h; \7 O+ o4 H( y5 J% Q8 C7 _9 K4 U& z# F7 a' Z
插上USB之后首先会进入中断过程,执行USB_Istr()函数中的操作,逐步进入枚举过程,接下来从中断操作开始分析6 t: `4 d* {/ \+ z& z% x
- }+ A* Z6 i2 {* m( b. s. R( t. y8 H( Y( a+ i6 b
; o6 y- O& @' }
: t; Q& m& U5 G4 q& U1、 进入中断执行USB_Istr()函数后,首先获得中断的状态,因为在初始化阶段,首先先对USB进行了复位操作,所以直接可以进入Device_Property.Reset()函数进行复位操作。6 s9 E( R% A$ x' n6 ?- s- p* V3 O3 _1 U8 a$ N- A7 v% [1 d
; Y, X/ U5 ^/ w# z4 M; m5 `* }! k! o
得到USB的各类描述符值,设置报表地址为0x00,端点地址为0x00,又对USB的端点0和端点1的进行了初始化设置/*在usb_prop.c文件中*/7 e- n( {3 H- L. ~7 X4 u2 x9 h6 a, K
- |, }0 x- Z# V1 L& ^5 u, |" g/ l e! N/ O
3 U8 w* Q9 ] u( |" m8 X, Q Z
$ o( j" ]; U# u$ F5 K2、因为在USB枚举的阶段是通过控制传输的传输过程来实现的,所以数据的发送接收,通过CTR_LP()中断进入的1 x4 T I) c6 k1 A% k4 I. D i- [- y3 w. r' U7 w$ G
! V5 @5 ?2 t( U: C
在这个函数中等待中断状态设置好,并且数据发送正确。然后检查是不是端点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
8 {& l# G5 u) y b3 u+ k$ f2 B7 a. l5 X& f/ R4 R: `% n
$ }: i! s0 m1 F: S9 s
$ M2 n$ m5 _5 |6 ]等待数据的发送,假设是IN_DATA或LAST_IN_DATA,则进入数据发送阶段DataStageIn()函数,主要是发送开始存入缓存区中的数据,以描述符为主,发送给主机。
1 c% ?8 l; O, J; q2 a8 J2 w: a. K1 g! z; m/ f$ O @
+ U7 \/ d" P D" }' K' V' z. F& g8 f3 Q0 O/ Y
3、在主机接收到USB发送来的数据之后,主机会重新给USB分配新地址,这是进入中断在轮询时会检测到((wEPVal & EP_CTR_RX) != 0)进入到USB的接收状态,接着会执行Out0_Process();的主机输出,USB接收状态。此数据输出主机的过程与上面数据输入主机的过程相类似。也会初始化数据包长,并根据数据长度来进行数据的接收状态。
& O$ ~/ D+ [' {
- a6 Y( r& N) }6 C8 ]2 m7 R }/ e0 e4 r" t8 R4 ?2 d& ]# W
数据从主机SB和数据从USB写入主机主要由UserToPMABufferCopy()MAToUserBufferCopy()两个函数来完成& j6 J! Z% c/ d: g* J, n; o6 {" O. u/ K7 y0 f) b1 G( B) c, g w- u& H
$ v' \( [ ^5 M( h# [
4 u% I4 |3 z/ o7 U: Z8 A
3 }$ t( g) ^+ K2 S4、接下来主机会以分配给USB的新地址来与USB进行数据通信。通信过程与之前相类似,只是不再使用端点0,而是使用新地址,非0端点的处理。9 m8 I6 _8 d! v4 b& ?% @: {! i6 G/ Q9 _" A
c0 Q4 A" B# C+ b; A4 Z接下来说一下USB不同的c文件的功能:; }4 B5 ]& A f2 e b
Usb_core.c枚举过程重要的函数在此列出,包括数据输出主机的函数DataStageOut()数据输入主机的函数DataStageIn(),非0数据包的建立Data_Setup0(),0数据包的建立NoData_Setup0(),还有主机发送的IN进程In0_Process(),主机发送的Out进程Out0_Process()。还有一些标准的配置函数,接口设置函数等等。/ u, E& n- m( j* ~ |/ B
- M0 Y3 n; J' c \# U0 B- W) s$ e0 N* O
Usb_init.c这个c文件中只包含一个主要的函数USB_Init(),这里主要是对在usb_core.c中使用的重要指针的初始化,包括pinformation,pProperty和pUser_Standard_Requests这三个指针,另外就是在初始化状态时已经将usb的控制状态设置为IN_DATA状态。并将USB初始化为初始配置,上电,开始设备的状态为未连接状态等 ?9 e) K8 G0 Q+ r) y$ r' D0 T" w# Z% B) z% ?/ J
% s1 v, {0 j1 O' C" b8 `7 X( |1 n- p1 o: o6 h; P3 \
9 |: L" Y% W6 T' ?& K- X; t% D6 U1 q( `2 W) L+ b
Usb_int.c包含两个主要函数CTR_HP()和CTR_LP(),CTR_HP()用于处理高优先级中断,用于同步传输模式和批量模式(双缓冲区),CTR_LP()用于处理低优先级中断,用于控制传输,中断传输和批量传输(单缓冲区)。1 \) t: z' t; P9 _
- H( w- g' B9 |) a$ |# {
. f" U% A! d" A+ @ I% rUsb_mem.c包含两个函数PMAToUserBufferCopy()和UserToPMABufferCopy(),是将PMA缓冲区的数据传给用户,和将用户缓冲区数据传给PMA缓冲区的主要数据传输过程。- I: c0 G' z- K! `+ f8 g
6 n E$ b0 `/ }8 h" j( h! w9 \; l) \& j& r+ `( ?& K- `; e6 a! ?. Y# A) }0 l
( [3 O6 |$ K( h8 i2 L( q# g- bUsb_regs.c主要是调用宏,实现寄存器的操作,但是上层函数很少调用这些函数直接就是用宏。& O2 F& U6 Q. V, u. @! w$ Y! y/ n4 n$ X
( \/ M( B, \( A4 U/ }. c
2 ?4 `! {2 K' ]0 `% X( E9 `) h8 c' cUsb_pwr.c主要是包括对一些电源的配置,包括USB上电PowerOn(),USB断电PowerOff(),挂起函数Suspend(),处理唤醒恢复操作Resume_Init(),状态机处理和恢复函数Resume(); h: K/ _. g8 |9 n- _6 Y+ I" m
: S' Z9 D& o1 x* [, R3 \# BUsb_desc.c主要是对描述符的定义,有CustomHID_DeviceDescriptor[18],CustomHID_ConfigDescriptor[],CustomHID_ReportDescriptor[],CustomHID_StringLangID[],CustomHID_StringVendor[],CustomHID_StringProduct[],CustomHID_StringSerial[]。- j& z! K0 m: E, G
Usb_prop.c是对一些获得描述符的设置,还有复位和初始化的设置,主要的函数是CustomHID_init()和CustomHID_Reset()两个函数
9 q1 g: S6 y+ y9 u1 R |
|