本文基于MCUXpresso SDK的USB協(xié)議棧,討論了多CDC ACM在NXP RT1060平臺的實現(xiàn)。文中的工作在MCUXpresso SDK USB協(xié)議棧的基礎(chǔ)上做了兩處改進(jìn):
1.由于Notification功能在大多數(shù)實際的CDC ACM應(yīng)用中基本不會用到,本文去掉了Notification使用的EP,在EHCI USB控制器支持8個雙向硬件EP的情況下,實現(xiàn)了多達(dá)7個CDC ACM通道的理論最大值。
2.屏蔽了復(fù)雜的USB協(xié)議和代碼的諸多細(xì)節(jié),使得CDC ACM 的數(shù)量僅僅由一個宏來進(jìn)行控制,這樣把開發(fā)時切換CDC ACM數(shù)目的時間,從數(shù)小時到數(shù)天縮短為秒級,大幅提升了用戶使用體驗。改進(jìn)之后的代碼經(jīng)過在RT1060 EVK上面測試,運(yùn)行良好。
1.淺析CDC ACM
USB CDC的內(nèi)容非常廣泛,本文只討論其最常見的一種應(yīng)用模型——ACM。ACM是英文Abstract Control Model的縮寫。這個模型是隸屬于PSTN設(shè)備,PSTN是Public Switched Telephone Network的英文縮寫。PSTN是一種非常古老的電話交換網(wǎng)絡(luò)。ACM是為模擬PSTN中傳統(tǒng)的Modem設(shè)備而設(shè)計的。
我們知道,Modem的控制接口正是UART。全功能支持Modem的UART控制信號線多達(dá)9根。但是在嵌入式的世界,更多使用的是精簡版本的UART,即只使用TX、RX、GND這三個信號實現(xiàn)簡單的雙向通信。所以我們可以把CDC ACM看成是一個USB to UART的Bridge。
隨著時代的發(fā)展,很多PC,尤其是筆記本電腦,目前已經(jīng)取消了UART,USB成為了主流的標(biāo)配。但是,多年來,由于UART簡單易用,并且有深厚的群眾基礎(chǔ),經(jīng)年累月的使用習(xí)慣,放棄UART會是一件很痛苦的事情。而主流的OS比如Linux、Windows、MacOS對CDC ACM的支持都很好,CDC ACM逐漸的代替了傳統(tǒng)的物理串口,延續(xù)了傳統(tǒng)物理串口在新型電腦上的使用。在PC上,UART的肉體滅亡了,但是靈魂依舊永存,依附于USB,UART會一直存在。
從協(xié)議的角度講CDC ACM,相信會很枯燥。因為USB浩如煙海的復(fù)雜協(xié)議會看得每個正常的人心煩意亂。所以小編這里并不準(zhǔn)備把整個CDC ACM的協(xié)議內(nèi)容在這里完整的講一遍,那實在是太復(fù)雜了。但是如果完全不講協(xié)議,小編也無法表達(dá)多CDC ACM實現(xiàn)技術(shù)的重點。下面小編會嘗試用最簡潔的方式來進(jìn)行表達(dá),會涉及協(xié)議,但是會突出重點,省略掉很多不重要的細(xì)節(jié)。
讓我們先看看一個CDC ACM是如何構(gòu)成的:
這里可以看到,一個CDC ACM實例由Communication接口和Data接口構(gòu)成。Communication接口包含class專用接口和一個可選的中斷型EP。而Data接口包含一對雙向的BULK EP用于數(shù)據(jù)通信,他們就是虛擬UART的TX和RX的物理載體。
在我們SDK的默認(rèn)實現(xiàn)中,Communication接口下的端點默認(rèn)是使能的。這樣,實現(xiàn)一個CDC ACM通道就需要2個端點,RT1060的USB控制器共有8個雙向端點。除去端點0,只有7個端點可以用于CDC ACM,這樣RT1060上可實現(xiàn)的CDC ACM實例最大數(shù)目為3。
而根據(jù)USB規(guī)范,Communication接口下的端點是可選的,小編嘗試了對此端點進(jìn)行移除。移除后,每個CDC ACM僅占用一個雙向端點,這樣,最終成功實現(xiàn)了7個CDC ACM實例。
小編在實踐的過程中,心中一直有個疑問,那就是Communication接口的那個Notification用的INT IN EP到底是干嘛用的。借助協(xié)議分析儀提供的線索,小編終于在Spec中找到了定義:
說白了是全功能UART的設(shè)備狀態(tài)模擬,用于原始Modem的狀態(tài)上報和載波控制。而我們大多數(shù)的情況下使用CDC ACM,只是為了做簡單的雙向收發(fā),而并不需要全功能的UART。在移除了Notification EP后,系統(tǒng)會變得更加簡單,CDC ACM模擬的全功能UART退化為只有TX、RX的精簡版本。
小編在實踐過程中的另一個疑問是,對于多CDC的情況,設(shè)置波特率之類的命令,是如何區(qū)分該命令是給哪個CDC ACM的實例呢?
借助于USB邏輯分析儀,我們可以很快找到答案,每一組命令都是針對某一個Interface的,我們可以通過Interface的編號來識別當(dāng)前的命令是傳給哪一個CDC ACM實例的。
下圖更加清晰地展示了實現(xiàn)的諸多細(xì)節(jié)。需要注意的是,這些命令是從EP0走的,移除Notification EP對此命令并無影響。
說到這里,小編想小結(jié)一下:CDC ACM是用于模擬PSTN環(huán)境下的Modem控制接口,即全功能UART,我們可以在此基礎(chǔ)上進(jìn)行精簡,得到僅具備TX, RX功能的虛擬UART設(shè)備。
2.通過一個宏定義來控制CDC的實例數(shù)
由于USB協(xié)議和代碼的復(fù)雜性,為了方便用戶使用,小編實現(xiàn)了通過一個宏定義來控制CDC的通道數(shù)。用戶只需要修改一個宏定義的值,就可以控制CDC的通道數(shù)量,代碼如下:#define USB_DEVICE_CONFIG_CDC_ACM (6U)
具體的實現(xiàn),有興趣的讀者可以去參考本文提供的代碼,這里小編只說一下實現(xiàn)的思路。
為了實現(xiàn)通過一個宏控制CDC的數(shù)量,我們需要軟件能夠提供以下功能:自動分配每個CDC ACM的接口編號
自動分配每個CDC ACM的端點編號
自動生成配置描述符
自動初始化SDK USB協(xié)議棧的數(shù)據(jù)結(jié)構(gòu)
自動匹配SDK USB協(xié)議棧的其他各種要求
為了完成所有這些自動化的操作,經(jīng)粗略統(tǒng)計,在原始SDK的基礎(chǔ)上,涉及的更改點大約有66處。
3.測試
1.CDC通道數(shù)測試:
小編依次修改配置宏定義,成功的測試了CDC ACM通道數(shù)從1到7的全部情況。
下面是7個通道枚舉后,在設(shè)備管理器中顯示的截圖:
2.7個CDC通道同時通信測試:為了進(jìn)行測試,小編同時開了7個串口終端,測試結(jié)果如下圖所示,7個終端均能獨立正常通信。
4.獲取源代碼
本文的原代碼可以從github.com進(jìn)行下載,無需密碼,下載鏈接為:http://github.com/jiaguonxpcom/usb_ncdc
該代碼編譯后可以直接下載到RT1060 EVK運(yùn)行。
5.特別感謝
在本人的實踐過程中,最開始只是實現(xiàn)了nCDC用一個宏定義的自動生成部分,并未能成功實現(xiàn)CDC ACM的Communication接口下的EP移除,在RT1060最大僅能自動實現(xiàn)3個CDC ACM實例。
來自NXP LPC/Kinetis SE團(tuán)隊的ZhangYang同學(xué)提供的AN給出了詳細(xì)的操作細(xì)節(jié)(ZhangYang同學(xué)成功的在Kinetis MCU上實現(xiàn)了15個CDC ACM實例,其USB控制器支持16個硬件端點)。另外,來自NXP中國區(qū)SE團(tuán)隊的資深USB專家梁平老師提供了寶貴的理論指導(dǎo)意見。在二位同事的熱心幫助下,才使本文設(shè)計的實驗?zāi)艹晒崿F(xiàn),并發(fā)布本文章。
在此,小編向二位表示深深的感謝!