s3c2440的USB主機(jī)控制器
OHCI(Open HCI)是目前使用比較廣泛的三種USB主機(jī)控制器規(guī)范之一。USB體系結(jié)構(gòu)是由四個(gè)主要部分組成:客戶軟件/USB驅(qū)動,主機(jī)控制器驅(qū)動(HCD),主機(jī)控制器(HC)和USB驅(qū)動。前兩者由軟件實(shí)現(xiàn),后兩者由硬件實(shí)現(xiàn)。而OHCI就是規(guī)范了主機(jī)控制器驅(qū)動和主機(jī)控制器之間的接口,以及它們的基本操作。在主機(jī)控制器驅(qū)動和主機(jī)控制器之間,有兩個(gè)通信通道,第一個(gè)是應(yīng)用位于HC的一套可操作寄存器,它們包括控制寄存器、狀態(tài)寄存器和列表指針寄存器;另一個(gè)通道是應(yīng)用稱為主機(jī)控制器通信域(HCCA)的共享內(nèi)存。
USB定義了四種數(shù)據(jù)傳輸類型:控制傳輸、批量傳輸、中斷傳輸和同步傳輸。在OHCI規(guī)范中把數(shù)據(jù)傳輸類型分為兩類:周期傳輸和非周期傳輸。同步傳輸和中斷傳輸屬于周期傳輸,控制傳輸和批量傳輸屬于非周期傳輸。USB定義了每幀的周期為1.0毫秒,為了保證每一幀都能發(fā)生周期傳輸和非周期傳輸,一般地,OHCI把每一幀的帶寬分為四個(gè)部分,首先是發(fā)送SOF,然后是非周期傳輸,緊接著是周期傳輸,如果周期傳輸完畢后,還有時(shí)間,則剩余的時(shí)間仍然留給非周期傳輸。
端點(diǎn)描述符(ED)和傳輸描述符(TD)是兩個(gè)最基本的通信模塊。ED包含了一個(gè)端點(diǎn)的信息,它被HC用來管理使用端點(diǎn)。ED的典型參數(shù)包括端點(diǎn)地址、傳輸速度、最大數(shù)據(jù)包大小,另外ED還提供了TD鏈表的??康兀ㄥ^點(diǎn))。TD是一個(gè)依賴于ED的內(nèi)存緩存區(qū),用于與端點(diǎn)之間進(jìn)行數(shù)據(jù)傳輸。當(dāng)HC存取一個(gè)ED,并且找到一個(gè)有效的TD地址時(shí),則HC就完成了一個(gè)簡單的與端點(diǎn)之間的傳輸任務(wù),這個(gè)端點(diǎn)是由ED確定,而所存取的數(shù)據(jù)內(nèi)存地址由TD指定。當(dāng)所有的被TD所定義的數(shù)據(jù)傳輸完畢后,TD就從ED中解鏈出來,并鏈接到完成列表中。這個(gè)完成列表能夠被HCD所處理,以提供一些完成信息。
ED的數(shù)據(jù)結(jié)構(gòu)長度為16字節(jié),它的數(shù)據(jù)域有:
FA:USB的功能地址;
EN:USB功能內(nèi)的端點(diǎn)地址;
D:數(shù)據(jù)流的傳輸方向,是IN,OUT,還是有TD來決定傳輸方向;
S:速度,全速還是低速;
K:用于設(shè)置跳過當(dāng)前ED;
F:鏈接于ED的TD的形式,是通用TD格式還是同步TD格式;
MPS:數(shù)據(jù)傳輸?shù)淖畲笞止?jié)大??;
TailP:TD列表的尾指針;
H:用于停止當(dāng)前TD列表的處理;
C:數(shù)據(jù)翻轉(zhuǎn)進(jìn)位位;
HeadP:TD列表的頭指針;
NextED:下一個(gè)要處理的ED指針。
根據(jù)上述說明,我們可以定義ED為下面的數(shù)據(jù)類型:
typedef struct _ED {
volatile unsigned int Control;
volatile unsigned int TailP;
volatile unsigned int HeadP;
volatile unsigned int NextEd;
} ED, *P_ED;
由于ED必須是16字節(jié)地址對齊形式,因此我們必須用下面的形式來聲明它的變量:
__align(16) ED ed;
我們可以用下面的函數(shù)來創(chuàng)建一個(gè)ED:
__inline void CreateEd(
unsigned int EDAddr,//ED地址指針
unsigned int MaxPacket,//MPS
unsigned int TDFormat,//F
unsigned int Skip,//K
unsigned int Speed,//S
unsigned int Direction,//D
unsigned int EndPt,//EN
unsigned int FuncAddress,//FA
unsigned int TDQTailPntr,//TailP
unsigned int TDQHeadPntr,//HeadP
unsigned int ToggleCarry,//C
unsigned int NextED)//NextED
{
P_ED pED = (P_ED) EDAddr;
pED->Control = (MaxPacket << 16) | (TDFormat << 15) |(Skip << 14) | (Speed << 13)
| Direction << 11) | (EndPt << 7) | FuncAddress;
pED->TailP = (TDQTailPntr & 0xFFFFFFF0);
pED->HeadP = (TDQHeadPntr & 0xFFFFFFF0) | (ToggleCarry << 1);
pED->NextEd = (NextED & 0xFFFFFFF0);
}
TD共有兩種類型:通用TD和同步TD。通用TD用于中斷、控制和批量端點(diǎn),同步TD用于同步傳輸。在這里,我們只給出通用TD的數(shù)據(jù)結(jié)構(gòu)和定義。
通用TD的數(shù)據(jù)結(jié)構(gòu)長度也是16字節(jié),它的數(shù)據(jù)域有:
R:緩存湊整,用于設(shè)置是否需要最后一個(gè)數(shù)據(jù)包的長度與所定義的長度一致;
DP:方向,是IN,OUT,還是SETUP;
DI:延時(shí)中斷;
T:數(shù)據(jù)翻轉(zhuǎn);
EC:傳輸錯(cuò)誤計(jì)數(shù);
CC:條件碼,為上一次企圖傳輸?shù)臓顟B(tài);
CBP:將要被傳輸?shù)臄?shù)據(jù)內(nèi)存物理地址;
NextTD:下一個(gè)TD;
BE:將要被傳輸?shù)臄?shù)據(jù)內(nèi)存物理末字節(jié)地址;
根據(jù)上述說明,我們可以定義通用TD為下面的數(shù)據(jù)類型:
typedef struct _TD {
volatile unsigned int Control;
volatile unsigned int CBP;
volatile unsigned int NextTD;
volatile unsigned int BE;
} TD, *P_TD;
由于通用TD必須是16字節(jié)地址對齊形式,因此我們必須用下面的形式來聲明它的變量:
__align(16) TD td[4];
我們可以用下面的函數(shù)來創(chuàng)建一個(gè)通用TD:
__inline void CreateGenTd(
unsigned int GenTdAddr,//TD地址指針
unsigned int DataToggle,//T
unsigned int DelayInterrupt,//DI
unsigned int Direction,//DP
unsigned int BufRnding,//R
unsigned int CurBufPtr,//CBP
unsigned int NextTD,//NextTD
unsigned int BuffLen)//被傳輸?shù)臄?shù)據(jù)長度,由該變量可以得到BE
{
P_TD pTD = (P_TD) GenTdAddr;
pTD->Control = (DataToggle << 24) | (DelayInterrupt << 21)
| (Direction << 19) | (BufRnding << 18);
pTD->CBP = CurBufPtr;
pTD->NextTD = (NextTD & 0xFFFFFFF0);
pTD->BE = (BuffLen) ? CurBufPtr + BuffLen - 1 : CurBufPtr;
}
下面我們給出HCCA的數(shù)據(jù)結(jié)構(gòu),它的長度為256字節(jié),包括128字節(jié)的HCCA中斷表,2字節(jié)的HCCA幀數(shù),2字節(jié)的HCCA便簽(表示HC是否正在更新HCCA幀數(shù)),4字節(jié)的HCCA完成隊(duì)列頭指針,以及116字節(jié)的保留區(qū)。根據(jù)上述說明,我們可以定義HCCA為下面的數(shù)據(jù)類型:
typedef struct _HCCA {
volatile unsigned int HccaInterruptTable[32];
volatile unsigned short HccaFrameNumber;
volatile unsigned short HccaPad1;
volatile unsigned int HccaDoneHead;
volatile unsigned char reserved[116];
} HCCA, *P_HCCA;
由于HCCA必須是256字節(jié)地址對齊形式,因此我們必須用下面的形式來聲明它的變量:
__align(256) HCCA hcca;
OHCI是基于寄存器層描述的USB主機(jī)控制器的規(guī)范,因此HC包含了一些片內(nèi)可操作寄存器,這些寄存器同樣可以被HCD所使用。下面我們就簡單介紹OHCI中的寄存器。
HcRevision:HCI規(guī)范版本;
HcControl:HC的操作模式,CBSR——在非周期隊(duì)列中,被服務(wù)的控制ED與批量ED之間的比例;CLE——下一幀控制隊(duì)列處理使能;HCFS——USB主機(jī)控制器功能狀態(tài),包括復(fù)位、重新開始、操作和中止;
HcCommandStatus:HC接收來至HCD的命令,也可反映HC的當(dāng)前狀態(tài),HCR——軟件復(fù)位HC;CLF——確定是否有控制隊(duì)列TD;
HcInterruptStatus:提供各種能夠觸發(fā)硬件中斷事件的狀態(tài);
HcInterruptEnable:使能用于控制產(chǎn)生硬件中斷事件的位;
HcInterruptDisable:無效用于控制產(chǎn)生硬件中斷事件的位
HcHCCA:HCCA的物理地址;
HcPeriodCurrentED:當(dāng)前同步或中斷ED的物理地址;
HcControlHeadED:控制隊(duì)列的第一個(gè)ED的物理地址;
HcControlCurrentED:當(dāng)前控制對立ED的物理地址;
HcBulkHeadED:批量隊(duì)列的第一個(gè)ED的物理地址;
HcBulkCurrentED:當(dāng)前批量對立ED的物理地址;
HcDoneHead:被添加在完成隊(duì)列中的最近一個(gè)TD的物理地址;
HcFmInterval:包含一個(gè)14位的FI——用于表示一幀之內(nèi)所占用的比特時(shí)間,2個(gè)連續(xù)的SOFs,和一個(gè)15位PSMPS——用于表示在沒有引發(fā)調(diào)度溢出下可發(fā)送或接收全速最大包大小,F(xiàn)I,PSMPS的推薦值為0x2EDF和0x2778。
HcFmRemaining:14位的倒計(jì)數(shù)器,以表示當(dāng)前幀所剩時(shí)間;
HcFmNumber:16位計(jì)數(shù)器,以提供時(shí)序參考;
HcPeriodicStart:14位可編程數(shù)值,以確定HC在什么時(shí)間開始執(zhí)行周期隊(duì)列;
HcLSThreshold:11位數(shù)值,用于確定是否在EOF之前執(zhí)行最大8位LS包傳輸;
HcRhDescriptorA:第一個(gè)對跟集線器進(jìn)行描述的寄存器;
HcRhDescriptorB:第二個(gè)對跟集線器進(jìn)行描述的寄存器;
HcRhStatus:包括集線器狀態(tài)域和集線器狀態(tài)更改域;
HcRhPortStstus[1:NDP]:用于控制和報(bào)告每個(gè)端口上的事件,在s3c2440中,NDP為2
下面給出OHCI的初始化,它都是基于寄存器的。根據(jù)OHCI規(guī)范,HCD應(yīng)該完成下列初始化步驟:
●初始化HCCA數(shù)據(jù)內(nèi)存單元
●初始化可操作寄存器,以匹配當(dāng)前設(shè)備數(shù)據(jù)狀態(tài)
●設(shè)置HcHCCA
●設(shè)置HcInterruptEnable
●設(shè)置HcControl
●設(shè)置HcPeriodicStart
結(jié)合本文所介紹的實(shí)際內(nèi)容,OHCI的初始化函數(shù)為:
void OHCIInit( )
{
unsigned int fminterval;
//復(fù)位
rHcControl = 0;
//寫HCCA
rHcHCCA = (volatile unsigned )&hcca;
//設(shè)置幀間隔
fminterval = 0x2edf;
rHcFmInterval =((((fminterval - 210) * 6) / 7) << 16)| fminterval;
rHcPeriodicStart= (fminterval * 9) / 10;
//初始化HcDoneHead
rHcDoneHead = 0x00;
hcca.HccaDoneHead = 0x0000;
//設(shè)置HC為運(yùn)行狀態(tài)
rHcControl = 0x80;
}
主機(jī)對USB設(shè)備的識別過程稱為設(shè)備枚舉,因此枚舉對于USB至關(guān)重要。在本文,只進(jìn)行下列簡單的5步枚舉過程:
1、主機(jī)要求得到設(shè)備描述符,SETUP數(shù)據(jù)包為:0x80, 0x06,0x00,0x01,0x00,0x00,0x40,0x00,得到的數(shù)據(jù)長度最大為0x40;
2、第二個(gè)SETUP包是為設(shè)備分配一個(gè)地址,內(nèi)容一般為:0x00,0x05,0x02,0x00,0x00,0x00,0x00,0x00。其中的02表示為設(shè)備分配的地址為0x02,以后我們再對該設(shè)備操作時(shí),就只能使用0x02這個(gè)地址值;
3、主機(jī)用新的地址再次獲取設(shè)備描述符,SETUP包為:0x80,0x06,0x00,0x01,0x00,0x00,0x12,0x00,與上次不同,這次得到數(shù)據(jù)長度時(shí)實(shí)際的數(shù)據(jù)長度0x12;
4、主機(jī)讀取設(shè)備全部配置描述符,SETUP包為:0x80,0x06,0x00,0x02,0x00,0x00,0x40,0x00,由于主機(jī)不知道設(shè)備描述符的長度,因此這里只要求得到0x40個(gè)字節(jié);
5、主機(jī)發(fā)送SETUP數(shù)據(jù)包:0x00,0x09,0x01,0x00,0x00,0x00,0x00,0x00,用以設(shè)置配置,允許所有端點(diǎn)進(jìn)入工作狀態(tài)。
對USB設(shè)備枚舉我們只做了簡單的介紹,關(guān)于枚舉的其他步驟以及SETUP數(shù)據(jù)包各個(gè)字節(jié)的具體含義,請閱讀USB協(xié)議的第9章。
下面我們就主要介紹OHCI規(guī)范是如何完成USB設(shè)備枚舉的。前面我們已經(jīng)介紹過了,OHCI數(shù)據(jù)傳輸主要依靠ED和TD,其中TD是掛靠在ED上的。ED主要用來設(shè)置傳輸?shù)母鞣N參數(shù),TD則主要負(fù)責(zé)具體的數(shù)據(jù)傳輸。根據(jù)USB協(xié)議,USB的設(shè)備枚舉只涉及控制傳輸。控制傳輸最少有兩個(gè)事務(wù)階段:建立和狀態(tài),控制傳輸可以有選擇性地包括建立和狀態(tài)階段之間的數(shù)據(jù)階段。在這里,控制寫傳輸不需要數(shù)據(jù)階段,而控制讀需要在建立和狀態(tài)之間添加主機(jī)要讀取到的數(shù)據(jù)。一般來說,完成一次控制寫傳輸需要3個(gè)TD:第一個(gè)發(fā)送Setup包,第二個(gè)用于接收握手或零長度的數(shù)據(jù)包,第三個(gè)用于發(fā)送狀態(tài);而完成一次控制讀傳輸需要4個(gè)TD:第一個(gè)發(fā)送Setup包,第二個(gè)用于接收數(shù)據(jù),第三個(gè)用于發(fā)送一個(gè)零長度的數(shù)據(jù)包,,第四個(gè)用于接收狀態(tài)。
下面給出具體的USB設(shè)備枚舉的函數(shù)。在進(jìn)行枚舉之前,主機(jī)一定要確認(rèn)有USB設(shè)備的存在。正確情況下,在確認(rèn)過程中,如果在一段給定時(shí)間沒有檢測到設(shè)備,則主機(jī)認(rèn)為沒有USB設(shè)備。“一段給定的時(shí)間”應(yīng)該由定時(shí)器來完成。在這里,為了簡化程序,我們只用計(jì)數(shù)來代替定時(shí)。
int USB_Enum()
{
int i;
//判斷有無USB設(shè)備
for(i=0;i<100000;i++)
{
if (rHcRhPortStatus1 & 0x01)
{
rHcRhPortStatus1 = (1 << 4);//端口復(fù)位
while (rHcRhPortStatus1 & (1 << 4))
;//等待復(fù)位結(jié)束
rHcRhPortStatus1 = (1 << 1);//使能該端口
break;
}
else if (rHcRhPortStatus2 & 0x01)
{
rHcRhPortStatus2 = (1 << 4);//端口復(fù)位
while (rHcRhPortStatus2 & (1 << 4))
;//等待復(fù)位結(jié)束
rHcRhPortStatus2 = (1 << 1);//使能該端口
break;
}
}
if (i>90000)
return 0x44;
//第一步,主機(jī)得到設(shè)備描述符
CreateEd(
(unsigned int) &ed,// ED Address
64,// Max packet
0,// TD format
0,// Skip
0,// Speed
0x0,// Direction
0x0,// Endpoint
0x0,// Func Address,初始為0
(unsigned int) &td[3],// TDQTailPointer
(unsigned int) &td[0],// TDQHeadPointer
0,// ToggleCarry
0x0);// NextED
//建立PID
CreateGenTd(
(unsigned int) &td[0],// TD Address
2,// Data Toggle
0x2,// DelayInterrupt
0x0,// Direction
1,// Buffer Rounding
(unsigned int) pSetup1,// Current Buffer Pointer,定義的全局變量數(shù)組
//const char pSetup1[8] ={0x80,0x06,0x00,0x01,0x00,0x00,0x40,0x00};
(unsigned int) &td[1],// Next TD
8);// Buffer Length
//接收數(shù)據(jù)
CreateGenTd(
(unsigned int) &td[1],// TD Address
0,// Data Toggle
0x2,// DelayInterrupt
0x2,// Direction
1,// Buffer Rounding
(unsigned int) pData1,// Current Buffer Pointer,定義的全局變量數(shù)組
// char pData1[0x40];通過讀取該數(shù)組,可以獲知設(shè)備描述符
(unsigned int) &td[2],// Next TD
0x40);// Buffer Length
//零長度數(shù)據(jù)包
CreateGenTd(
(unsigned int) &td[2],// TD Address
3,// Data Toggle
0x2,// DelayInterrupt
0x1,// Direction
1,// Buffer Rounding
0x0,// Current Buffer Pointer
(unsigned int) &td[3],// Next TD
0x0);// Buffer Length
//接收狀態(tài)
CreateGenTd(
(unsigned int) &td[3],// TD Address
3,// Data Toggle
0x2,// DelayInterrupt
0x2,// Direction
1,// Buffer Rounding
0x0,// Current Buffer Pointer
(unsigned int) 0,// Next TD
0x0);// Buffer Length
//設(shè)置寄存器
rHcControlHeadED = (unsigned int )& ed;
rHcControlCurrentED = (unsigned int )& ed;
//控制列表處理使能,開始工作
rHcControl = 0x90;
//通知HC控制列表已填充
rHcCommandStatus = 0x02;
//第二步為設(shè)備分配地址
CreateEd(
(unsigned int) &ed,// ED Address
64,// Max packet
0,// TD format
0,// Skip
0,// Speed
0x0,// Direction
0,// Endpoint
0,// Func Address
(unsigned int) &td[2],// TDQTailPointer
(unsigned int) &td[0],// TDQHeadPointer
0,// ToggleCarry
0x0);// NextED
//建立PID
CreateGenTd(
(unsigned int) &td[0],// TD Address
2,// Data Toggle
2,// DelayInterrupt
0,// Direction
1,// Buffer Rounding
(unsigned int) pSetup2,// Current Buffer Pointer,定義的全局變量數(shù)組
//const char pSetup2[8] ={0x00,0x05,0x02,0x00,0x00,0x00,0x00,0x00};
(unsigned int) &td[1],// Next TD
8);// Buffer Length
//接收零長度數(shù)據(jù)包
CreateGenTd(
(unsigned int) &td[1],// TD Address
0,// Data Toggle
2,// DelayInterrupt
2,// Direction
1,// Buffer Rounding
(unsigned int) 0,// Current Buffer Pointer
(unsigned int) &td[2],// Next TD
0);// Buffer Length
//發(fā)送狀態(tài)
CreateGenTd(
(unsigned int) &td[2],// TD Address
3,// Data Toggle
2,// DelayInterrupt
1,// Direction
1,// Buffer Rounding
0x0,// Current Buffer Pointer
(unsigned int) 0,// Next TD
0x0);// Buffer Length
rHcControlHeadED = (unsigned int )& ed;
rHcControlCurrentED = (unsigned int )& ed;
rHcControl = 0x90;
rHcCommandStatus = 0x02;
//第三步,主機(jī)用新的地址再次獲取設(shè)備描述符
CreateEd(
(unsigned int) &ed, // ED Address
64,// Max packet
0,// TD format
0,// Skip
0,// Speed
0x0,// Direction
0x0,// Endpoint
0x2,// Func Address,新的地址
(unsigned int) &td[3],// TDQTailPointer
(unsigned int) &td[0],// TDQHeadPointer
0,// ToggleCarry
0x0);// NextED
CreateGenTd(
(unsigned int) &td[0],// TD Address
2,// Data Toggle
0x2,// DelayInterrupt
0x0,// Direction
1,// Buffer Rounding
(unsigned int) pSetup3,// Current Buffer Pointer,定義的全局變量數(shù)組
//const char pSetup3[8] ={0x80,0x06,0x00,0x01,0x00,0x00,0x12,0x00};
(unsigned int) &td[1],// Next TD
8);// Buffer Length
CreateGenTd(
(unsigned int) &td[1],// TD Address
0,// Data Toggle
0x2,// DelayInterrupt
0x2,// Direction
1,// Buffer Rounding
(unsigned int) pData3,// Current Buffer Pointer,定義的全局變量數(shù)組
// char pData3[0x12];通過讀取該數(shù)組,可以獲知設(shè)備描述符
(unsigned int) &td[2],// Next TD
0x12);// Buffer Length
CreateGenTd(
(unsigned int) &td[2],// TD Address
3,// Data Toggle
0x2,// DelayInterrupt
0x1,// Direction
1,// Buffer Rounding
0x0,// Current Buffer Pointer
(unsigned int) &td[3],// Next TD
0x0);// Buffer Length
CreateGenTd(
(unsigned int) &td[3],// TD Address
3,// Data Toggle
0x2,// DelayInterrupt
0x2,// Direction
1,// Buffer Rounding
0x0,// Current Buffer Pointer
(unsigned int) 0,// Next TD
0x0);// Buffer Length
rHcControlHeadED = (unsigned int )& ed;
rHcControlCurrentED = (unsigned int )& ed;
rHcControl = 0x90;
rHcCommandStatus = 0x02;
//第四步,主機(jī)讀取設(shè)備全部配置描述符
CreateEd(
(unsigned int) &ed, // ED Address
64,// Max packet
0,// TD format
0,// Skip
0,// Speed
0x0,// Direction
0x0,// Endpoint
0x2,// Func Address
(unsigned int) &td[3],// TDQTailPointer
(unsigned int) &td[0],// TDQHeadPointer
0,// ToggleCarry
0x0);// NextED
CreateGenTd(
(unsigned int) &td[0],// TD Address
2,// Data Toggle
0x2,// DelayInterrupt
0x0,// Direction
1,// Buffer Rounding
(unsigned int) pSetup4,// Current Buffer Pointer,定義的全局變量數(shù)組
//const char pSetup4[8] ={0x80,0x06,0x00,0x02,0x00,0x00,0x40,0x00};
(unsigned int) &td[1],// Next TD
8);// Buffer Length
CreateGenTd(
(unsigned int) &td[1],// TD Address
0,// Data Toggle
0x2,// DelayInterrupt
0x2,// Direction
1,// Buffer Rounding
(unsigned int) pData4,// Current Buffer Pointer,定義的全局變量數(shù)組
// char pData4[0x40];通過讀取該數(shù)組,可以獲知配置描述符
(unsigned int) &td[2],// Next TD
0x40);// Buffer Length
CreateGenTd(
(unsigned int) &td[2],// TD Address
3,// Data Toggle
0x2,// DelayInterrupt
0x1,// Direction
1,// Buffer Rounding
0x0,// Current Buffer Pointer
(unsigned int) &td[3],// Next TD
0x0);// Buffer Length
CreateGenTd(
(unsigned int) &td[3],// TD Address
3,// Data Toggle
0x2,// DelayInterrupt
0x2,// Direction
1,// Buffer Rounding
0x0,// Current Buffer Pointer
(unsigned int) 0,// Next TD
0x0);// Buffer Length
rHcControlHeadED = (unsigned int )& ed;
rHcControlCurrentED = (unsigned int )& ed;
rHcControl = 0x90;
rHcCommandStatus = 0x02;
//第五步,主機(jī)發(fā)送SETUP數(shù)據(jù)包,用以設(shè)置配置,允許所有端點(diǎn)進(jìn)入工作狀態(tài)。
CreateEd(
(unsigned int) &ed, // ED Address
64,// Max packet
0,// TD format
0,// Skip
0,// Speed
0x0,// Direction
0,// Endpoint
2,// Func Address
(unsigned int) &td[2],// TDQTailPointer
(unsigned int) &td[0],// TDQHeadPointer
0,// ToggleCarry
0x0);// NextED
CreateGenTd(
(unsigned int) &td[0],// TD Address
2,// Data Toggle
2,// DelayInterrupt
0,// Direction
1,// Buffer Rounding
(unsigned int) pSetup5,// Current Buffer Pointer,定義的全局變量數(shù)組
//const char pSetup5[8] ={0x00,0x09,0x01,0x00,0x00,0x00,0x00,0x00};
(unsigned int) &td[1],// Next TD
8);// Buffer Length
CreateGenTd(
(unsigned int) &td[1],// TD Address
0,// Data Toggle
2,// DelayInterrupt
2,// Direction
1,// Buffer Rounding
(unsigned int) 0,// Current Buffer Pointer
(unsigned int) &td[2],// Next TD
0);// Buffer Length
CreateGenTd(
(unsigned int) &td[2],// TD Address
3,// Data Toggle
2,// DelayInterrupt
1,// Direction
1,// Buffer Rounding
0x0,// Current Buffer Pointer
(unsigned int) 0,// Next TD
0x0);// Buffer Length
rHcControlHeadED = (unsigned int )& ed;
rHcControlCurrentED = (unsigned int )& ed;
rHcControl = 0x90;
rHcCommandStatus = 0x02;
return 0x88;
}
評論