《極海芯得》系列內容為用戶使用極海系列產品的經驗總結,均轉載自21ic論壇極海半導體專區,全文未作任何修改,未經原文作者授權禁止轉載。
最近需要使用到APM32F427枚舉成Custom HID設備進行用戶自定義通信,但我又不想要使用官方的USB中間件去做一個USB Custom HID設備。了解到Cherry USB這個開源的USB代碼,而且他最強的就是不需要使用芯片的任何關于USB的代碼,就能使用起來。所以,打算使用CherryUSB實現Custom HID設備。
1. Cherry USB簡介
CherryUSB是一個小而美的、可移植性高的、用于嵌入式系統(帶USB IP)的高性能 USB 主從協議棧。
關于CherryUSB的介紹,大家可以去它的開源倉庫和官方提供的介紹文檔進行學習。官方提供了很詳細的介紹和使用說明。
官方的使用教程:https://cherryusb.readthedocs.io/zh-cn/latest/
CherryUSB代碼倉庫:https://github.com/cherry-embedded/CherryUSB
CherryUSB厲害之處在于,它不需要使用到芯片SDK中任何關于USB相關的代碼,它是完全和芯片脫離關系的。CherryUSB它是基于USB IP寫的底層,和芯片完全沒有關系,所以移植使用CherryUSB也比較簡單。它支持了常見的USB IP。如下:

其中APM32F427使用的USB IP就是 DWC2 USB IP。
2. APM32F427移植CherryUSB實現Custom HID設備
2.1 準備工作
1、下載官網APM32F427 SDK。
下載路徑:
https://www.geehy.com/product/fifth/APM32F427_425_423#design
2、下載CherryUSB源碼。
CherryUSB代碼倉庫:
https://github.com/cherry-embedded/CherryUSB

下載的源碼暫時放到SDK的中間件目錄下備用。
3、復制一個SDK的可以正常使用的例程,然后基于這個例程進行移植CherryUSB。

2.2 提供CherryUSB的
usb_dc_low_level_init/usb_dc_low_level_deinit函數的實現
要移植實現CherryUSB,我們只需要提供usb_dc_low_level_init/usb_dc_low_level_deinit函數的實現即可。這兩個函數只是做了最底層的GPIO引腳初始化,以及開啟芯片的USB時鐘和中斷等與芯片相關的代碼。
1、復制usb_glue_st.c文件,修改為usb_glue_apm32f27.c文件。

2、根據原有的usb_dc_low_level_init函數,修改為適應APM32F427芯片的函數。
void usb_dc_low_level_init(uint8_t busid)
{
if (g_usbdev_bus[busid].reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = busid;
g_usb_dwc2_irq[1] = USBD_IRQHandler;
} else {
g_usb_dwc2_busid[0] = busid;
g_usb_dwc2_irq[0] = USBD_IRQHandler;
}
//g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)g_usbdev_bus[busid].reg_base;
//HAL_PCD_MspInit((PCD_HandleTypeDef *)&g_dwc2_instance);
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Configure USB OTG GPIO */
__DAL_RCM_GPIOA_CLK_ENABLE();
/* USB DM, DP pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
DAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Configure USB OTG */
__DAL_RCM_USB_OTG_FS_CLK_ENABLE();
/* Configure interrupt */
DAL_NVIC_SetPriority(OTG_FS_IRQn, 1U, 0U);
DAL_NVIC_EnableIRQ(OTG_FS_IRQn);
}
該函數主要實現了使用到的USB GPIO初始化,以及打開USB外設時鐘和使能USB中斷等硬件的初始化工作。
3、提供usb_dc_low_level_deinit函數實現
void usb_dc_low_level_deinit(uint8_t busid)
{
if (g_usbdev_bus[busid].reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = 0;
g_usb_dwc2_irq[1] = NULL;
} else {
g_usb_dwc2_busid[0] = 0;
g_usb_dwc2_irq[0] = NULL;
}
//g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)g_usbdev_bus[busid].reg_base;
//HAL_PCD_MspDeInit((PCD_HandleTypeDef *)&g_dwc2_instance);
/* Disable peripheral clock */
__DAL_RCM_USB_OTG_FS_CLK_DISABLE();
/* USB DM, DP pin configuration */
DAL_GPIO_DeInit(GPIOA, GPIO_PIN_11 | GPIO_PIN_12);
/* Disable peripheral interrupt */
DAL_NVIC_DisableIRQ(OTG_FS_IRQn);
}
該函數是usb_dc_low_level_init函數的反操作,解除GPIO初始化和失能時鐘等。
2.3 提供CherryUSB中斷函數的實現
調用USB中斷函數時,已經不能調用SDK提供的中斷處理函數了,需要調用Cherry提供的中斷處理函數。如下:
void OTG_FS_IRQHandler(void)
{
g_usb_dwc2_irq[0](g_usb_dwc2_busid[0]);
}
//void OTG_HS_IRQHandler(void)
void OTG_FS2_IRQHandler(void)
{
g_usb_dwc2_irq[1](g_usb_dwc2_busid[1]);
}
到這里就已經修改完了需要把CHerryUSB移植到APM32F427的底層的實現。修改實現的代碼,都保存到usb_glue_apm32f427.c這個文件里。
2.4 修改Keil工程配置
前面已經把該準備的代碼實現了,下面我們把復制的SDK一個例程,修改一下實現CherryUSB的例程。
1、添加CherryUSB源碼到Keil工程

2、添加CherryUSB的編譯路徑

3、CherryUSB倉庫代碼,把cherryusb_config_template.h復制這個文件到我們的工程目錄下,并修改名稱為 usb_config.h

2.5 實現CherryUSB Custom HID收發測試函數
前面的步驟已經相當于全部移植完了CherryUSB了。現在實現CherryUSB Custom HID應用層的收發測試函數。
void custom_hid_test(uint8_t busid)
{
uint8_t report[64] = {0};
if(usb_device_is_configured(busid) == false) {
return;
}
custom_state = HID_STATE_BUSY;
usbd_ep_start_write(busid, HIDRAW_IN_EP, (uint8_t *)&report, sizeof(report));
while (custom_state == HID_STATE_BUSY) {
}
}
這個函數就是把接收到數據返回到PC端上位機。
2.6 實現main函數的調用
在main函數,我們首先需要調用 hid_custom_init 函數進行CherryUSB的初始化,然后再主循環檢測到接收USB數據,就調用2.5小節實現的CherryUSB收發測試函數。如下:
int main(void)
{
// uint8_t mouse_cfg[4] = {};
/* Device configuration */
DAL_DeviceConfig();
// /* Output a message on Hyperterminal using printf function */
// LOG_Print(" UART Printf Example: retarget the C library printf function to the UART ");
// LOG_Print(" ** Test finished successfully. ** ");
hid_custom_init(0, USB_OTG_FS_PERIPH_BASE);
/* Infinite loop */
while (1)
{
if (usb_receive_flag == 1)
{
custom_hid_test(0);
}
}
}
3. USB Custom HID設備通信的測試驗證
關于測試驗證,和我之前寫的一篇文章很相似的,因為代碼實現都是和上位機進行收發測試。
3.1 在電腦的設備管理器查看
在第二節修改完代碼之后,編譯下載到APM32F427芯片,運行起來后,我們可以在windows系統的設備管理器的人體學輸入設備,查看到我們自己實現的USB Custom HID的。如下:

又或者通過控制面板的設備和打印機的選項,可以查看到我們實現的USB HID設備,如下:

可以看到我們實現的Cherry HID DEMO設備,說明修改的代碼已經正常運行。
3.2 通過PC端上位機工具進行數據收發測試
我們需要使用USB HID的調試工具,進行數據收發測試。關于這樣的上位機工具,網上有很多的。我這里使用的是PortHelper工具。這個工具大家可以網上搜一下下載。
1、打開PortHelper 上位機,然后選擇USB調試,然后找到
APM32 Custom HID 設備,然后打開USB

2、PortHelper 測試與APM32F427進行USB數據收發
打開USB之后,然后我們勾選hex發送,hex顯示。然后點擊發送即可,如下圖:

然后可以PC端上位機發送的數據給APM32F427,芯片原樣返回數據給該上位機。
到這里就實現的我們自定義的USB Custom HID設備,該設備主要是接收PC端上位機發送過來的數據,然后APM32F427接收進行處理。在實際項目我是需要基于這個通信進行更復雜的項目開發。
注:文章作者在原帖中提供了代碼文件,有需要請至原文21ic論壇
原文地址:https://bbs.21ic.com/icview-3501154-1-1.html?_dsign=67f2f385
或點擊下方閱讀原文跳轉
-
usb
+關注
關注
60文章
8438瀏覽量
284454 -
移植
+關注
關注
1文章
414瀏覽量
29392 -
極海半導體
+關注
關注
0文章
209瀏覽量
4825
原文標題:極海芯得 EP.72 | APM32F427移植CherryUSB實現自定義USB HID設備
文章出處:【微信號:geehysemi,微信公眾號:Geehy極海半導體】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
STM32 自定義HID USB設備的實現
STM32F107做USB host識別自定義HID設備有了解的嗎
采用HID協議實現工控自定義鍵盤接口設計
標準hid設備pc上驅動不用自己開發,自定義的hid設備windows系統的驅動用自己開發嗎
國民技術MCU應用筆記連載(4)——N32G45x系列USB自定義HID設備的實現
萬利EK-STM32板實現的自定義USB HID設備
【技術專欄】泰凌微電子USB HID 用戶自定義設備應用及調試
CherryUSB-HID設備實踐 | 技術集結
極海APM32F427系列MCU榮獲IEC 60730/60335功能安全認證
極海APM32F427移植CherryUSB實現自定義USB HID設備
評論