1.簡介
USB協議棧是基於東軟微電子ES32系列的USB控制器開發的USB範例,基於有效縮短開發者在應用範例的開發時程,協議棧以結構化的架構提供一系列的USB應用範例,經由將USB控制器的存取抽象化的架構下,開發者只需針對相關的應用層修改或新增功能,可有效降低對USB控制器存取的複雜度並縮減開發或移植的時程,在中斷,標準請求及裝置類(Class)請求的處理流程中,亦可經由Callback功能的延伸擴充相關請求的處理流程
2.協議棧架構
USB協議棧的基本架構如下
架構區分為核心層,裝置/主機枚舉層,裝置/主機類(Class)枚舉層及應用層,各結構層基本功能說明如下:
核心層:提供USB中斷處理函數及與PHY層配置相關的函數,此核心層的功能均直接對PHY層做存取 枚舉層:處理基本的USB標準請求流程,部分請求可經由Callback函數擴充處理流程 類(Class)枚舉層:處理基本的裝置類(Class)請求流程,目前版本提供HID,CDC,MSC,UAC的類(Class)請求處理範例,部分請求可經由Callback函數擴充處理流程 應用層:經由枚舉層的應用端點狀態所延伸的相關應用程序,這也是開發者最須關注開發的流程序,由於不同的USB應用對於對應的端點狀態及應用流程均不相同,因此無法以通用的端點狀態及應用流程概括之,開發者必須針對所開發的USB應用所對應的應用端點狀態自行開發相對應的應用程序 Callback:提供開發者對USB中斷,標準請求及裝置類(Class)請求處理流程中擴充額外的處理流程
3.檔案說明
3.1.核心層
usb_core.h:核心層的表頭檔
usb_core.c:
USB Interrupt Service Routine(USB_IRQHandler):
基本的USB中斷處理程序,開發者可經由Callback程序擴充中斷處理程序
操作模式配置(usb_core_mode_set):
配置USB控制器的操作模式,目前版本僅提供ForceDeviceMode,ForceHostMode
Soft Connect(usb_core_dev_connect):
在裝置模式下使用Soft Connect連接USB
Soft Disconnect(usb_core_dev_disconnect):
在裝置模式下使用Soft Disconnect斷接USB
3.2.裝置枚舉層
usb_enum.h:
usb_dev_enum.h:
usb_dev_enum.c:
USB標準請求處理程序(pUSBDStandardRequest[]):
所有USB標準請求基本處理流程處理,其中GET_DESCRIPTOR,SET_ADDRESS,SET_COFIGURATION,SET_INTERFACE可經由Callback程序擴充處理流程
裝置枚舉狀態(usbd_dev_enum):
經由相關的USB中斷處理紀錄目前的裝置枚舉狀態,提供給應用層開發相對應的應用流程,枚舉狀態定義於eUSBDState(usb_dev_enum.h)類型
3.3.裝置類(Class)枚舉層
usbhid.h:
usb_dev_hid.h:
usb_dev_hid.c:
HID裝置類(Class)請求處理程序(pHIDClassRequest[]):
相關HID裝置類(Class)請求基本處理流程,其中SET_REPORT,SET_IDLE,SET_PROTOCOL可經由Callback程序擴充請求處理流程
usbcdc.h:
usb_dev_cdc.h:
usb_dev_cdc.c: CDC裝置類(Class)請求處理程序(pCDCClassRequest[]): 相關CDC裝置類(Class)請求基本處理流程
usbmsc.h:
usb_dev_msc.h:
usb_dev_msc.c: MSC裝置類(Class)請求處理程序(pMSCClassRequest[]): 相關MSC裝置類(Class)請求基本處理流程
usbuac1.h:
usb_dev_uac1.h:
usb_dev_uac1.c: UAC1裝置類(Class)請求處理程序(pUAC1ClassRequest[]): 相關UAC1裝置類(Class)請求基本處理流程
usbuac2.h:
usb_dev_uac2.h:
usb_dev_uac2.c: UAC2裝置類(Class)請求處理程序(pUAC2ClassRequest[]): 相關UAC2裝置類(Class)請求基本處理流程
3.4.應用層
app_dev_xxxx.h:
app_dev_xxxx.c:
應用裝置初始化(xxxx_dev_init):
端點0初始化(以最大64Bytes初始化端點0Tx/Rx,開發者無須修改此函數),Enable端點0中斷
開發者將自訂的標準及裝置類(Class)請求的Callback函數位址以_CB_DEV_REQUEST_USER(usb_dev_enum.h)型態賦予以_USB_FS_DEVICE(usb_core.h)型態定義的USB裝置的cb_dev_req_user欄位,如無自訂Callback請求程序,則賦予NULL
開發者將自訂的USB中斷Callback函數位址賦予cb_app_usb_handler變數,如無自訂Callback中斷程序,則賦予NULL
應用裝置使用的端點配置(xxxx_dev_ep_config):
配置使用端點的類型,最大封包,記憶體位置,端點中斷
應用裝置枚舉狀態(xxxx_dev_enum):
經由裝置枚舉層的usbd_dev_enum紀錄目前的裝置枚舉狀態
應用裝置應用程序(xxxx_dev_transaction):
經由特定的端點狀態開發相對應的應用處理程序,這個程序為開發者最必須專注開發的程序,在USB應用過程中,開發者需針對對應的端點狀態及相關的應用處理流程開發相對應的程序
cb_dev_xxxx.h:
cb_dev_xxxx.c:
Callback程序,由於中斷,標準請求及裝置類(Class)請求的處理程序僅提供最基本的處理流程,在實際應用中可能需根據系統應用擴充額外的處理流程,這些流程依據應用的不同並無法提供一致性的流程,因此定義了Callback程序以提供開發者更彈性化的開發,Callback程序本身根據應用分成幾大項
USB中斷處理(cb_app_usb_handler):
額外的中斷處理流程,基本的USB中斷流程僅將中斷旗標記錄下來,清除中斷旗標,再回到主程序由usbd_dev_enum(usb_dev_enum.h)決定枚舉狀態,如果開發者希望增加額外的中斷處理流程,可自行開發處理程序,並將cb_app_usb_handler(usb_core.h)指向自行開發的中斷處理程序
標準請求流程(cb_dev_enum_user):
額外的標準請求處理流程,基本的標準請求處理流程僅依據USB規範的標準流程處理,在目前的協議棧中,提供GET_DESCRIPTOR、SET_ADDRESS、SET_CONFIGURATION、SET_INTERFACE可由開發者自行開發額外的處理流程,如果開發者希望增加額外的請求處理流程,可自行開發處理程序,並將_USB_FS_DEVICE(usb_dev_enum.h)中以_CB_DEV_REQUEST_USER(usb_dev_enum.h)型態定義的cb_dev_enum_user函數指標指向自行開發的請求處理程序,
GET_DESCRIPTOR:在額外的請求處理程序中,GET_DESCRIPTOR是目前開發者必需提供的請求處理程序,由於Descriptor Data是USB裝置與主機溝通的基本資訊,而且每一個應用裝置的Descriptor Data都不會相同,為保留最大的彈性,所有GET_DESCRIPTOR請求所需要的資訊將留給開發者提供,開發者須將_USB_FS_DEVICE(usb_dev_enum.h)中定義的pCtrlBurstData指標指向要回傳的Descriptor Data的位址,將_USB_FS_DEVICEㄒ中定義的CtrlBurstRemain變數填入要回傳的Descriptor Data的長度
類(Class)請求流程(cb_dev_class_user):
額外的類(Class)請求處理流程,基本的類(Class)請求處理流程僅依據USB類(Class)規範的標準流程處理,在目前的協議棧中,依據不同的類(Class)請求提供開發者開發額外的處理流程,如果開發者希望增加額外的類(Class)請求處理流程,可自行開發處理程序,並將_USB_FS_DEVICE(usb_dev_enum.h)中以_CB_DEV_REQUEST_USER(usb_dev_enum.h)型態定義的cb_dev_class_user函數指標指向自行開發的類(Class)請求處理程序,額外的類(Class)請求處理程序將於個別的應用開發例程中說明
app_xxxx_desc.h:
app_xxxx_desc.c:定義USB裝置的Descriptor Data
4.應用例程開發 - Device
4.1.宣告USB裝置
在開始開發應用例程之前,開發者必須先以_USB_FS_DEVICE(usb_dev_enum.h)的型態定義一個USB裝置,_USB_FS_DEVICE的類型定義在usb_dev_enum.h,類型的欄位說明如下:
DevAddr:主機賦予的USB裝置地址,預設為0,主機會透過SET_ADDRESS配置一個唯一的地址給USB裝置,當收到SET_ADDRESS的請求時,會將主機賦予的USB裝置地址存放在這裡,一個USB裝置只會有一個地址,在SET_ADDRESS的請求程序中已完成此配置 ConfigValue:主機配置的配置值,預設為0,主機會依據應用的不同透過SET_CONFIGURATION賦予不同的配置值,當收到SET_CONFIGURATION的請求時,會將主機配置的配置值存放在這裡,這個數值是由裝置定義的COnfiguration Descriptor中的bConfigurationValue決定,在一般應用下,一個裝置只會定義一個配置值,但在多重配置的應用下,一個裝置可以有好幾個不同的Configuration Descriptor,每一個Configuration Descriptor有各自的配置值,在SET_CONFIGURATION的請求程序中已完成此配置 pCtrlBurstData:用於指定Control In/Out的數據緩衝區指標,在處理Control In/Out時會直接從這裡所指向的數據緩衝區存取數據 CtrlBurstRemain:存放Control In/Out的數據剩餘長度,在處理Control In/Out時會從這裡所存放的數值決定還有多少數據 cb_dev_req_user:一個以_CB_DEV_REQUEST_USER(usb_dev_enum.h)的類型定義的Callback函數指標,指向處理額外的標準及裝置類(Class)請求的處理程序的Callback函數 在整個枚舉或請求的過程中,這個裝置都會以指標的形式作為函數呼叫的參數之一 另外一個以指標的形式作為函數呼叫的參數為以_USB_SETUP_REQUEST(usb_core.h)的型態定義的SetupReq指標參數,SetupReq包含USB標準請求所定義的8個字節的數據
4.2.初始化
主程序在做過系統相關的配置之後(系統時鐘,中斷,IO…)即可開始USB裝置的初始化流程
4.2.1.裝置初始化
應用程序需先對以_USB_FS_DEVICE(usb_dev_enum.h)的型態定義的USB裝置初始化xxxx_dev_init(app_dev_xxxx.c),初始化流程包含對端點0的配置(預設是以最大64Bytes配置,應用程序可以不必修改)以及對以_USB_FS_DEVICE(usb_dev_enum.h)的型態定義的USB裝置的Callbacl函數指標賦予標準請求及類(Class)請求的Callback函數的位址(如無Callback,則預設為NULL),應用程序如果需要處理額外的USB中斷流程,也可在此對cb_app_usb_handler賦予中斷流程的Callback函數位址 除了端點0之外,其他端點的配置不建議在這裡配置,這是因為在枚舉的過程中主機會下RESET命令,當USB控制器收到RESET命令時會重置所有端點的配置狀態,因此在本範例中,端點的配置是在RESET命令之後執行的,開發者也可以依據實際應用場景調整
4.2.2.配置運行模式
將模式配置為FORCEDEVICE(usb_core_mode_set)
4.3.開始枚舉流程
初始化完成之後便進入枚舉流程,應用程序呼叫xxxx_dev_enum(app_dev_xxxx.c)以決定枚舉狀態,所有關於標準請求及裝置類(Class)請求的流程都會經由usbd_dev_enum(usbd_dev_enum.c)及usbd_dev_xxx.c完成,當開發者需要需要在請求過程中處理額外的流程時,將透過xxxx_dev_init(app_dev_xxxx.c)指定的Callback函數位址完成,除了端點0的請求流程外,枚舉狀態還包含相關的端點中斷狀態(IN/Out),開發者須依據應用場景的端點中斷狀態處理相關的應用流程,這部分的流程將透過xxxx_dev_transaction(app_dev_xxxx.c)及其延伸的處理程序完成
4.4.應用流程圖
5.應用例程 - HID裝置
5.2.裝置初始化
呼叫hidenum_dev_init(app_dev_hidenum.c)對HID_FS_Dev初始化 呼叫usb_core_mode_set(usb_core.c)將運行模式設定為FORCEDEVICE Mode 呼叫hidenum_dev_enum(app_dev_hidenum.c)決定枚舉的USB狀態 依實際應用的端點狀態呼叫hidenum_dev_transaction(app_dev_hidenum.c)執行實際的應用程序
5.3.開發HID裝置的應用程序
app_dev_hidenum.c: hidenum_dev_init:設定端點0,將cb_dev_enum_user hidenum_dev_ep_config:設定HID應用的IN端點 hidenum_dev_enum:呼叫usbd_dev_enum(usb_dev_enum.c)以決定USB狀態,在USB主機發出SETUP時呼叫hidenum_dev_ep_config設定IN端點 hidenum_dev_transaction:依HID應用的實際流程開發應用程序,包含相關週邊IP的程序
cb_dev_hidenum.c: 以_CB_DEV_REQUEST_USER(usb_dev_enum.h)的型態定義一個cb_dev_hidenum_user,並將cb_dev_enum_user函數指標指向cb_dev_enum_user,cb_dev_class_user函數指標指向cb_dev_hid_user cb_dev_enum_user:開發GET_DESCRIPTOR的Callback處理程序,將相關Descriptor的數據指標及數據長度填入HID_FS_Dev的pCtrlBurstData及CtrlBurstRemain欄位中 cb_dev_hid_user:視實際應用情況決定是否要開發HID請求的SET_REPORT,SET_IDLE及SET_PROTOCOL Callback程序
app_hidenum_desc.c:定義HIDEnum裝置的Descriptor Data及Report Descriptor Data