5.1 使用流程
在 USB 協(xié)議中,永遠(yuǎn)是 Host 主動(dòng)發(fā)起傳輸。作為一個(gè) Gadget 驅(qū)動(dòng)程序,它永遠(yuǎn)都是這樣:
- 想接收數(shù)據(jù):
- 先構(gòu)造好 usb_request:分配 buffer、設(shè)置回調(diào)函數(shù)
- 把 usb_request 放入隊(duì)列
- UDC 和 Host 完成 USB 傳輸,在 usb_request 中填充數(shù)據(jù),并觸發(fā)中斷調(diào)用 usb_request 的回調(diào)函數(shù)
- 想發(fā)送數(shù)據(jù):
- 先構(gòu)造好 usb_request:分配 buffer、在 buffer 里填充數(shù)據(jù)、設(shè)置回調(diào)函數(shù)
- 把 usb_request 放入隊(duì)列
- UDC 和 Host 完成 USB 傳輸,把 usb_request 的數(shù)據(jù)發(fā)給 Host,并觸發(fā)中斷調(diào)用 usb_request 的回調(diào)函數(shù)
5.2 endpoint 是核心
USB 傳輸?shù)膶?duì)象是 endpoint,使用流程如下:
- 功能驅(qū)動(dòng)里,通過 endpoint 描述符表明需要怎樣的 endpoint,比如(注意:bEndpointAddress 是表明方向,里面還沒有地址,driversusbgadgetfunctionf_loopback.c):
- 功能驅(qū)動(dòng)里,它的 bind 函數(shù)根據(jù) endpoint 描述符向底層申請(qǐng)分配 endpoint,比如:
- 功能驅(qū)動(dòng)里,使能 endpoint,比如:
- 功能驅(qū)動(dòng)里,給 endpoint 分配 buffer、設(shè)置 usb_request、提交 usb_request,比如:
5.3 回調(diào)函數(shù)
功能驅(qū)動(dòng)里構(gòu)造的 usb_request,可以是接收 Host 發(fā)來的數(shù)據(jù),也可以是向 Host 發(fā)送數(shù)據(jù)。當(dāng)傳輸完成,usb_request 的回調(diào)函數(shù)被調(diào)用。
在回調(diào)函數(shù)里,可以再次提交 usb_request。
怎么調(diào)用到回調(diào)函數(shù)?源頭是 UDC 的中斷函數(shù)。
5.3.1 IMX6ULL
調(diào)用關(guān)系如下:
// Linux-4.9.88driversusbchipideacore.c
ci_irq
/* Handle device/host interrupt */
if (ci- >role != CI_ROLE_END)
ret = ci_role(ci)- >irq(ci); // udc_irq
udc_irq
if (USBi_UI & intr)
isr_tr_complete_handler(ci);
err = isr_tr_complete_low(hwep);
usb_gadget_giveback_request(&hweptemp- >ep, &hwreq- >req);
req- >complete(ep, req);
5.3.2 STM32MP157
調(diào)用關(guān)系如下:
// Linux-5.4driversusbdwc2gadget.c
dwc2_hsotg_irq
// 處理endpoint中斷
for (ep = 0; ep < hsotg- >num_of_eps && daint_out;
ep++, daint_out > >= 1) {
if (daint_out & 1)
dwc2_hsotg_epint(hsotg, ep, 0);
dwc2_hsotg_handle_outdone(hsotg, idx);
dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
usb_gadget_giveback_request(&hs_ep- >ep, &hs_req- >req);
req- >complete(ep, req);
}
for (ep = 0; ep < hsotg- >num_of_eps && daint_in;
ep++, daint_in > >= 1) {
if (daint_in & 1)
dwc2_hsotg_epint(hsotg, ep, 1);
dwc2_hsotg_complete_in(hsotg, hs_ep);
dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
usb_gadget_giveback_request(&hs_ep- >ep, &hs_req- >req);
req- >complete(ep, req);
}
5.4 f_loopback分析
loopback 就是回環(huán),Host 發(fā)數(shù)據(jù)給 Gadget,然后再讀 Gadget 就可以得到原樣的數(shù)據(jù)。
5.4.1 Gadget接收數(shù)據(jù)
Host 選擇某個(gè)配置時(shí),默認(rèn)會(huì)選擇這個(gè)配置下那些接口的第 0 個(gè)設(shè)置(altsetting);
當(dāng) Host 發(fā)來 USB_REQ_SET_INTERFACE 請(qǐng)求時(shí),可以選擇指定的設(shè)置。
所以,我們從 f_loopback.c 的函數(shù)loopback_set_alt
開始分析。
調(diào)用關(guān)系為:
loopback_set_alt
enable_loopback
result = enable_endpoint(cdev, loop, loop- >in_ep);
result = enable_endpoint(cdev, loop, loop- >out_ep);
result = alloc_requests(cdev, loop);
如上圖所示,先提交的是 out_req,它在等待 Host 發(fā)來數(shù)據(jù)。
假設(shè)斷點(diǎn) loop->out_ep 的 out_req 獲得了數(shù)據(jù),它的回調(diào)函數(shù)loopback_complete
被調(diào)用,如下:
5.4.2 Gadget 回環(huán)數(shù)據(jù)
5.5 f_sourcesink 分析
前面的 f_loopback 也實(shí)現(xiàn)了兩個(gè)方向的數(shù)據(jù)傳輸:Host 到 Gadget、Gadget 到 Host,但是它們之間是有依賴關(guān)系的,Host 必須先發(fā)送數(shù)據(jù)再讀數(shù)據(jù)。
f_sourcesink.c 也實(shí)現(xiàn)了兩個(gè)方向的數(shù)據(jù)傳輸:Host 到 Gadget、Gadget 到 Host,它們是獨(dú)立的。
- Host 讀 Gadget:驅(qū)動(dòng)程序里構(gòu)造好數(shù)據(jù),Host 可以讀到,Gadget 作為源(source)
- Host 寫 Gadget:驅(qū)動(dòng)程序里得到 Host 發(fā)來的數(shù)據(jù),Gadget 作為目的(sink)
5.5.1 Host 寫 Gadget
Host 選擇某個(gè)配置時(shí),默認(rèn)會(huì)選擇這個(gè)配置下那些接口的第 0 個(gè)設(shè)置(altsetting);
當(dāng) Host 發(fā)來 USB_REQ_SET_INTERFACE 請(qǐng)求時(shí),可以選擇指定的設(shè)置。
所為,我們從 f_sourcesink.c 的函數(shù)sourcesink_set_alt
開始分析。
sourcesink_set_alt
enable_source_sink(cdev, ss, alt);
作為"source",函數(shù)source_sink_start_ep
會(huì)構(gòu)造數(shù)據(jù)、提交 usb_request:
當(dāng) Host 讀取到數(shù)據(jù)后,usb_request 的回調(diào)函數(shù)被調(diào)用,它只是再次提交 USB 請(qǐng)求,給 Host 繼續(xù)提供跟上次一樣的數(shù)據(jù):
5.5.2 Host 讀 Gadget
仍然從 f_sourcesink.c 的函數(shù)sourcesink_set_alt
開始分析。
sourcesink_set_alt
enable_source_sink(cdev, ss, alt);
作為"sink",函數(shù)source_sink_start_ep
會(huì)故意把數(shù)據(jù)設(shè)置為 0x55(這是為了調(diào)試,當(dāng)讀到數(shù)據(jù)時(shí)可以看到 0x55 被覆蓋)、提交 usb_request:
當(dāng) Host 發(fā)來數(shù)據(jù),usb_request 的回調(diào)函數(shù)被調(diào)用,它檢查收到的數(shù)據(jù),再次提交 usb_request:
-
嵌入式
+關(guān)注
關(guān)注
5141文章
19528瀏覽量
314934 -
Linux
+關(guān)注
關(guān)注
87文章
11459瀏覽量
212788 -
框架
+關(guān)注
關(guān)注
0文章
404瀏覽量
17790
發(fā)布評(píng)論請(qǐng)先 登錄
無線數(shù)據(jù)傳輸模塊的實(shí)際應(yīng)用
USART數(shù)據(jù)傳輸模型怎么理解
DMA進(jìn)行數(shù)據(jù)傳輸和CPU進(jìn)行數(shù)據(jù)傳輸的疑問
數(shù)據(jù)傳輸介質(zhì)
什么是內(nèi)部數(shù)據(jù)傳輸率
IDE數(shù)據(jù)傳輸模式
Modem數(shù)據(jù)傳輸標(biāo)準(zhǔn)
RAID卡的數(shù)據(jù)傳輸速度
數(shù)據(jù)傳輸,數(shù)據(jù)傳輸的工作方式有哪些?
數(shù)據(jù)傳輸速率是什么意思
tcp_ip 協(xié)議講座:介紹數(shù)據(jù)傳輸

SPI數(shù)據(jù)傳輸有哪些方式

評(píng)論