Переглянути джерело

[bsp/at32] add support usb driver (#6968)

* add support usb driver

* fixed code format error
sheltonyu 2 роки тому
батько
коміт
a5c62b9a84
75 змінених файлів з 10709 додано та 10 видалено
  1. 3 0
      bsp/at32/at32f403a-start/README.md
  2. 3 0
      bsp/at32/at32f403a-start/SConstruct
  3. 5 0
      bsp/at32/at32f403a-start/board/Kconfig
  4. 1 0
      bsp/at32/at32f403a-start/board/inc/at32_msp.h
  5. 66 0
      bsp/at32/at32f403a-start/board/src/at32_msp.c
  6. 3 0
      bsp/at32/at32f407-start/README.md
  7. 3 0
      bsp/at32/at32f407-start/SConstruct
  8. 5 0
      bsp/at32/at32f407-start/board/Kconfig
  9. 1 0
      bsp/at32/at32f407-start/board/inc/at32_msp.h
  10. 67 0
      bsp/at32/at32f407-start/board/src/at32_msp.c
  11. 3 0
      bsp/at32/at32f413-start/README.md
  12. 3 3
      bsp/at32/at32f413-start/SConscript
  13. 3 0
      bsp/at32/at32f413-start/SConstruct
  14. 5 0
      bsp/at32/at32f413-start/board/Kconfig
  15. 1 0
      bsp/at32/at32f413-start/board/inc/at32_msp.h
  16. 66 0
      bsp/at32/at32f413-start/board/src/at32_msp.c
  17. 3 0
      bsp/at32/at32f415-start/README.md
  18. 3 0
      bsp/at32/at32f415-start/SConstruct
  19. 20 0
      bsp/at32/at32f415-start/board/Kconfig
  20. 1 0
      bsp/at32/at32f415-start/board/inc/at32_msp.h
  21. 40 0
      bsp/at32/at32f415-start/board/src/at32_msp.c
  22. 3 0
      bsp/at32/at32f425-start/README.md
  23. 3 0
      bsp/at32/at32f425-start/SConstruct
  24. 20 0
      bsp/at32/at32f425-start/board/Kconfig
  25. 1 0
      bsp/at32/at32f425-start/board/inc/at32_msp.h
  26. 50 0
      bsp/at32/at32f425-start/board/src/at32_msp.c
  27. 5 0
      bsp/at32/at32f435-start/README.md
  28. 3 0
      bsp/at32/at32f435-start/SConstruct
  29. 35 0
      bsp/at32/at32f435-start/board/Kconfig
  30. 1 0
      bsp/at32/at32f435-start/board/inc/at32_msp.h
  31. 95 0
      bsp/at32/at32f435-start/board/src/at32_msp.c
  32. 5 0
      bsp/at32/at32f437-start/README.md
  33. 3 0
      bsp/at32/at32f437-start/SConstruct
  34. 35 0
      bsp/at32/at32f437-start/board/Kconfig
  35. 1 0
      bsp/at32/at32f437-start/board/inc/at32_msp.h
  36. 95 0
      bsp/at32/at32f437-start/board/src/at32_msp.c
  37. 4 3
      bsp/at32/libraries/AT32F403A_407_Firmware_Library/drivers/inc/at32f403a_407_usb.h
  38. 4 3
      bsp/at32/libraries/AT32F413_Firmware_Library/drivers/inc/at32f413_usb.h
  39. 9 0
      bsp/at32/libraries/rt_drivers/SConscript
  40. 69 0
      bsp/at32/libraries/rt_drivers/config/f403a_407/usb_config.h
  41. 69 0
      bsp/at32/libraries/rt_drivers/config/f413/usb_config.h
  42. 95 0
      bsp/at32/libraries/rt_drivers/config/f415/usb_config.h
  43. 95 0
      bsp/at32/libraries/rt_drivers/config/f425/usb_config.h
  44. 135 0
      bsp/at32/libraries/rt_drivers/config/f435_437/usb_config.h
  45. 6 1
      bsp/at32/libraries/rt_drivers/drv_config.h
  46. 274 0
      bsp/at32/libraries/rt_drivers/drv_usbd.c
  47. 27 0
      bsp/at32/libraries/rt_drivers/drv_usbd.h
  48. 28 0
      bsp/at32/libraries/rt_drivers/drv_usbfs.h
  49. 311 0
      bsp/at32/libraries/rt_drivers/drv_usbfsd.c
  50. 406 0
      bsp/at32/libraries/rt_drivers/drv_usbfsh.c
  51. 19 0
      bsp/at32/libraries/usbd_library/SConscript
  52. 376 0
      bsp/at32/libraries/usbd_library/inc/usb_std.h
  53. 181 0
      bsp/at32/libraries/usbd_library/inc/usbd_core.h
  54. 72 0
      bsp/at32/libraries/usbd_library/inc/usbd_int.h
  55. 63 0
      bsp/at32/libraries/usbd_library/inc/usbd_sdr.h
  56. 689 0
      bsp/at32/libraries/usbd_library/src/usbd_core.c
  57. 347 0
      bsp/at32/libraries/usbd_library/src/usbd_int.c
  58. 533 0
      bsp/at32/libraries/usbd_library/src/usbd_sdr.c
  59. 27 0
      bsp/at32/libraries/usbfs_library/SConscript
  60. 122 0
      bsp/at32/libraries/usbfs_library/inc/usb_core.h
  61. 368 0
      bsp/at32/libraries/usbfs_library/inc/usb_std.h
  62. 176 0
      bsp/at32/libraries/usbfs_library/inc/usbd_core.h
  63. 85 0
      bsp/at32/libraries/usbfs_library/inc/usbd_int.h
  64. 65 0
      bsp/at32/libraries/usbfs_library/inc/usbd_sdr.h
  65. 367 0
      bsp/at32/libraries/usbfs_library/inc/usbh_core.h
  66. 98 0
      bsp/at32/libraries/usbfs_library/inc/usbh_ctrl.h
  67. 71 0
      bsp/at32/libraries/usbfs_library/inc/usbh_int.h
  68. 171 0
      bsp/at32/libraries/usbfs_library/src/usb_core.c
  69. 870 0
      bsp/at32/libraries/usbfs_library/src/usbd_core.c
  70. 560 0
      bsp/at32/libraries/usbfs_library/src/usbd_int.c
  71. 535 0
      bsp/at32/libraries/usbfs_library/src/usbd_sdr.c
  72. 1222 0
      bsp/at32/libraries/usbfs_library/src/usbh_core.c
  73. 958 0
      bsp/at32/libraries/usbfs_library/src/usbh_ctrl.c
  74. 540 0
      bsp/at32/libraries/usbfs_library/src/usbh_int.c
  75. 2 0
      bsp/at32/tools/sdk_dist.py

+ 3 - 0
bsp/at32/at32f403a-start/README.md

@@ -50,6 +50,7 @@ AT32F403A-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | WDT       | 支持     |                            |
 | RTC       | 支持     |                            |
 | FLASH     | 支持     |                            |
+| USB       | 支持     |                            |
 
 ### IO在板级支持包中的映射情况
 
@@ -94,6 +95,8 @@ AT32F403A-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PB9  | CAN1_TX        |
 | PB5  | CAN2_RX        |
 | PB6  | CAN2_TX        |
+| PA11 | USB_DM         |
+| PA12 | USB_DP         |
 
 ## 使用说明
 

+ 3 - 0
bsp/at32/at32f403a-start/SConstruct

@@ -52,6 +52,9 @@ rtconfig.BSP_LIBRARY_TYPE = at32_library
 # include libraries
 objs.extend(SConscript(os.path.join(libraries_path_prefix, at32_library, 'SConscript')))
 
+# include usb libraries
+objs.extend(SConscript(os.path.join(libraries_path_prefix, 'usbd_library', 'SConscript')))
+
 # include drivers
 objs.extend(SConscript(os.path.join(libraries_path_prefix, 'rt_drivers', 'SConscript')))
 

+ 5 - 0
bsp/at32/at32f403a-start/board/Kconfig

@@ -26,6 +26,11 @@ menu "On-chip Peripheral Drivers"
 
     config BSP_USING_ON_CHIP_FLASH
         bool "Enable on-chip FLASH"
+        default n 
+
+    config BSP_USING_USBD
+        bool "Enable USB BUS"
+        select RT_USING_USB_DEVICE
         default n
 
     menuconfig BSP_USING_RTC

+ 1 - 0
bsp/at32/at32f403a-start/board/inc/at32_msp.h

@@ -19,5 +19,6 @@ void at32_msp_sdio_init(void *instance);
 void at32_msp_adc_init(void *instance);
 void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
+void at32_msp_usb_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 66 - 0
bsp/at32/at32f403a-start/board/src/at32_msp.c

@@ -317,3 +317,69 @@ void at32_msp_can_init(void *instance)
 #endif
 }
 #endif /* BSP_USING_CAN */
+
+#ifdef BSP_USING_USBD
+void at32_msp_usb_init(void *instance)
+{
+    usb_clk48_s clk_s;
+
+    /* default usb clock source from hick */
+    clk_s = USB_CLK_HICK;
+
+    /* enable usb clock */
+    crm_periph_clock_enable(CRM_USB_PERIPH_CLOCK, TRUE);
+
+    if(clk_s == USB_CLK_HICK)
+    {
+        crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
+
+        /* enable the acc calibration ready interrupt */
+        crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
+
+        /* update the c1\c2\c3 value */
+        acc_write_c1(7980);
+        acc_write_c2(8000);
+        acc_write_c3(8020);
+
+        /* open acc calibration */
+        acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
+    }
+    else
+    {
+        switch(system_core_clock)
+        {
+            /* 48MHz */
+            case 48000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1);
+                break;
+            /* 72MHz */
+            case 72000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1_5);
+                break;
+            /* 96MHz */
+            case 96000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2);
+                break;
+            /* 120MHz */
+            case 120000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2_5);
+                break;
+            /* 144MHz */
+            case 144000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3);
+                break;
+            /* 168MHz */
+            case 168000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3_5);
+                break;
+            /* 192MHz */
+            case 192000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_4);
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+#endif /* BSP_USING_USBD */

+ 3 - 0
bsp/at32/at32f407-start/README.md

@@ -51,6 +51,7 @@ AT32F407-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | RTC       | 支持     |                            |
 | FLASH     | 支持     |                            |
 | EMAC      | 支持     |                            |
+| USB       | 支持     |                            |
 
 ### IO在板级支持包中的映射情况
 
@@ -102,6 +103,8 @@ AT32F407-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PD9  | EMAC_RMII_RXD0    |
 | PD10 | EMAC_RMII_RXD1    |
 | PA1  | EMAC_RMII_REF_CLK |
+| PA11 | USB_DM            |
+| PA12 | USB_DP            |
 
 ## 使用说明
 

+ 3 - 0
bsp/at32/at32f407-start/SConstruct

@@ -52,6 +52,9 @@ rtconfig.BSP_LIBRARY_TYPE = at32_library
 # include libraries
 objs.extend(SConscript(os.path.join(libraries_path_prefix, at32_library, 'SConscript')))
 
+# include usb libraries
+objs.extend(SConscript(os.path.join(libraries_path_prefix, 'usbd_library', 'SConscript')))
+
 # include drivers
 objs.extend(SConscript(os.path.join(libraries_path_prefix, 'rt_drivers', 'SConscript')))
 

+ 5 - 0
bsp/at32/at32f407-start/board/Kconfig

@@ -45,6 +45,11 @@ menu "On-chip Peripheral Drivers"
             endchoice
         endif
 
+    config BSP_USING_USBD
+        bool "Enable USB BUS"
+        select RT_USING_USB_DEVICE
+        default n
+
     menuconfig BSP_USING_RTC
         bool "Enable RTC"
         select RT_USING_RTC

+ 1 - 0
bsp/at32/at32f407-start/board/inc/at32_msp.h

@@ -20,5 +20,6 @@ void at32_msp_adc_init(void *instance);
 void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
 void at32_msp_emac_init(void *instance);
+void at32_msp_usb_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 67 - 0
bsp/at32/at32f407-start/board/src/at32_msp.c

@@ -358,3 +358,70 @@ void at32_msp_emac_init(void *instance)
     gpio_init(GPIOD, &gpio_init_struct);
 }
 #endif /* BSP_USING_EMAC */
+
+#ifdef BSP_USING_USBD
+void at32_msp_usb_init(void *instance)
+{
+    usb_clk48_s clk_s;
+
+    /* default usb clock source from hick */
+    clk_s = USB_CLK_HICK;
+
+    /* enable usb clock */
+    crm_periph_clock_enable(CRM_USB_PERIPH_CLOCK, TRUE);
+
+    if(clk_s == USB_CLK_HICK)
+    {
+        crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
+
+        /* enable the acc calibration ready interrupt */
+        crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
+
+        /* update the c1\c2\c3 value */
+        acc_write_c1(7980);
+        acc_write_c2(8000);
+        acc_write_c3(8020);
+
+        /* open acc calibration */
+        acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
+    }
+    else
+    {
+        switch(system_core_clock)
+        {
+            /* 48MHz */
+            case 48000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1);
+                break;
+            /* 72MHz */
+            case 72000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1_5);
+                break;
+            /* 96MHz */
+            case 96000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2);
+                break;
+            /* 120MHz */
+            case 120000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2_5);
+                break;
+            /* 144MHz */
+            case 144000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3);
+                break;
+            /* 168MHz */
+            case 168000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3_5);
+                break;
+            /* 192MHz */
+            case 192000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_4);
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+#endif /* BSP_USING_USBD */
+

+ 3 - 0
bsp/at32/at32f413-start/README.md

@@ -50,6 +50,7 @@ AT32F413-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | WDT       | 支持     |                            |
 | RTC       | 支持     |                            |
 | FLASH     | 支持     |                            |
+| USB       | 支持     |                            |
 
 ### IO在板级支持包中的映射情况
 
@@ -94,6 +95,8 @@ AT32F413-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PB9  | CAN1_TX        |
 | PB5  | CAN2_RX        |
 | PB6  | CAN2_TX        |
+| PA11 | USB_DM         |
+| PA12 | USB_DP         |
 
 ## 使用说明
 

+ 3 - 3
bsp/at32/at32f413-start/SConscript

@@ -1,11 +1,11 @@
 # for module compiling
+from building import *
 import os
-Import('RTT_ROOT')
 
-cwd = str(Dir('#'))
+cwd = GetCurrentDir()
 objs = []
-list = os.listdir(cwd)
 
+list = os.listdir(cwd)
 for d in list:
     path = os.path.join(cwd, d)
     if os.path.isfile(os.path.join(path, 'SConscript')):

+ 3 - 0
bsp/at32/at32f413-start/SConstruct

@@ -52,6 +52,9 @@ rtconfig.BSP_LIBRARY_TYPE = at32_library
 # include libraries
 objs.extend(SConscript(os.path.join(libraries_path_prefix, at32_library, 'SConscript')))
 
+# include usb libraries
+objs.extend(SConscript(os.path.join(libraries_path_prefix, 'usbd_library', 'SConscript')))
+
 # include drivers
 objs.extend(SConscript(os.path.join(libraries_path_prefix, 'rt_drivers', 'SConscript')))
 

+ 5 - 0
bsp/at32/at32f413-start/board/Kconfig

@@ -26,6 +26,11 @@ menu "On-chip Peripheral Drivers"
 
     config BSP_USING_ON_CHIP_FLASH
         bool "Enable on-chip FLASH"
+        default n 
+
+    config BSP_USING_USBD
+        bool "Enable USB BUS"
+        select RT_USING_USB_DEVICE
         default n
 
     menuconfig BSP_USING_RTC

+ 1 - 0
bsp/at32/at32f413-start/board/inc/at32_msp.h

@@ -19,5 +19,6 @@ void at32_msp_sdio_init(void *instance);
 void at32_msp_adc_init(void *instance);
 void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
+void at32_msp_usb_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 66 - 0
bsp/at32/at32f413-start/board/src/at32_msp.c

@@ -317,3 +317,69 @@ void at32_msp_can_init(void *instance)
 #endif
 }
 #endif /* BSP_USING_CAN */
+
+#ifdef BSP_USING_USBD
+void at32_msp_usb_init(void *instance)
+{
+    usb_clk48_s clk_s;
+
+    /* default usb clock source from hick */
+    clk_s = USB_CLK_HICK;
+
+    /* enable usb clock */
+    crm_periph_clock_enable(CRM_USB_PERIPH_CLOCK, TRUE);
+
+    if(clk_s == USB_CLK_HICK)
+    {
+        crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
+
+        /* enable the acc calibration ready interrupt */
+        crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
+
+        /* update the c1\c2\c3 value */
+        acc_write_c1(7980);
+        acc_write_c2(8000);
+        acc_write_c3(8020);
+
+        /* open acc calibration */
+        acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
+    }
+    else
+    {
+        switch(system_core_clock)
+        {
+            /* 48MHz */
+            case 48000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1);
+                break;
+            /* 72MHz */
+            case 72000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1_5);
+                break;
+            /* 96MHz */
+            case 96000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2);
+                break;
+            /* 120MHz */
+            case 120000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2_5);
+                break;
+            /* 144MHz */
+            case 144000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3);
+                break;
+            /* 168MHz */
+            case 168000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3_5);
+                break;
+            /* 192MHz */
+            case 192000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_4);
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+#endif /* BSP_USING_USBD */

+ 3 - 0
bsp/at32/at32f415-start/README.md

@@ -50,6 +50,7 @@ AT32F415-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | WDT       | 支持     |                            |
 | RTC       | 支持     |                            |
 | FLASH     | 支持     |                            |
+| USB       | 支持     |                            |
 
 ### IO在板级支持包中的映射情况
 
@@ -92,6 +93,8 @@ AT32F415-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PC5  | ADC1_IN15      |
 | PB8  | CAN1_RX        |
 | PB9  | CAN1_TX        |
+| PA11 | USB_DM         |
+| PA12 | USB_DP         |
 
 ## 使用说明
 

+ 3 - 0
bsp/at32/at32f415-start/SConstruct

@@ -52,6 +52,9 @@ rtconfig.BSP_LIBRARY_TYPE = at32_library
 # include libraries
 objs.extend(SConscript(os.path.join(libraries_path_prefix, at32_library, 'SConscript')))
 
+# include usb libraries
+objs.extend(SConscript(os.path.join(libraries_path_prefix, 'usbfs_library', 'SConscript')))
+
 # include drivers
 objs.extend(SConscript(os.path.join(libraries_path_prefix, 'rt_drivers', 'SConscript')))
 

+ 20 - 0
bsp/at32/at32f415-start/board/Kconfig

@@ -26,7 +26,27 @@ menu "On-chip Peripheral Drivers"
 
     config BSP_USING_ON_CHIP_FLASH
         bool "Enable on-chip FLASH"
+        default n 
+
+    menuconfig BSP_USING_USBFS
+        bool "Enable USB BUS"
         default n
+        if BSP_USING_USBFS
+            menuconfig BSP_USING_USBFS1
+                bool "Enable USB BUS1"
+                default n
+                if BSP_USING_USBFS1
+                    config BSP_USING_DEVICE_USBFS1
+                        bool "Enable USB1 Deivce"
+                        select RT_USING_USB_DEVICE
+                        default n
+
+                    config BSP_USING_HOST_USBFS1
+                        bool "Enable USB1 Host"
+                        select RT_USING_USB_HOST
+                        default n
+                endif
+        endif
 
     menuconfig BSP_USING_RTC
         bool "Enable RTC"

+ 1 - 0
bsp/at32/at32f415-start/board/inc/at32_msp.h

@@ -19,5 +19,6 @@ void at32_msp_sdio_init(void *instance);
 void at32_msp_adc_init(void *instance);
 void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
+void at32_msp_usb_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 40 - 0
bsp/at32/at32f415-start/board/src/at32_msp.c

@@ -283,3 +283,43 @@ void at32_msp_can_init(void *instance)
 #endif
 }
 #endif /* BSP_USING_CAN */
+
+#ifdef BSP_USING_USBFS
+void at32_msp_usb_init(void *instance)
+{
+    /* enable usb clock */
+    crm_periph_clock_enable(CRM_OTGFS1_PERIPH_CLOCK, TRUE);
+
+    switch(system_core_clock)
+    {
+        /* 48MHz */
+        case 48000000:
+            crm_usb_clock_div_set(CRM_USB_DIV_1);
+            break;
+
+        /* 72MHz */
+        case 72000000:
+            crm_usb_clock_div_set(CRM_USB_DIV_1_5);
+            break;
+
+        /* 96MHz */
+        case 96000000:
+            crm_usb_clock_div_set(CRM_USB_DIV_2);
+            break;
+
+        /* 120MHz */
+        case 120000000:
+            crm_usb_clock_div_set(CRM_USB_DIV_2_5);
+            break;
+
+        /* 144MHz */
+        case 144000000:
+            crm_usb_clock_div_set(CRM_USB_DIV_3);
+            break;
+
+        default:
+            break;
+    }
+}
+
+#endif /* BSP_USING_USBFS */

+ 3 - 0
bsp/at32/at32f425-start/README.md

@@ -49,6 +49,7 @@ AT32F425-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | WDT       | 支持     |                            |
 | RTC       | 支持     |                            |
 | FLASH     | 支持     |                            |
+| USB       | 支持     |                            |
 
 ### IO在板级支持包中的映射情况
 
@@ -85,6 +86,8 @@ AT32F425-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PC5  | ADC1_IN15      |
 | PB8  | CAN1_RX        |
 | PB9  | CAN1_TX        |
+| PA11 | USB_DM         |
+| PA12 | USB_DP         |
 
 ## 使用说明
 

+ 3 - 0
bsp/at32/at32f425-start/SConstruct

@@ -52,6 +52,9 @@ rtconfig.BSP_LIBRARY_TYPE = at32_library
 # include libraries
 objs.extend(SConscript(os.path.join(libraries_path_prefix, at32_library, 'SConscript')))
 
+# include usb libraries
+objs.extend(SConscript(os.path.join(libraries_path_prefix, 'usbfs_library', 'SConscript')))
+
 # include drivers
 objs.extend(SConscript(os.path.join(libraries_path_prefix, 'rt_drivers', 'SConscript')))
 

+ 20 - 0
bsp/at32/at32f425-start/board/Kconfig

@@ -26,7 +26,27 @@ menu "On-chip Peripheral Drivers"
 
     config BSP_USING_ON_CHIP_FLASH
         bool "Enable on-chip FLASH"
+        default n 
+
+    menuconfig BSP_USING_USBFS
+        bool "Enable USB BUS"
         default n
+        if BSP_USING_USBFS
+            menuconfig BSP_USING_USBFS1
+                bool "Enable USB BUS1"
+                default n
+                if BSP_USING_USBFS1
+                    config BSP_USING_DEVICE_USBFS1
+                        bool "Enable USB1 Deivce"
+                        select RT_USING_USB_DEVICE
+                        default n
+
+                    config BSP_USING_HOST_USBFS1
+                        bool "Enable USB1 Host"
+                        select RT_USING_USB_HOST
+                        default n
+                endif
+        endif
 
     menuconfig BSP_USING_RTC
         bool "Enable RTC"

+ 1 - 0
bsp/at32/at32f425-start/board/inc/at32_msp.h

@@ -17,5 +17,6 @@ void at32_msp_tmr_init(void *instance);
 void at32_msp_adc_init(void *instance);
 void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
+void at32_msp_usb_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 50 - 0
bsp/at32/at32f425-start/board/src/at32_msp.c

@@ -247,3 +247,53 @@ void at32_msp_can_init(void *instance)
 #endif
 }
 #endif /* BSP_USING_CAN */
+
+#ifdef BSP_USING_USBFS
+void at32_msp_usb_init(void *instance)
+{
+    /* defalut usb clock from hext */
+    usb_clk48_s clk_s = USB_CLK_HICK;
+
+    crm_periph_clock_enable(CRM_OTGFS1_PERIPH_CLOCK, TRUE);
+
+    if(clk_s == USB_CLK_HICK)
+    {
+        crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
+
+        /* enable the acc calibration ready interrupt */
+        crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
+
+        /* update the c1\c2\c3 value */
+        acc_write_c1(7980);
+        acc_write_c2(8000);
+        acc_write_c3(8020);
+
+        /* open acc calibration */
+        acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
+    }
+    else
+    {
+        switch(system_core_clock)
+        {
+            /* 48MHz */
+            case 48000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1);
+                break;
+
+            /* 72MHz */
+            case 72000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1_5);
+                break;
+
+            /* 96MHz */
+            case 96000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2);
+                break;
+
+            default:
+                break;
+        }
+    }
+}
+
+#endif /* BSP_USING_USBFS */

+ 5 - 0
bsp/at32/at32f435-start/README.md

@@ -52,6 +52,7 @@ AT32F437-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | RTC       | 支持     |                            |
 | FLASH     | 支持     |                            |
 | SDRAM     | 支持     |                            |
+| USB       | 支持     |                            |
 
 ### IO在板级支持包中的映射情况
 
@@ -108,6 +109,10 @@ AT32F437-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PE10 | QSPI2_IO3         |
 | PG13 | QSPI2_SCK         |
 | PG8  | QSPI2_CS          |
+| PA11 | USB1_DM           |
+| PA12 | USB1_DP           |
+| PB14 | USB2_DM           |
+| PB15 | USB2_DP           |
 
 ## 使用说明
 

+ 3 - 0
bsp/at32/at32f435-start/SConstruct

@@ -52,6 +52,9 @@ rtconfig.BSP_LIBRARY_TYPE = at32_library
 # include libraries
 objs.extend(SConscript(os.path.join(libraries_path_prefix, at32_library, 'SConscript')))
 
+# include usb libraries
+objs.extend(SConscript(os.path.join(libraries_path_prefix, 'usbfs_library', 'SConscript')))
+
 # include drivers
 objs.extend(SConscript(os.path.join(libraries_path_prefix, 'rt_drivers', 'SConscript')))
 

+ 35 - 0
bsp/at32/at32f435-start/board/Kconfig

@@ -30,7 +30,42 @@ menu "On-chip Peripheral Drivers"
 
     config BSP_USING_ON_CHIP_FLASH
         bool "Enable on-chip FLASH"
+        default n 
+
+    menuconfig BSP_USING_USBFS
+        bool "Enable USB BUS"
         default n
+        if BSP_USING_USBFS
+            menuconfig BSP_USING_USBFS1
+                bool "Enable USB BUS1"
+                default n
+                if BSP_USING_USBFS1
+                    config BSP_USING_DEVICE_USBFS1
+                        bool "Enable USB1 Deivce"
+                        select RT_USING_USB_DEVICE
+                        default n
+
+                    config BSP_USING_HOST_USBFS1
+                        bool "Enable USB1 Host"
+                        select RT_USING_USB_HOST
+                        default n
+                endif
+
+            menuconfig BSP_USING_USBFS2
+                bool "Enable USB BUS2"
+                default n
+                if BSP_USING_USBFS2
+                    config BSP_USING_DEVICE_USBFS2
+                        bool "Enable USB2 Deivce"
+                        select RT_USING_USB_DEVICE
+                        default n
+
+                    config BSP_USING_HOST_USBFS2
+                        bool "Enable USB2 Host"
+                        select RT_USING_USB_HOST
+                        default n
+                endif
+        endif
 
     menuconfig BSP_USING_QSPI
         bool "Enable QSPI BUS"

+ 1 - 0
bsp/at32/at32f435-start/board/inc/at32_msp.h

@@ -21,5 +21,6 @@ void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
 void at32_msp_qspi_init(void *instance);
 void at32_msp_sdram_init(void *instance);
+void at32_msp_usb_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 95 - 0
bsp/at32/at32f435-start/board/src/at32_msp.c

@@ -477,3 +477,98 @@ void at32_msp_sdram_init(void *instance)
 }
 
 #endif /* BSP_USING_SDRAM */
+
+#ifdef BSP_USING_USBFS
+void at32_msp_usb_init(void *instance)
+{
+    /* defalut usb clock from hick */
+    usb_clk48_s clk_s = USB_CLK_HICK;
+
+#if defined (BSP_USING_HOST_USBFS1) || defined (BSP_USING_DEVICE_USBFS1)
+    crm_periph_clock_enable(CRM_OTGFS1_PERIPH_CLOCK, TRUE);
+#endif
+
+#if defined (BSP_USING_HOST_USBFS2) || defined (BSP_USING_DEVICE_USBFS2)
+    crm_periph_clock_enable(CRM_OTGFS2_PERIPH_CLOCK, TRUE);
+#endif
+
+    if(clk_s == USB_CLK_HICK)
+    {
+        crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
+        /* enable the acc calibration ready interrupt */
+        crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
+
+        /* update the c1\c2\c3 value */
+        acc_write_c1(7980);
+        acc_write_c2(8000);
+        acc_write_c3(8020);
+
+        /* open acc calibration */
+        acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
+    }
+    else
+    {
+        switch(system_core_clock)
+        {
+            /* 48MHz */
+            case 48000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1);
+                break;
+
+            /* 72MHz */
+            case 72000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1_5);
+                break;
+
+            /* 96MHz */
+            case 96000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2);
+                break;
+
+            /* 120MHz */
+            case 120000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2_5);
+                break;
+
+            /* 144MHz */
+            case 144000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3);
+                break;
+
+            /* 168MHz */
+            case 168000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3_5);
+                break;
+
+            /* 192MHz */
+            case 192000000:
+              crm_usb_clock_div_set(CRM_USB_DIV_4);
+              break;
+
+            /* 216MHz */
+            case 216000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_4_5);
+                break;
+
+            /* 240MHz */
+            case 240000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_5);
+                break;
+
+            /* 264MHz */
+            case 264000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_5_5);
+                break;
+
+            /* 288MHz */
+            case 288000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_6);
+                break;
+
+            default:
+                break;
+        }
+    }
+}
+
+#endif /* BSP_USING_USBFS */

+ 5 - 0
bsp/at32/at32f437-start/README.md

@@ -53,6 +53,7 @@ AT32F437-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | FLASH     | 支持     |                            |
 | EMAC      | 支持     |                            |
 | SDRAM     | 支持     |                            |
+| USB       | 支持     |                            |
 
 ### IO在板级支持包中的映射情况
 
@@ -116,6 +117,10 @@ AT32F437-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PE10 | QSPI2_IO3         |
 | PG13 | QSPI2_SCK         |
 | PG8  | QSPI2_CS          |
+| PA11 | USB1_DM           |
+| PA12 | USB1_DP           |
+| PB14 | USB2_DM           |
+| PB15 | USB2_DP           |
 
 ## 使用说明
 

+ 3 - 0
bsp/at32/at32f437-start/SConstruct

@@ -52,6 +52,9 @@ rtconfig.BSP_LIBRARY_TYPE = at32_library
 # include libraries
 objs.extend(SConscript(os.path.join(libraries_path_prefix, at32_library, 'SConscript')))
 
+# include usb libraries
+objs.extend(SConscript(os.path.join(libraries_path_prefix, 'usbfs_library', 'SConscript')))
+
 # include drivers
 objs.extend(SConscript(os.path.join(libraries_path_prefix, 'rt_drivers', 'SConscript')))
 

+ 35 - 0
bsp/at32/at32f437-start/board/Kconfig

@@ -32,6 +32,41 @@ menu "On-chip Peripheral Drivers"
         bool "Enable on-chip FLASH"
         default n
 
+    menuconfig BSP_USING_USBFS
+        bool "Enable USB BUS"
+        default n
+        if BSP_USING_USBFS
+            menuconfig BSP_USING_USBFS1
+                bool "Enable USB BUS1"
+                default n
+                if BSP_USING_USBFS1
+                    config BSP_USING_DEVICE_USBFS1
+                        bool "Enable USB1 Deivce"
+                        select RT_USING_USB_DEVICE
+                        default n
+
+                    config BSP_USING_HOST_USBFS1
+                        bool "Enable USB1 Host"
+                        select RT_USING_USB_HOST
+                        default n
+                endif
+
+            menuconfig BSP_USING_USBFS2
+                bool "Enable USB BUS2"
+                default n
+                if BSP_USING_USBFS2
+                    config BSP_USING_DEVICE_USBFS2
+                        bool "Enable USB2 Deivce"
+                        select RT_USING_USB_DEVICE
+                        default n
+
+                    config BSP_USING_HOST_USBFS2
+                        bool "Enable USB2 Host"
+                        select RT_USING_USB_HOST
+                        default n
+                endif
+        endif
+
     config BSP_USING_EMAC
         bool "Enable Ethernet"
         default n

+ 1 - 0
bsp/at32/at32f437-start/board/inc/at32_msp.h

@@ -22,5 +22,6 @@ void at32_msp_can_init(void *instance);
 void at32_msp_qspi_init(void *instance);
 void at32_msp_sdram_init(void *instance);
 void at32_msp_emac_init(void *instance);
+void at32_msp_usb_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 95 - 0
bsp/at32/at32f437-start/board/src/at32_msp.c

@@ -517,3 +517,98 @@ void at32_msp_sdram_init(void *instance)
 }
 
 #endif /* BSP_USING_SDRAM */
+
+#ifdef BSP_USING_USBFS
+void at32_msp_usb_init(void *instance)
+{
+    /* defalut usb clock from hick */
+    usb_clk48_s clk_s = USB_CLK_HICK;
+
+#if defined (BSP_USING_HOST_USBFS1) || defined (BSP_USING_DEVICE_USBFS1)
+    crm_periph_clock_enable(CRM_OTGFS1_PERIPH_CLOCK, TRUE);
+#endif
+
+#if defined (BSP_USING_HOST_USBFS2) || defined (BSP_USING_DEVICE_USBFS2)
+    crm_periph_clock_enable(CRM_OTGFS2_PERIPH_CLOCK, TRUE);
+#endif
+
+    if(clk_s == USB_CLK_HICK)
+    {
+        crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
+        /* enable the acc calibration ready interrupt */
+        crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
+
+        /* update the c1\c2\c3 value */
+        acc_write_c1(7980);
+        acc_write_c2(8000);
+        acc_write_c3(8020);
+
+        /* open acc calibration */
+        acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
+    }
+    else
+    {
+        switch(system_core_clock)
+        {
+            /* 48MHz */
+            case 48000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1);
+                break;
+
+            /* 72MHz */
+            case 72000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_1_5);
+                break;
+
+            /* 96MHz */
+            case 96000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2);
+                break;
+
+            /* 120MHz */
+            case 120000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_2_5);
+                break;
+
+            /* 144MHz */
+            case 144000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3);
+                break;
+
+            /* 168MHz */
+            case 168000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_3_5);
+                break;
+
+            /* 192MHz */
+            case 192000000:
+              crm_usb_clock_div_set(CRM_USB_DIV_4);
+              break;
+
+            /* 216MHz */
+            case 216000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_4_5);
+                break;
+
+            /* 240MHz */
+            case 240000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_5);
+                break;
+
+            /* 264MHz */
+            case 264000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_5_5);
+                break;
+
+            /* 288MHz */
+            case 288000000:
+                crm_usb_clock_div_set(CRM_USB_DIV_6);
+                break;
+
+            default:
+                break;
+        }
+    }
+}
+
+#endif /* BSP_USING_USBFS */

+ 4 - 3
bsp/at32/libraries/AT32F403A_407_Firmware_Library/drivers/inc/at32f403a_407_usb.h

@@ -195,15 +195,16 @@ typedef enum
 #ifndef USB_EPT_MAX_NUM
 #define USB_EPT_MAX_NUM                   8  /*!< usb device support endpoint number */
 #endif
+
 /**
   * @brief endpoint transfer type define
   */
 typedef enum
 {
   EPT_CONTROL_TYPE                       = 0x00, /*!< usb transfer type control */
-  EPT_BULK_TYPE                          = 0x01, /*!< usb transfer type bulk */
-  EPT_INT_TYPE                           = 0x02, /*!< usb transfer type interrut */
-  EPT_ISO_TYPE                           = 0x03  /*!< usb transfer type iso */
+  EPT_ISO_TYPE                           = 0x01, /*!< usb transfer type iso */
+  EPT_BULK_TYPE                          = 0x02, /*!< usb transfer type bulk */
+  EPT_INT_TYPE                           = 0x03  /*!< usb transfer type interrupt */
 }ept_trans_type;
 
 /**

+ 4 - 3
bsp/at32/libraries/AT32F413_Firmware_Library/drivers/inc/at32f413_usb.h

@@ -195,15 +195,16 @@ typedef enum
 #ifndef USB_EPT_MAX_NUM
 #define USB_EPT_MAX_NUM                   8  /*!< usb device support endpoint number */
 #endif
+
 /**
   * @brief endpoint transfer type define
   */
 typedef enum
 {
   EPT_CONTROL_TYPE                       = 0x00, /*!< usb transfer type control */
-  EPT_BULK_TYPE                          = 0x01, /*!< usb transfer type bulk */
-  EPT_INT_TYPE                           = 0x02, /*!< usb transfer type interrut */
-  EPT_ISO_TYPE                           = 0x03  /*!< usb transfer type iso */
+  EPT_ISO_TYPE                           = 0x01, /*!< usb transfer type iso */
+  EPT_BULK_TYPE                          = 0x02, /*!< usb transfer type bulk */
+  EPT_INT_TYPE                           = 0x03  /*!< usb transfer type interrupt */
 }ept_trans_type;
 
 /**

+ 9 - 0
bsp/at32/libraries/rt_drivers/SConscript

@@ -62,6 +62,15 @@ if GetDepend(['BSP_USING_CAN']):
 if GetDepend(['BSP_USING_SDIO']):
     src += ['drv_sdio.c']
 
+if GetDepend(['BSP_USING_USBD']):
+    src += ['drv_usbd.c']
+
+if GetDepend(['BSP_USING_DEVICE_USBFS1']) or GetDepend(['BSP_USING_DEVICE_USBFS2']):
+    src += ['drv_usbfsd.c']
+
+if GetDepend(['BSP_USING_HOST_USBFS1']) or GetDepend(['BSP_USING_HOST_USBFS2']):
+    src += ['drv_usbfsh.c']
+
 path =  [cwd]
 path += [cwd + '/config']
 

+ 69 - 0
bsp/at32/libraries/rt_drivers/config/f403a_407/usb_config.h

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     leo          first version
+ */
+
+#ifndef __USB_CONFIG_H__
+#define __USB_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* usb irqhandler */
+#define USB_IRQHandler                  USBFS_L_CAN1_RX0_IRQHandler
+
+/**
+  * @brief usb endpoint number
+  */
+#define USB_EPT_MAX_NUM                 8
+
+/**
+  * @brief auto malloc usb endpoint buffer
+  */
+#define USB_EPT_AUTO_MALLOC_BUFFER
+
+#ifndef USB_EPT_AUTO_MALLOC_BUFFER
+#define EPT0_TX_ADDR                    0x40
+#define EPT0_RX_ADDR                    0x80
+#define EPT1_TX_ADDR                    0xC0
+#define EPT1_RX_ADDR                    0x100
+#define EPT2_TX_ADDR                    0x140
+#define EPT2_RX_ADDR                    0x180
+#define EPT3_TX_ADDR                    0x00
+#define EPT3_RX_ADDR                    0x00
+#define EPT4_TX_ADDR                    0x00
+#define EPT4_RX_ADDR                    0x00
+#define EPT5_TX_ADDR                    0x00
+#define EPT5_RX_ADDR                    0x00
+#define EPT6_TX_ADDR                    0x00
+#define EPT6_RX_ADDR                    0x00
+#define EPT7_TX_ADDR                    0x00
+#define EPT7_RX_ADDR                    0x00
+#endif
+
+/**
+  * @brief usb low power wakeup handler enable
+  */
+#define USB_LOW_POWER_WAKUP
+
+#if defined(BSP_USING_USBD)
+#define USBD_CONFIG                                                 \
+    {                                                               \
+        .name = "usbd",                                             \
+        .irqn = USBFS_L_CAN1_RX0_IRQn,                              \
+    }
+#endif /* BSP_USING_USBD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 69 - 0
bsp/at32/libraries/rt_drivers/config/f413/usb_config.h

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     leo          first version
+ */
+
+#ifndef __USB_CONFIG_H__
+#define __USB_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* usb irqhandler */
+#define USB_IRQHandler                  USBFS_L_CAN1_RX0_IRQHandler
+
+/**
+  * @brief usb endpoint number
+  */
+#define USB_EPT_MAX_NUM                 8
+
+/**
+  * @brief auto malloc usb endpoint buffer
+  */
+#define USB_EPT_AUTO_MALLOC_BUFFER
+
+#ifndef USB_EPT_AUTO_MALLOC_BUFFER
+#define EPT0_TX_ADDR                    0x40
+#define EPT0_RX_ADDR                    0x80
+#define EPT1_TX_ADDR                    0xC0
+#define EPT1_RX_ADDR                    0x100
+#define EPT2_TX_ADDR                    0x140
+#define EPT2_RX_ADDR                    0x180
+#define EPT3_TX_ADDR                    0x00
+#define EPT3_RX_ADDR                    0x00
+#define EPT4_TX_ADDR                    0x00
+#define EPT4_RX_ADDR                    0x00
+#define EPT5_TX_ADDR                    0x00
+#define EPT5_RX_ADDR                    0x00
+#define EPT6_TX_ADDR                    0x00
+#define EPT6_RX_ADDR                    0x00
+#define EPT7_TX_ADDR                    0x00
+#define EPT7_RX_ADDR                    0x00
+#endif
+
+/**
+  * @brief usb low power wakeup handler enable
+  */
+#define USB_LOW_POWER_WAKUP
+
+#if defined(BSP_USING_USBD)
+#define USBD_CONFIG                                                 \
+    {                                                               \
+        .name = "usbd",                                             \
+        .irqn = USBFS_L_CAN1_RX0_IRQn,                              \
+    }
+#endif /* BSP_USING_USBD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 95 - 0
bsp/at32/libraries/rt_drivers/config/f415/usb_config.h

@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     leo          first version
+ */
+
+#ifndef __USB_CONFIG_H__
+#define __USB_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined BSP_USING_DEVICE_USBFS1
+#define USE_OTG_DEVICE_MODE
+#endif
+
+#if defined BSP_USING_HOST_USBFS1
+#define USE_OTG_HOST_MODE
+#endif
+
+/* usbfs irqhandler */
+#define OTGFS1_IRQHandler               OTGFS1_IRQHandler
+
+/**
+  * @brief usb device mode config
+  */
+#define USB_EPT_MAX_NUM                 4
+
+/* otg1 device fifo */
+#define USBD_RX_SIZE                    128
+#define USBD_EP0_TX_SIZE                24
+#define USBD_EP1_TX_SIZE                20
+#define USBD_EP2_TX_SIZE                20
+#define USBD_EP3_TX_SIZE                20
+#define USBD_EP4_TX_SIZE                20
+#define USBD_EP5_TX_SIZE                20
+#define USBD_EP6_TX_SIZE                20
+#define USBD_EP7_TX_SIZE                20
+
+/**
+  * @brief usb host mode config
+  */
+#define USB_HOST_CHANNEL_NUM            8
+
+/* otg1 host fifo */
+#define USBH_RX_FIFO_SIZE               128
+#define USBH_NP_TX_FIFO_SIZE            96
+#define USBH_P_TX_FIFO_SIZE             96
+
+/**
+  * @brief usb sof output enable
+  */
+// #define USB_SOF_OUTPUT_ENABLE
+
+/**
+  * @brief usb vbus ignore, not use vbus pin
+  */
+#define USB_VBUS_IGNORE
+
+/**
+  * @brief usb low power wakeup handler enable
+  */
+// #define USB_LOW_POWER_WAKUP
+
+#if defined(BSP_USING_HOST_USBFS1)
+#undef BSP_USING_DEVICE_USBFS1
+#define USBFS1_CONFIG                                               \
+    {                                                               \
+        .name = "usbh",                                             \
+        .id = USB_OTG1_ID,                                          \
+        .irqn = OTGFS1_IRQn,                                        \
+    }
+#endif /* BSP_USING_HOST_USBFS1 */
+
+#if defined(BSP_USING_DEVICE_USBFS1)
+#define USBFS1_CONFIG                                               \
+    {                                                               \
+        .name = "usbd",                                             \
+        .id = USB_OTG1_ID,                                          \
+        .irqn = OTGFS1_IRQn,                                        \
+    }
+#endif /* BSP_USING_DEVICE_USBFS1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 95 - 0
bsp/at32/libraries/rt_drivers/config/f425/usb_config.h

@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     leo          first version
+ */
+
+#ifndef __USB_CONFIG_H__
+#define __USB_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined BSP_USING_DEVICE_USBFS1
+#define USE_OTG_DEVICE_MODE
+#endif
+
+#if defined BSP_USING_HOST_USBFS1
+#define USE_OTG_HOST_MODE
+#endif
+
+/* usbfs irqhandler */
+#define OTGFS1_IRQHandler               OTGFS1_IRQHandler
+
+/**
+  * @brief usb device mode config
+  */
+#define USB_EPT_MAX_NUM                 8
+
+/* otg1 device fifo */
+#define USBD_RX_SIZE                    128
+#define USBD_EP0_TX_SIZE                24
+#define USBD_EP1_TX_SIZE                20
+#define USBD_EP2_TX_SIZE                20
+#define USBD_EP3_TX_SIZE                20
+#define USBD_EP4_TX_SIZE                20
+#define USBD_EP5_TX_SIZE                20
+#define USBD_EP6_TX_SIZE                20
+#define USBD_EP7_TX_SIZE                20
+
+/**
+  * @brief usb host mode config
+  */
+#define USB_HOST_CHANNEL_NUM            16
+
+/* otg1 host fifo */
+#define USBH_RX_FIFO_SIZE               128
+#define USBH_NP_TX_FIFO_SIZE            96
+#define USBH_P_TX_FIFO_SIZE             96
+
+/**
+  * @brief usb sof output enable
+  */
+// #define USB_SOF_OUTPUT_ENABLE
+
+/**
+  * @brief usb vbus ignore, not use vbus pin
+  */
+#define USB_VBUS_IGNORE
+
+/**
+  * @brief usb low power wakeup handler enable
+  */
+// #define USB_LOW_POWER_WAKUP
+
+#if defined(BSP_USING_HOST_USBFS1)
+#undef BSP_USING_DEVICE_USBFS1
+#define USBFS1_CONFIG                                               \
+    {                                                               \
+        .name = "usbh",                                             \
+        .id = USB_OTG1_ID,                                          \
+        .irqn = OTGFS1_IRQn,                                        \
+    }
+#endif /* BSP_USING_HOST_USBFS1 */
+
+#if defined(BSP_USING_DEVICE_USBFS1)
+#define USBFS1_CONFIG                                               \
+    {                                                               \
+        .name = "usbd",                                             \
+        .id = USB_OTG1_ID,                                          \
+        .irqn = OTGFS1_IRQn,                                        \
+    }
+#endif /* BSP_USING_DEVICE_USBFS1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 135 - 0
bsp/at32/libraries/rt_drivers/config/f435_437/usb_config.h

@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     leo          first version
+ */
+
+#ifndef __USB_CONFIG_H__
+#define __USB_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined BSP_USING_DEVICE_USBFS1 || defined BSP_USING_DEVICE_USBFS2
+#define USE_OTG_DEVICE_MODE
+#endif
+
+#if defined BSP_USING_HOST_USBFS1 || defined BSP_USING_HOST_USBFS2
+#define USE_OTG_HOST_MODE
+#endif
+
+/* usbfs irqhandler */
+#define OTGFS1_IRQHandler               OTGFS1_IRQHandler
+#define OTGFS2_IRQHandler               OTGFS2_IRQHandler
+
+/**
+  * @brief usb device mode config
+  */
+#define USB_EPT_MAX_NUM                 8
+
+/* otg1 device fifo */
+#define USBD_RX_SIZE                    128
+#define USBD_EP0_TX_SIZE                24
+#define USBD_EP1_TX_SIZE                20
+#define USBD_EP2_TX_SIZE                20
+#define USBD_EP3_TX_SIZE                20
+#define USBD_EP4_TX_SIZE                20
+#define USBD_EP5_TX_SIZE                20
+#define USBD_EP6_TX_SIZE                20
+#define USBD_EP7_TX_SIZE                20
+
+/* otg2 device fifo */
+#define USBD2_RX_SIZE                   128
+#define USBD2_EP0_TX_SIZE               24
+#define USBD2_EP1_TX_SIZE               20
+#define USBD2_EP2_TX_SIZE               20
+#define USBD2_EP3_TX_SIZE               20
+#define USBD2_EP4_TX_SIZE               20
+#define USBD2_EP5_TX_SIZE               20
+#define USBD2_EP6_TX_SIZE               20
+#define USBD2_EP7_TX_SIZE               20
+
+/**
+  * @brief usb host mode config
+  */
+#define USB_HOST_CHANNEL_NUM            16
+
+/* otg1 host fifo */
+#define USBH_RX_FIFO_SIZE               128
+#define USBH_NP_TX_FIFO_SIZE            96
+#define USBH_P_TX_FIFO_SIZE             96
+
+/* otg2 host fifo */
+#define USBH2_RX_FIFO_SIZE              128
+#define USBH2_NP_TX_FIFO_SIZE           96
+#define USBH2_P_TX_FIFO_SIZE            96
+
+/**
+  * @brief usb sof output enable
+  */
+// #define USB_SOF_OUTPUT_ENABLE
+
+/**
+  * @brief usb vbus ignore, not use vbus pin
+  */
+#define USB_VBUS_IGNORE
+
+/**
+  * @brief usb low power wakeup handler enable
+  */
+// #define USB_LOW_POWER_WAKUP
+
+#if defined(BSP_USING_HOST_USBFS1)
+#undef BSP_USING_HOST_USBFS2
+#undef BSP_USING_DEVICE_USBFS1
+#define USBFS1_CONFIG                                               \
+    {                                                               \
+        .name = "usbh1",                                            \
+        .id = USB_OTG1_ID,                                          \
+        .irqn = OTGFS1_IRQn,                                        \
+    }
+#endif /* BSP_USING_HOST_USBFS1 */
+
+#if defined(BSP_USING_DEVICE_USBFS1)
+#undef BSP_USING_DEVICE_USBFS2
+#define USBFS1_CONFIG                                               \
+    {                                                               \
+        .name = "usbd",                                             \
+        .id = USB_OTG1_ID,                                          \
+        .irqn = OTGFS1_IRQn,                                        \
+    }
+#endif /* BSP_USING_DEVICE_USBFS1 */
+
+#if defined(BSP_USING_HOST_USBFS2)
+#undef BSP_USING_HOST_USBFS1
+#undef BSP_USING_DEVICE_USBFS2
+#define USBFS2_CONFIG                                               \
+    {                                                               \
+        .name = "usbh2",                                            \
+        .id = USB_OTG2_ID,                                          \
+        .irqn = OTGFS2_IRQn,                                        \
+    }
+#endif /* BSP_USING_HOST_USBFS2 */
+
+#if defined(BSP_USING_DEVICE_USBFS2)
+#undef BSP_USING_DEVICE_USBFS1
+#define USBFS2_CONFIG                                               \
+    {                                                               \
+        .name = "usbd",                                             \
+        .id = USB_OTG2_ID,                                          \
+        .irqn = OTGFS2_IRQn,                                        \
+    }
+#endif /* BSP_USING_DEVICE_USBFS2 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 6 - 1
bsp/at32/libraries/rt_drivers/drv_config.h

@@ -12,8 +12,8 @@
 #ifndef __DRV_CONFIG_H__
 #define __DRV_CONFIG_H__
 
-#include <board.h>
 #include <rtthread.h>
+#include "drv_common.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -23,14 +23,17 @@ extern "C" {
 #include "f403a_407/dma_config.h"
 #include "f403a_407/uart_config.h"
 #include "f403a_407/spi_config.h"
+#include "f403a_407/usb_config.h"
 #elif defined(SOC_SERIES_AT32F413)
 #include "f413/dma_config.h"
 #include "f413/uart_config.h"
 #include "f413/spi_config.h"
+#include "f413/usb_config.h"
 #elif defined(SOC_SERIES_AT32F415)
 #include "f415/dma_config.h"
 #include "f415/uart_config.h"
 #include "f415/spi_config.h"
+#include "f415/usb_config.h"
 #elif defined(SOC_SERIES_AT32F421)
 #include "f421/dma_config.h"
 #include "f421/uart_config.h"
@@ -39,10 +42,12 @@ extern "C" {
 #include "f425/dma_config.h"
 #include "f425/uart_config.h"
 #include "f425/spi_config.h"
+#include "f425/usb_config.h"
 #elif defined(SOC_SERIES_AT32F435) || defined (SOC_SERIES_AT32F437)
 #include "f435_437/dma_config.h"
 #include "f435_437/uart_config.h"
 #include "f435_437/spi_config.h"
+#include "f435_437/usb_config.h"
 #endif
 
 #ifdef __cplusplus

+ 274 - 0
bsp/at32/libraries/rt_drivers/drv_usbd.c

@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     leo          first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "usbd_int.h"
+#include "drv_common.h"
+#include "drv_usbd.h"
+#include "drv_config.h"
+
+#if defined(BSP_USING_USBD)
+
+static struct at32_usbd *p_usbd_instance = NULL;
+static struct ep_id endpoint_pool[] =
+{
+    {0x0,  USB_EP_ATTR_CONTROL,   USB_DIR_INOUT, 64, ID_ASSIGNED  },
+    {0x1,  USB_EP_ATTR_BULK,      USB_DIR_IN,    64, ID_UNASSIGNED},
+    {0x1,  USB_EP_ATTR_BULK,      USB_DIR_OUT,   64, ID_UNASSIGNED},
+    {0x2,  USB_EP_ATTR_INT,       USB_DIR_IN,    64, ID_UNASSIGNED},
+    {0x2,  USB_EP_ATTR_INT,       USB_DIR_OUT,   64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_ISOC,      USB_DIR_IN,    64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_ISOC,      USB_DIR_OUT,   64, ID_UNASSIGNED},
+    {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK,  0,  ID_ASSIGNED  },
+};
+
+enum
+{
+#ifdef BSP_USING_USBD
+    USBD1_INDEX,
+#endif
+};
+
+static struct at32_usbd usbd_config[] = {
+#ifdef BSP_USING_USBD
+    USBD_CONFIG,
+#endif
+};
+
+void USB_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    usbd_irq_handler(p_usbd_instance->p_usbd_core);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+void usbd_reset_callback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_reset_handler(udcd);
+}
+
+void usbd_connectCallback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_connect_handler(udcd);
+}
+
+void usbd_disconnectCallback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_disconnect_handler(udcd);
+}
+
+void usbd_setup_phase_done_callback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_ep0_setup_handler(udcd, (struct urequest*)udev->setup_buffer);
+}
+
+void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+
+    if (ept_num == 0)
+    {
+        rt_usbd_ep0_in_handler(udcd);
+    }
+    else
+    {
+        rt_usbd_ep_in_handler(udcd, 0x80 | ept_num, udev->ept_in[ept_num].trans_len);
+    }
+}
+
+void usbd_sof_callback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_sof_handler(udcd);
+}
+
+void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+
+    if (ept_num != 0)
+    {
+        rt_usbd_ep_out_handler(udcd, ept_num, udev->ept_out[ept_num].trans_len);
+    }
+    else
+    {
+        rt_usbd_ep0_out_handler(udcd, udev->ept_out[0].trans_len);
+    }
+}
+
+static rt_err_t _ep_set_stall(rt_uint8_t address)
+{
+    usbd_set_stall(p_usbd_instance->p_usbd_core, address);
+    return RT_EOK;
+}
+
+static rt_err_t _ep_clear_stall(rt_uint8_t address)
+{
+    usbd_clear_stall(p_usbd_instance->p_usbd_core, address);
+    return RT_EOK;
+}
+
+static rt_err_t _set_address(rt_uint8_t address)
+{
+    usbd_set_device_addr(p_usbd_instance->p_usbd_core, address);
+    return RT_EOK;
+}
+
+static rt_err_t _set_config(rt_uint8_t address)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _ep_enable(uep_t ep)
+{
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+
+    usbd_ept_open(p_usbd_instance->p_usbd_core, ep->ep_desc->bEndpointAddress, ep->ep_desc->bmAttributes, ep->ep_desc->wMaxPacketSize);
+    return RT_EOK;
+}
+
+static rt_err_t _ep_disable(uep_t ep)
+{
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+    usbd_ept_close(p_usbd_instance->p_usbd_core, ep->ep_desc->bEndpointAddress);
+    return RT_EOK;
+}
+
+static rt_size_t _ep_read(rt_uint8_t address, void *buffer)
+{
+    rt_size_t size = 0;
+    RT_ASSERT(buffer != RT_NULL);
+    return size;
+}
+
+static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    usbd_ept_recv(p_usbd_instance->p_usbd_core, address, buffer, size);
+    return size;
+}
+
+static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    usbd_ept_send(p_usbd_instance->p_usbd_core, address, buffer, size);
+    return size;
+}
+
+static rt_err_t _ep0_send_status(void)
+{
+    usbd_ctrl_send_status(p_usbd_instance->p_usbd_core);
+    return RT_EOK;
+}
+
+static rt_err_t _suspend(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _wakeup(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t at32_dcd_init(rt_device_t device)
+{
+    /* usb gpio config */
+    at32_msp_usb_init(device);
+
+    /* enable usb interrupt */
+    nvic_irq_enable(p_usbd_instance->irqn, 2, 0);
+
+    /* usb core init */
+    usbd_core_init(p_usbd_instance->p_usbd_core, USB, 0);
+
+    /* enable usb pull-up */
+    usbd_connect(p_usbd_instance->p_usbd_core);
+
+    return RT_EOK;
+}
+
+const static struct udcd_ops _udc_ops =
+{
+    _set_address,
+    _set_config,
+    _ep_set_stall,
+    _ep_clear_stall,
+    _ep_enable,
+    _ep_disable,
+    _ep_read_prepare,
+    _ep_read,
+    _ep_write,
+    _ep0_send_status,
+    _suspend,
+    _wakeup,
+};
+
+int at32_usbd_register(void)
+{
+    rt_size_t obj_num;
+    rt_err_t result = 0;
+    int index;
+
+    obj_num = sizeof(usbd_config) / sizeof(struct at32_usbd);
+
+    for (index = 0; index < obj_num; index++) {
+        udcd_t udcd = (udcd_t)rt_malloc(sizeof(struct udcd));
+        if (udcd == RT_NULL)
+        {
+            rt_kprintf("udcd malloc failed\r\n");
+            return -RT_ERROR;
+        }
+        rt_memset((void *)udcd, 0, sizeof(struct udcd));
+
+        usbd_core_type *p_usbd_core = (usbd_core_type *)rt_malloc(sizeof(usbd_core_type));
+        if (p_usbd_core == RT_NULL)
+        {
+            rt_kprintf("usbd_core malloc failed\r\n");
+            return -RT_ERROR;
+        }
+        rt_memset((void *)p_usbd_core, 0, sizeof(usbd_core_type));
+
+        udcd->parent.type = RT_Device_Class_USBDevice;
+        udcd->parent.init = at32_dcd_init;
+
+        udcd->parent.user_data = p_usbd_core;
+        udcd->ops = &_udc_ops;
+        p_usbd_core->pdata = udcd;
+        usbd_config[index].p_usbd_core = p_usbd_core;
+
+        /* register endpoint infomation */
+        udcd->ep_pool = endpoint_pool;
+        udcd->ep0.id = &endpoint_pool[0];
+
+        result = rt_device_register((rt_device_t)udcd, usbd_config[index].name, 0);
+        RT_ASSERT(result == RT_EOK);
+
+        p_usbd_instance = &usbd_config[index];
+
+        result = rt_usb_device_init();
+        RT_ASSERT(result == RT_EOK);
+    }
+
+    return result;
+}
+
+INIT_DEVICE_EXPORT(at32_usbd_register);
+
+#endif

+ 27 - 0
bsp/at32/libraries/rt_drivers/drv_usbd.h

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     shelton      first version
+ */
+
+#ifndef __DRV_USBD_H__
+#define __DRV_USBD_H__
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "drv_common.h"
+#include "usbd_core.h"
+
+struct at32_usbd {
+    char *name;
+    usbd_core_type *p_usbd_core;
+    IRQn_Type irqn;
+};
+
+#endif /* __DRV_USBD_H__ */
+
+/******************* end of file *******************/

+ 28 - 0
bsp/at32/libraries/rt_drivers/drv_usbfs.h

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     shelton      first version
+ */
+
+#ifndef __DRV_USBFS_H__
+#define __DRV_USBFS_H__
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "drv_common.h"
+#include "usb_core.h"
+
+struct at32_usbfs {
+    char *name;
+    otg_core_type *p_otg_core;
+    otg_id_type id;
+    IRQn_Type irqn;
+};
+
+#endif /* __DRV_USBFS_H__ */
+
+/******************* end of file *******************/

+ 311 - 0
bsp/at32/libraries/rt_drivers/drv_usbfsd.c

@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     leo          first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "usbd_int.h"
+#include "drv_common.h"
+#include "drv_usbfs.h"
+#include "drv_config.h"
+
+#if defined(BSP_USING_DEVICE_USBFS1) || defined(BSP_USING_DEVICE_USBFS2)
+
+static struct at32_usbfs *p_usbfs_instance = NULL;
+static struct ep_id endpoint_pool[] =
+{
+    {0x0,  USB_EP_ATTR_CONTROL,   USB_DIR_INOUT, 64, ID_ASSIGNED  },
+    {0x1,  USB_EP_ATTR_BULK,      USB_DIR_IN,    64, ID_UNASSIGNED},
+    {0x1,  USB_EP_ATTR_BULK,      USB_DIR_OUT,   64, ID_UNASSIGNED},
+    {0x2,  USB_EP_ATTR_INT,       USB_DIR_IN,    64, ID_UNASSIGNED},
+    {0x2,  USB_EP_ATTR_INT,       USB_DIR_OUT,   64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_ISOC,      USB_DIR_IN,    64, ID_UNASSIGNED},
+    {0x3,  USB_EP_ATTR_ISOC,      USB_DIR_OUT,   64, ID_UNASSIGNED},
+    {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK,  0,  ID_ASSIGNED  },
+};
+
+enum
+{
+#ifdef BSP_USING_DEVICE_USBFS1
+    USBFS1_INDEX,
+#endif
+#ifdef BSP_USING_DEVICE_USBFS2
+    USBFS2_INDEX,
+#endif
+};
+
+static struct at32_usbfs usbfsd_config[] = {
+#ifdef BSP_USING_DEVICE_USBFS1
+    USBFS1_CONFIG,
+#endif
+#ifdef BSP_USING_DEVICE_USBFS2
+    USBFS2_CONFIG,
+#endif
+};
+
+#ifdef BSP_USING_DEVICE_USBFS1
+void OTGFS1_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    usbd_irq_handler(p_usbfs_instance->p_otg_core);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_DEVICE_USBFS2
+void OTGFS2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    usbd_irq_handler(p_usbfs_instance->p_otg_core);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+
+void usbd_reset_callback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_reset_handler(udcd);
+}
+
+void usbd_connectCallback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_connect_handler(udcd);
+}
+
+void usbd_disconnectCallback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_disconnect_handler(udcd);
+}
+
+void usbd_setup_phase_done_callback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_ep0_setup_handler(udcd, (struct urequest*)udev->setup_buffer);
+}
+
+void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+
+    if (ept_num == 0)
+    {
+        rt_usbd_ep0_in_handler(udcd);
+    }
+    else
+    {
+        rt_usbd_ep_in_handler(udcd, 0x80 | ept_num, udev->ept_in[ept_num].trans_len);
+    }
+}
+
+void usbd_sof_callback(usbd_core_type *udev)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+    rt_usbd_sof_handler(udcd);
+}
+
+void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+    udcd_t udcd = (udcd_t)udev->pdata;
+
+    if (ept_num != 0)
+    {
+        rt_usbd_ep_out_handler(udcd, ept_num, udev->ept_out[ept_num].trans_len);
+    }
+    else
+    {
+        rt_usbd_ep0_out_handler(udcd, udev->ept_out[0].trans_len);
+    }
+}
+
+static rt_err_t _ep_set_stall(rt_uint8_t address)
+{
+    usbd_set_stall(&p_usbfs_instance->p_otg_core->dev, address);
+    return RT_EOK;
+}
+
+static rt_err_t _ep_clear_stall(rt_uint8_t address)
+{
+    usbd_clear_stall(&p_usbfs_instance->p_otg_core->dev, address);
+    return RT_EOK;
+}
+
+static rt_err_t _set_address(rt_uint8_t address)
+{
+    usbd_set_device_addr(&p_usbfs_instance->p_otg_core->dev, address);
+    return RT_EOK;
+}
+
+static rt_err_t _set_config(rt_uint8_t address)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _ep_enable(uep_t ep)
+{
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+
+    usbd_ept_open(&p_usbfs_instance->p_otg_core->dev, ep->ep_desc->bEndpointAddress, \
+                  ep->ep_desc->bmAttributes, ep->ep_desc->wMaxPacketSize);
+    return RT_EOK;
+}
+
+static rt_err_t _ep_disable(uep_t ep)
+{
+    RT_ASSERT(ep != RT_NULL);
+    RT_ASSERT(ep->ep_desc != RT_NULL);
+
+    usbd_ept_close(&p_usbfs_instance->p_otg_core->dev, ep->ep_desc->bEndpointAddress);
+    return RT_EOK;
+}
+
+static rt_size_t _ep_read(rt_uint8_t address, void *buffer)
+{
+    rt_size_t size = 0;
+    RT_ASSERT(buffer != RT_NULL);
+    return size;
+}
+
+static rt_size_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    usbd_ept_recv(&p_usbfs_instance->p_otg_core->dev, address, buffer, size);
+    return size;
+}
+
+static rt_size_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
+{
+    usbd_ept_send(&p_usbfs_instance->p_otg_core->dev, address, buffer, size);
+    return size;
+}
+
+static rt_err_t _ep0_send_status(void)
+{
+    usbd_ept_send(&p_usbfs_instance->p_otg_core->dev, 0x00, NULL, 0);
+    return RT_EOK;
+}
+
+static rt_err_t _suspend(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t _wakeup(void)
+{
+    return RT_EOK;
+}
+
+static rt_err_t at32_dcd_init(rt_device_t device)
+{
+    /* usb gpio config */
+    at32_msp_usb_init(device);
+
+    /* enable otgfs irq */
+    nvic_irq_enable(p_usbfs_instance->irqn, 2, 0);
+
+    /* init usb */
+    p_usbfs_instance->p_otg_core->usb_reg = usb_global_select_core(p_usbfs_instance->id);
+
+    /* usb device core config */
+    usb_core_config(p_usbfs_instance->p_otg_core, USB_FULL_SPEED_CORE_ID);
+
+    if(p_usbfs_instance->p_otg_core->cfg.sof_out)
+    {
+      p_usbfs_instance->p_otg_core->usb_reg->gccfg_bit.sofouten = TRUE;
+    }
+
+    if(p_usbfs_instance->p_otg_core->cfg.vbusig)
+    {
+      p_usbfs_instance->p_otg_core->usb_reg->gccfg_bit.vbusig = TRUE;
+    }
+
+    /* usb device core init */
+    usbd_core_init(&(p_usbfs_instance->p_otg_core->dev), p_usbfs_instance->p_otg_core->usb_reg,
+                   USB_FULL_SPEED_CORE_ID);
+
+    return RT_EOK;
+}
+
+const static struct udcd_ops _udc_ops =
+{
+    _set_address,
+    _set_config,
+    _ep_set_stall,
+    _ep_clear_stall,
+    _ep_enable,
+    _ep_disable,
+    _ep_read_prepare,
+    _ep_read,
+    _ep_write,
+    _ep0_send_status,
+    _suspend,
+    _wakeup,
+};
+
+int at32_usbd_register(void)
+{
+    rt_size_t obj_num;
+    rt_err_t result = 0;
+    int index;
+
+    obj_num = sizeof(usbfsd_config) / sizeof(struct at32_usbfs);
+
+    for (index = 0; index < obj_num; index++) {
+        udcd_t udcd = (udcd_t)rt_malloc(sizeof(struct udcd));
+        if (udcd == RT_NULL)
+        {
+            rt_kprintf("uhcd malloc failed\r\n");
+            return -RT_ERROR;
+        }
+        rt_memset((void *)udcd, 0, sizeof(struct udcd));
+
+        otg_core_type *p_otg_core = (otg_core_type *)rt_malloc(sizeof(otg_core_type));
+        if (p_otg_core == RT_NULL)
+        {
+            rt_kprintf("otg_core malloc failed\r\n");
+            return -RT_ERROR;
+        }
+        rt_memset((void *)p_otg_core, 0, sizeof(otg_core_type));
+
+        udcd->parent.type = RT_Device_Class_USBDevice;
+        udcd->parent.init = at32_dcd_init;
+
+        udcd->parent.user_data = &(p_otg_core->dev);
+        udcd->ops = &_udc_ops;
+        p_otg_core->dev.pdata = udcd;
+        usbfsd_config[index].p_otg_core = p_otg_core;
+
+        /* register endpoint infomation */
+        udcd->ep_pool = endpoint_pool;
+        udcd->ep0.id = &endpoint_pool[0];
+
+        result = rt_device_register((rt_device_t)udcd, usbfsd_config[index].name, 0);
+        RT_ASSERT(result == RT_EOK);
+
+        p_usbfs_instance = &usbfsd_config[index];
+
+        result = rt_usb_device_init();
+        RT_ASSERT(result == RT_EOK);
+    }
+
+    return result;
+}
+
+INIT_DEVICE_EXPORT(at32_usbd_register);
+
+#endif

+ 406 - 0
bsp/at32/libraries/rt_drivers/drv_usbfsh.c

@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-28     leo          first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include "usbh_int.h"
+#include "drv_common.h"
+#include "drv_usbfs.h"
+#include "drv_config.h"
+
+#if defined(BSP_USING_HOST_USBFS1) || defined(BSP_USING_HOST_USBFS2)
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.usb"
+#include <drv_log.h>
+
+static struct rt_completion urb_completion;
+static volatile rt_bool_t connect_status = RT_FALSE;
+static struct at32_usbfs *p_usbfs_instance = NULL;
+
+enum
+{
+#ifdef BSP_USING_HOST_USBFS1
+    USBFS1_INDEX,
+#endif
+#ifdef BSP_USING_HOST_USBFS2
+    USBFS2_INDEX,
+#endif
+};
+
+static struct at32_usbfs usbfsh_config[] = {
+#ifdef BSP_USING_HOST_USBFS1
+    USBFS1_CONFIG,
+#endif
+#ifdef BSP_USING_HOST_USBFS2
+    USBFS2_CONFIG,
+#endif
+};
+
+#ifdef BSP_USING_HOST_USBFS1
+void OTGFS1_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    usbh_irq_handler(p_usbfs_instance->p_otg_core);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_HOST_USBFS2
+void OTGFS2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    usbh_irq_handler(p_usbfs_instance->p_otg_core);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+
+void usbh_connect_callback(usbh_core_type *uhost)
+{
+    uhcd_t hcd = (uhcd_t)uhost->pdata;
+    if (!connect_status)
+    {
+        connect_status = RT_TRUE;
+        RT_DEBUG_LOG(RT_DEBUG_USB, ("usb connected\n"));
+        rt_usbh_root_hub_connect_handler(hcd, 1, RT_FALSE);
+    }
+}
+
+void usbh_disconnect_callback(usbh_core_type *uhost)
+{
+    uhcd_t hcd = (uhcd_t)uhost->pdata;
+    if (connect_status)
+    {
+        connect_status = RT_FALSE;
+        RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnnect\n"));
+        rt_usbh_root_hub_disconnect_handler(hcd, 1);
+    }
+}
+
+void usbd_notify_urbchange_callback(usbh_core_type *uhost, uint8_t chnum, urb_sts_type sts)
+{
+    rt_completion_done(&urb_completion);
+}
+
+static rt_err_t drv_reset_port(rt_uint8_t port)
+{
+    RT_DEBUG_LOG(RT_DEBUG_USB, ("reset port\n"));
+    usbh_reset_port(&p_usbfs_instance->p_otg_core->host);
+    return RT_EOK;
+}
+
+static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
+{
+    int timeout = timeouts;
+
+    while(1)
+    {
+        if(!connect_status)
+        {
+            return -1;
+        }
+        rt_completion_init(&urb_completion);
+
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].dir = (pipe->ep.bEndpointAddress & 0x80) >> 7;
+
+        if(token == 0U)
+        {
+            p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_SETUP;
+        }
+        else
+        {
+            p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1;
+        }
+
+        /* endpoint type */
+        switch(pipe->ep.bmAttributes)
+        {
+            /* endpoint is control type */
+            case EPT_CONTROL_TYPE:
+                if((token == 1U) && (((pipe->ep.bEndpointAddress & 0x80) >> 7) == 0U))
+                {
+                    if(nbytes == 0U)
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_out = 1U;
+                    }
+                    if((&p_usbfs_instance->p_otg_core->host)->hch[pipe->pipe_index].toggle_out == 0U)
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0;
+                    }
+                    else
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1;
+                    }
+                }
+                break;
+            /* endpoint is bulk type */
+            case EPT_BULK_TYPE:
+                if(((pipe->ep.bEndpointAddress & 0x80) >> 7) == 0U)
+                {
+                    if( p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_out == 0U)
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0;
+                    }
+                    else
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1;
+                    }
+                }
+                else
+                {
+                    if( p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_in == 0U)
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0;
+                    }
+                    else
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1;
+                    }
+                }
+                break;
+            /* endpoint is int type */
+            case  EPT_INT_TYPE:
+                if(((pipe->ep.bEndpointAddress & 0x80) >> 7) == 0U)
+                {
+                    if( p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_out == 0U)
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0;
+                    }
+                    else
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1;
+                    }
+                }
+                else
+                {
+                    if( p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_in == 0U)
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0;
+                    }
+                    else
+                    {
+                        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA1;
+                    }
+                }
+                break;
+            /* endpoint is isoc type */
+            case EPT_ISO_TYPE:
+                p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].data_pid = HCH_PID_DATA0;
+                break;
+
+            default:
+                break;
+        }
+
+        /* set transfer buffer */
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].trans_buf = buffer;
+        /* set transfer len*/
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].trans_len = nbytes;
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].urb_sts = URB_IDLE;
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].ch_num = pipe->pipe_index;
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].trans_count = 0;
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].state = HCH_IDLE;
+
+        /* data in/out for host */
+        usbh_in_out_request((&p_usbfs_instance->p_otg_core->host), pipe->pipe_index);
+
+        rt_completion_wait(&urb_completion, timeout);
+        rt_thread_mdelay(1);
+
+        if(usbh_get_status((&p_usbfs_instance->p_otg_core->host), pipe->pipe_index) == HCH_NAK)
+        {
+            RT_DEBUG_LOG(RT_DEBUG_USB, ("nak\n"));
+            if (pipe->ep.bmAttributes == USB_EP_ATTR_INT)
+            {
+                rt_thread_delay((pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) > 0 ? (pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) : 1);
+            }
+            usb_hch_halt((&p_usbfs_instance->p_otg_core->host)->usb_reg, pipe->pipe_index);
+
+            usbh_hc_open(&p_usbfs_instance->p_otg_core->host,
+                         pipe->pipe_index,
+                         pipe->ep.bEndpointAddress,
+                         pipe->inst->address,
+                         pipe->ep.bmAttributes,
+                         pipe->ep.wMaxPacketSize,
+                         USB_PRTSPD_FULL_SPEED);
+            continue;
+        }
+        else if (usbh_get_status(&p_usbfs_instance->p_otg_core->host, pipe->pipe_index) == HCH_STALL)
+        {
+            RT_DEBUG_LOG(RT_DEBUG_USB, ("stall\n"));
+            pipe->status = UPIPE_STATUS_STALL;
+            if (pipe->callback != RT_NULL)
+            {
+                pipe->callback(pipe);
+            }
+            return -1;
+        }
+        else if (usbh_get_status(&p_usbfs_instance->p_otg_core->host, pipe->pipe_index) == URB_ERROR)
+        {
+            RT_DEBUG_LOG(RT_DEBUG_USB, ("error\n"));
+            pipe->status = UPIPE_STATUS_ERROR;
+            if (pipe->callback != RT_NULL)
+            {
+                pipe->callback(pipe);
+            }
+            return -1;
+        }
+        else if(URB_DONE == usbh_get_urb_status(&p_usbfs_instance->p_otg_core->host, pipe->pipe_index))
+        {
+            RT_DEBUG_LOG(RT_DEBUG_USB, ("ok\n"));
+            pipe->status = UPIPE_STATUS_OK;
+            if (pipe->callback != RT_NULL)
+            {
+                pipe->callback(pipe);
+            }
+            size_t size = (&p_usbfs_instance->p_otg_core->host)->hch[pipe->pipe_index].trans_count;
+            if (pipe->ep.bEndpointAddress & 0x80)
+            {
+                return size;
+            }
+            else if (pipe->ep.bEndpointAddress & 0x00)
+            {
+                return size;
+            }
+            return nbytes;
+        }
+        continue;
+    }
+}
+
+static rt_uint16_t pipe_index = 0;
+static rt_uint8_t  drv_get_free_pipe_index(void)
+{
+    rt_uint8_t idx;
+    for (idx = 1; idx < 16; idx++)
+    {
+        if (!(pipe_index & (0x01 << idx)))
+        {
+            pipe_index |= (0x01 << idx);
+            return idx;
+        }
+    }
+    return 0xff;
+}
+
+static void drv_free_pipe_index(rt_uint8_t index)
+{
+    pipe_index &= ~(0x01 << index);
+}
+
+static rt_err_t drv_open_pipe(upipe_t pipe)
+{
+    pipe->pipe_index = drv_get_free_pipe_index();
+    usbh_hc_open(&p_usbfs_instance->p_otg_core->host,
+                 pipe->pipe_index,
+                 pipe->ep.bEndpointAddress,
+                 pipe->inst->address,
+                 pipe->ep.bmAttributes,
+                 pipe->ep.wMaxPacketSize,
+                 USB_PRTSPD_FULL_SPEED);
+    /* set data0 pid token*/
+    if (p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].dir)
+    {
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_in = 0;
+    }
+    else
+    {
+        p_usbfs_instance->p_otg_core->host.hch[pipe->pipe_index].toggle_out = 0;
+    }
+    return RT_EOK;
+}
+
+static rt_err_t drv_close_pipe(upipe_t pipe)
+{
+    usb_hch_halt((&p_usbfs_instance->p_otg_core->host)->usb_reg, pipe->pipe_index);
+    drv_free_pipe_index(pipe->pipe_index);
+    return RT_EOK;
+}
+
+static struct uhcd_ops _uhcd_ops =
+{
+    drv_reset_port,
+    drv_pipe_xfer,
+    drv_open_pipe,
+    drv_close_pipe,
+};
+
+static rt_err_t at32_hcd_init(rt_device_t device)
+{
+    /* usb gpio config */
+    at32_msp_usb_init(device);
+
+    /* enable otgfs irq */
+    nvic_irq_enable(p_usbfs_instance->irqn, 2, 0);
+
+    /* init usb */
+    usbh_init(p_usbfs_instance->p_otg_core,
+              USB_FULL_SPEED_CORE_ID,
+              p_usbfs_instance->id);
+    return RT_EOK;
+}
+
+int at32_usbh_register(void)
+{
+    rt_size_t obj_num;
+    rt_err_t result = 0;
+    int index;
+
+    obj_num = sizeof(usbfsh_config) / sizeof(struct at32_usbfs);
+
+    for (index = 0; index < obj_num; index++) {
+        uhcd_t uhcd = (uhcd_t)rt_malloc(sizeof(struct uhcd));
+        if (uhcd == RT_NULL)
+        {
+            rt_kprintf("uhcd malloc failed\r\n");
+            return -RT_ERROR;
+        }
+        rt_memset((void *)uhcd, 0, sizeof(struct uhcd));
+
+        otg_core_type *p_otg_core = (otg_core_type *)rt_malloc(sizeof(otg_core_type));
+        if (p_otg_core == RT_NULL)
+        {
+            rt_kprintf("otg_core malloc failed\r\n");
+            return -RT_ERROR;
+        }
+        rt_memset((void *)p_otg_core, 0, sizeof(otg_core_type));
+
+        uhcd->parent.type = RT_Device_Class_USBHost;
+        uhcd->parent.init = at32_hcd_init;
+        uhcd->parent.user_data = &(p_otg_core->host);
+
+        uhcd->ops = &_uhcd_ops;
+        uhcd->num_ports = 1;
+        p_otg_core->host.pdata = uhcd;
+        usbfsh_config[index].p_otg_core = p_otg_core;
+
+        result = rt_device_register(&uhcd->parent, usbfsh_config[index].name, RT_DEVICE_FLAG_DEACTIVATE);
+        RT_ASSERT(result == RT_EOK);
+
+        p_usbfs_instance = &usbfsh_config[index];
+
+        result = rt_usb_host_init(usbfsh_config[index].name);
+        RT_ASSERT(result == RT_EOK);
+    }
+
+    return result;
+}
+
+INIT_DEVICE_EXPORT(at32_usbh_register);
+
+#endif

+ 19 - 0
bsp/at32/libraries/usbd_library/SConscript

@@ -0,0 +1,19 @@
+import rtconfig
+from building import *
+
+# get current directory
+cwd = GetCurrentDir()
+
+# add the general drivers.
+src = Split("""
+""")
+
+# The set of source files associated with this SConscript file.
+if GetDepend('RT_USING_USB_DEVICE'):
+	src += ['src/usbd_core.c', 'src/usbd_int.c', 'src/usbd_sdr.c']
+
+CPPPATH = [cwd + '/inc']
+
+group = DefineGroup('usbd_library', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 376 - 0
bsp/at32/libraries/usbd_library/inc/usb_std.h

@@ -0,0 +1,376 @@
+/**
+  **************************************************************************
+  * @file     usb_std.h
+  * @brief    usb standard header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_STD_H
+#define __USB_STD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes ------------------------------------------------------------------*/
+#include "drv_config.h"
+
+/** @addtogroup USB_standard
+  * @{
+  */
+
+/** @defgroup USB_standard_define
+  * @{
+  */
+
+/**
+  * @brief usb request recipient
+  */
+#define USB_REQ_RECIPIENT_DEVICE         0x00 /*!< usb request recipient device */
+#define USB_REQ_RECIPIENT_INTERFACE      0x01 /*!< usb request recipient interface */
+#define USB_REQ_RECIPIENT_ENDPOINT       0x02 /*!< usb request recipient endpoint */
+#define USB_REQ_RECIPIENT_OTHER          0x03 /*!< usb request recipient other */
+#define USB_REQ_RECIPIENT_MASK           0x1F /*!< usb request recipient mask */
+
+/**
+  * @brief usb request type
+  */
+#define USB_REQ_TYPE_STANDARD            0x00 /*!< usb request type standard */
+#define USB_REQ_TYPE_CLASS               0x20 /*!< usb request type class */
+#define USB_REQ_TYPE_VENDOR              0x40 /*!< usb request type vendor */
+#define USB_REQ_TYPE_RESERVED            0x60 /*!< usb request type reserved */
+
+/**
+  * @brief usb request data transfer direction
+  */
+#define USB_REQ_DIR_HTD                  0x00 /*!< usb request data transfer direction host to device */
+#define USB_REQ_DIR_DTH                  0x80 /*!< usb request data transfer direction device to host */
+
+/**
+  * @brief usb standard device requests codes
+  */
+#define USB_STD_REQ_GET_STATUS           0 /*!< usb request code status */
+#define USB_STD_REQ_CLEAR_FEATURE        1 /*!< usb request code clear feature */
+#define USB_STD_REQ_SET_FEATURE          3 /*!< usb request code feature */
+#define USB_STD_REQ_SET_ADDRESS          5 /*!< usb request code address */
+#define USB_STD_REQ_GET_DESCRIPTOR       6 /*!< usb request code get descriptor */
+#define USB_STD_REQ_SET_DESCRIPTOR       7 /*!< usb request code set descriptor */
+#define USB_STD_REQ_GET_CONFIGURATION    8 /*!< usb request code get configuration */
+#define USB_STD_REQ_SET_CONFIGURATION    9 /*!< usb request code set configuration */
+#define USB_STD_REQ_GET_INTERFACE        10 /*!< usb request code get interface */
+#define USB_STD_REQ_SET_INTERFACE        11 /*!< usb request code set interface */
+#define USB_STD_REQ_SYNCH_FRAME          12 /*!< usb request code synch frame */
+
+/**
+  * @brief usb standard device type
+  */
+#define USB_DESCIPTOR_TYPE_DEVICE        1 /*!< usb standard device type device */
+#define USB_DESCIPTOR_TYPE_CONFIGURATION 2 /*!< usb standard device type configuration */
+#define USB_DESCIPTOR_TYPE_STRING        3 /*!< usb standard device type string */
+#define USB_DESCIPTOR_TYPE_INTERFACE     4 /*!< usb standard device type interface */
+#define USB_DESCIPTOR_TYPE_ENDPOINT      5 /*!< usb standard device type endpoint */
+#define USB_DESCIPTOR_TYPE_DEVICE_QUALIFIER     6 /*!< usb standard device type qualifier */
+#define USB_DESCIPTOR_TYPE_OTHER_SPEED   7 /*!< usb standard device type other speed */
+#define USB_DESCIPTOR_TYPE_INTERFACE_POWER       8 /*!< usb standard device type interface power */
+
+/**
+  * @brief usb standard string type
+  */
+#define  USB_LANGID_STRING               0 /*!< usb standard string type lang id */
+#define  USB_MFC_STRING                  1 /*!< usb standard string type mfc */
+#define  USB_PRODUCT_STRING              2 /*!< usb standard string type product */
+#define  USB_SERIAL_STRING               3 /*!< usb standard string type serial */
+#define  USB_CONFIG_STRING               4 /*!< usb standard string type config */
+#define  USB_INTERFACE_STRING            5 /*!< usb standard string type interface */
+
+/**
+  * @brief usb configuration attributes
+  */
+#define USB_CONF_REMOTE_WAKEUP           2 /*!< usb configuration attributes remote wakeup */
+#define USB_CONF_SELF_POWERED            1 /*!< usb configuration attributes self powered */
+
+/**
+  * @brief usb standard feature selectors
+  */
+#define USB_FEATURE_EPT_HALT             0 /*!< usb standard feature selectors endpoint halt */
+#define USB_FEATURE_REMOTE_WAKEUP        1 /*!< usb standard feature selectors remote wakeup */
+//#define USB_FEATURE_TEST_MODE            2 /*!< usb standard feature selectors test mode */
+
+/**
+  * @brief usb device connect state
+  */
+typedef enum
+{
+  USB_CONN_STATE_DEFAULT                =1, /*!< usb device connect state default */
+  USB_CONN_STATE_ADDRESSED,                 /*!< usb device connect state address */
+  USB_CONN_STATE_CONFIGURED,                /*!< usb device connect state configured */
+  USB_CONN_STATE_SUSPENDED                  /*!< usb device connect state suspend */
+}usbd_conn_state;
+
+/**
+  * @brief endpoint 0 state
+  */
+#define USB_EPT0_IDLE                    0 /*!< usb endpoint state idle */
+#define USB_EPT0_SETUP                   1 /*!< usb endpoint state setup */
+#define USB_EPT0_DATA_IN                 2 /*!< usb endpoint state data in */
+#define USB_EPT0_DATA_OUT                3 /*!< usb endpoint state data out */
+#define USB_EPT0_STATUS_IN               4 /*!< usb endpoint state status in */
+#define USB_EPT0_STATUS_OUT              5 /*!< usb endpoint state status out */
+#define USB_EPT0_STALL                   6 /*!< usb endpoint state stall */
+
+/**
+  * @brief usb descriptor length
+  */
+#define USB_DEVICE_QUALIFIER_DESC_LEN    0x0A /*!< usb qualifier descriptor length */
+#define USB_DEVICE_DESC_LEN              0x12 /*!< usb device descriptor length */
+#define USB_DEVICE_CFG_DESC_LEN          0x09 /*!< usb configuration descriptor length */
+#define USB_DEVICE_IF_DESC_LEN           0x09 /*!< usb interface descriptor length */
+#define USB_DEVICE_EPT_LEN               0x07 /*!< usb endpoint descriptor length */
+#define USB_DEVICE_OTG_DESC_LEN          0x03 /*!< usb otg descriptor length */
+#define USB_DEVICE_LANGID_STR_DESC_LEN   0x04 /*!< usb lang id string descriptor length */
+#define USB_DEVICE_OTHER_SPEED_DESC_SIZ_LEN 0x09 /*!< usb other speed descriptor length */
+
+/**
+  * @brief usb class code
+  */
+#define USB_CLASS_CODE_AUDIO             0x01 /*!< usb class code audio */
+#define USB_CLASS_CODE_CDC               0x02 /*!< usb class code cdc */
+#define USB_CLASS_CODE_HID               0x03 /*!< usb class code hid */
+#define USB_CLASS_CODE_PRINTER           0x07 /*!< usb class code printer */
+#define USB_CLASS_CODE_MSC               0x08 /*!< usb class code msc */
+#define USB_CLASS_CODE_HUB               0x09 /*!< usb class code hub */
+#define USB_CLASS_CODE_CDCDATA           0x0A /*!< usb class code cdc data */
+#define USB_CLASS_CODE_CCID              0x0B /*!< usb class code ccid */
+#define USB_CLASS_CODE_VIDEO             0x0E /*!< usb class code video */
+#define USB_CLASS_CODE_VENDOR            0xFF /*!< usb class code vendor */
+
+/**
+  * @brief usb endpoint type
+  */
+#define USB_EPT_DESC_CONTROL             0x00 /*!< usb endpoint description type control */
+#define USB_EPT_DESC_ISO                 0x01 /*!< usb endpoint description type iso */
+#define USB_EPT_DESC_BULK                0x02 /*!< usb endpoint description type bulk */
+#define USB_EPT_DESC_INTERRUPT           0x03 /*!< usb endpoint description type interrupt */
+
+#define USB_EPT_DESC_NSYNC               0x00 /*!< usb endpoint description nsync */
+#define USB_ETP_DESC_ASYNC               0x04 /*!< usb endpoint description async */
+#define USB_ETP_DESC_ADAPTIVE            0x08 /*!< usb endpoint description adaptive */
+#define USB_ETP_DESC_SYNC                0x0C /*!< usb endpoint description sync */
+
+#define USB_EPT_DESC_DATA_EPT            0x00 /*!< usb endpoint description data */
+#define USB_EPT_DESC_FD_EPT              0x10 /*!< usb endpoint description fd */
+#define USB_EPT_DESC_FDDATA_EPT          0x20 /*!< usb endpoint description fddata */
+
+/**
+  * @brief usb cdc class descriptor define
+  */
+#define USBD_CDC_CS_INTERFACE             0x24
+#define USBD_CDC_CS_ENDPOINT              0x25
+
+/**
+  * @brief usb cdc class sub-type define
+  */
+#define USBD_CDC_SUBTYPE_HEADER           0x00
+#define USBD_CDC_SUBTYPE_CMF              0x01
+#define USBD_CDC_SUBTYPE_ACM              0x02
+#define USBD_CDC_SUBTYPE_UFD              0x06
+
+/**
+  * @brief usb cdc class request code define
+  */
+#define SET_LINE_CODING                   0x20
+#define GET_LINE_CODING                   0x21
+
+/**
+  * @brief usb cdc class set line coding struct
+  */
+typedef struct
+{
+  uint32_t bitrate;                      /* line coding baud rate */
+  uint8_t format;                        /* line coding foramt */
+  uint8_t parity;                        /* line coding parity */
+  uint8_t data;                          /* line coding data bit */
+}linecoding_type;
+
+/**
+  * @brief usb hid class descriptor define
+  */
+#define HID_CLASS_DESC_HID               0x21
+#define HID_CLASS_DESC_REPORT            0x22
+#define HID_CLASS_DESC_PHYSICAL          0x23
+
+/**
+  * @brief usb hid class request code define
+  */
+#define HID_REQ_SET_PROTOCOL             0x0B
+#define HID_REQ_GET_PROTOCOL             0x03
+#define HID_REQ_SET_IDLE                 0x0A
+#define HID_REQ_GET_IDLE                 0x02
+#define HID_REQ_SET_REPORT               0x09
+#define HID_REQ_GET_REPORT               0x01
+#define HID_DESCRIPTOR_TYPE              0x21
+#define HID_REPORT_DESC                  0x22
+
+/**
+  * @brief endpoint 0 max size
+  */
+#define USB_MAX_EP0_SIZE                 64 /*!< usb endpoint 0 max size */
+
+/**
+  * @brief usb swap address
+  */
+#define SWAPBYTE(addr)        (uint16_t)(((uint16_t)(*((uint8_t *)(addr)))) + \
+                               (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) /*!< swap address */
+
+/**
+  * @brief low byte and high byte define
+  */
+#define LBYTE(x)  ((uint8_t)(x & 0x00FF))        /*!< low byte define */
+#define HBYTE(x)  ((uint8_t)((x & 0xFF00) >>8))  /*!< high byte define*/
+
+/**
+  * @}
+  */
+
+/** @defgroup USB_standard_exported_types
+  * @{
+  */
+
+/**
+  * @brief usb return status
+  */
+typedef enum
+{
+  USB_OK,              /*!< usb status ok */
+  USB_FAIL,            /*!< usb status fail */
+  USB_WAIT,            /*!< usb status wait */
+  USB_NOT_SUPPORT,     /*!< usb status not support */
+  USB_ERROR,           /*!< usb status error */
+}usb_sts_type;
+
+/**
+  * @brief format of usb setup data
+  */
+typedef struct
+{
+  uint8_t                                bmRequestType;                 /*!< characteristics of request */
+  uint8_t                                bRequest;                      /*!< specific request */
+  uint16_t                               wValue;                        /*!< word-sized field that varies according to request */
+  uint16_t                               wIndex;                        /*!< word-sized field that varies according to request
+                                                                           typically used to pass an index or offset */
+  uint16_t                               wLength;                       /*!< number of bytes to transfer if there is a data stage */
+}usb_setup_type;
+
+/**
+  * @brief format of standard device descriptor
+  */
+typedef struct
+{
+  uint8_t                                bLength;                       /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;               /*!< device descriptor type */
+  uint16_t                               bcdUSB;                        /*!< usb specification release number */
+  uint8_t                                bDeviceClass;                  /*!< class code (assigned by the usb-if) */
+  uint8_t                                bDeviceSubClass;               /*!< subclass code (assigned by the usb-if) */
+  uint8_t                                bDeviceProtocol;               /*!< protocol code ((assigned by the usb-if)) */
+  uint8_t                                bMaxPacketSize0;               /*!< maximum packet size for endpoint zero */
+  uint16_t                               idVendor;                      /*!< verndor id ((assigned by the usb-if)) */
+  uint16_t                               idProduct;                     /*!< product id ((assigned by the usb-if)) */
+  uint16_t                               bcdDevice;                     /*!< device release number in binary-coded decimal */
+  uint8_t                                iManufacturer;                 /*!< index of string descriptor describing manufacturer */
+  uint8_t                                iProduct;                      /*!< index of string descriptor describing product */
+  uint8_t                                iSerialNumber;                 /*!< index of string descriptor describing serial number */
+  uint8_t                                bNumConfigurations;            /*!< number of possible configurations */
+}usb_device_desc_type;
+
+/**
+  * @brief format of standard configuration descriptor
+  */
+typedef struct
+{
+  uint8_t                                bLength;                        /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;                /*!< configuration descriptor type */
+  uint16_t                               wTotalLength;                   /*!< total length of data returned for this configuration */
+  uint8_t                                bNumInterfaces;                 /*!< number of interfaces supported by this configuration */
+  uint8_t                                bConfigurationValue;            /*!< value to use as an argument to the SetConfiguration() request */
+  uint8_t                                iConfiguration;                 /*!< index of string descriptor describing this configuration */
+  uint8_t                                bmAttributes;                   /*!< configuration characteristics
+                                                                            D7 reserved
+                                                                            D6 self-powered
+                                                                            D5 remote wakeup
+                                                                            D4~D0 reserved */
+  uint8_t                                bMaxPower;                      /*!< maximum power consumption of the usb device from the bus */
+
+
+}usb_configuration_desc_type;
+
+/**
+  * @brief format of standard interface descriptor
+  */
+typedef struct
+{
+  uint8_t                                bLength;                        /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;                /*!< interface descriptor type */
+  uint8_t                                bInterfaceNumber;               /*!< number of this interface */
+  uint8_t                                bAlternateSetting;              /*!< value used to select this alternate setting for the interface */
+  uint8_t                                bNumEndpoints;                  /*!< number of endpoints used by this interface */
+  uint8_t                                bInterfaceClass;                /*!< class code (assigned by the usb-if) */
+  uint8_t                                bInterfaceSubClass;             /*!< subclass code (assigned by the usb-if) */
+  uint8_t                                bInterfaceProtocol;             /*!< protocol code (assigned by the usb-if) */
+  uint8_t                                iInterface;                     /*!< index of string descriptor describing this interface */
+}usb_interface_desc_type;
+
+/**
+  * @brief format of standard endpoint descriptor
+  */
+typedef struct
+{
+  uint8_t                                bLength;                        /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;                /*!< endpoint descriptor type */
+  uint8_t                                bEndpointAddress;               /*!< the address of the endpoint on the usb device described by this descriptor */
+  uint8_t                                bmAttributes;                   /*!< describes the endpoints attributes when it is configured using bConfiguration value */
+  uint16_t                               wMaxPacketSize;                 /*!< maximum packet size this endpoint */
+  uint8_t                                bInterval;                      /*!< interval for polling endpoint for data transfers */
+}usb_endpoint_desc_type;
+
+/**
+  * @brief format of header
+  */
+typedef struct
+{
+  uint8_t                                bLength;                        /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;                /*!< descriptor type */
+}usb_header_desc_type;
+
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 181 - 0
bsp/at32/libraries/usbd_library/inc/usbd_core.h

@@ -0,0 +1,181 @@
+/**
+  **************************************************************************
+  * @file     usbd_core.h
+  * @brief    usb device core header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_CORE_H
+#define __USBD_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "usb_std.h"
+
+/** @addtogroup USBD_drivers_core
+  * @{
+  */
+
+/** @defgroup USBD_core_exported_types
+  * @{
+  */
+
+/**
+  * @brief usb device event
+  */
+typedef enum
+{
+  USBD_NOP_EVENT,      /*!< usb device event nop */
+  USBD_RESET_EVENT,    /*!< usb device event reset */
+  USBD_SUSPEND_EVENT,  /*!< usb device event suspend */
+  USBD_WAKEUP_EVENT,   /*!< usb device event wakeup */
+  USBD_ERR_EVENT       /*!< usb device event error */
+}usbd_event_type;
+
+/**
+  * @brief usb device descriptor struct
+  */
+typedef struct
+{
+  uint16_t length;                       /*!< descriptor length */
+  uint8_t *descriptor;                   /*!< descriptor string */
+}usbd_desc_t;
+
+/**
+  * @brief usb device descriptor handler
+  */
+typedef struct
+{
+  usbd_desc_t *(*get_device_descriptor)(void);                       /*!< get device descriptor callback */
+  usbd_desc_t *(*get_device_qualifier)(void);                        /*!< get device qualifier callback */
+  usbd_desc_t *(*get_device_configuration)(void);                    /*!< get device configuration callback */
+  usbd_desc_t *(*get_device_other_speed)(void);                      /*!< get device other speed callback */
+  usbd_desc_t *(*get_device_lang_id)(void);                          /*!< get device lang id callback */
+  usbd_desc_t *(*get_device_manufacturer_string)(void);              /*!< get device manufacturer callback */
+  usbd_desc_t *(*get_device_product_string)(void);                   /*!< get device product callback */
+  usbd_desc_t *(*get_device_serial_string)(void);                    /*!< get device serial callback */
+  usbd_desc_t *(*get_device_interface_string)(void);                 /*!< get device interface string callback */
+  usbd_desc_t *(*get_device_config_string)(void);                    /*!< get device device config callback */
+}usbd_desc_handler;
+
+/**
+  * @brief usb device class handler
+  */
+typedef struct
+{
+  usb_sts_type (*init_handler)(void *udev);                          /*!< usb class init handler */
+  usb_sts_type (*clear_handler)(void *udev);                         /*!< usb class clear handler */
+  usb_sts_type (*setup_handler)(void *udev, usb_setup_type *setup);  /*!< usb class setup handler */
+  usb_sts_type (*ept0_tx_handler)(void *udev);                       /*!< usb class endpoint 0 tx complete handler */
+  usb_sts_type (*ept0_rx_handler)(void *udev);                       /*!< usb class endpoint 0 rx complete handler */
+  usb_sts_type (*in_handler)(void *udev, uint8_t ept_num);           /*!< usb class in transfer complete handler */
+  usb_sts_type (*out_handler)(void *udev, uint8_t ept_num);          /*!< usb class out transfer complete handler */
+  usb_sts_type (*sof_handler)(void *udev);                           /*!< usb class sof handler */
+  usb_sts_type (*event_handler)(void *udev, usbd_event_type event);  /*!< usb class event handler */
+  void         *pdata;                                               /*!< usb class data pointer */
+}usbd_class_handler;
+
+/**
+  * @brief usb device core struct type
+  */
+typedef struct
+{
+  usb_reg_type *usb_reg;                 /*!< usb register pointer */
+
+  usbd_class_handler *class_handler;     /*!< usb device class handler pointer */
+  usbd_desc_handler *desc_handler;       /*!< usb device descriptor handler pointer */
+
+  usb_ept_info ept_in[USB_EPT_MAX_NUM];  /*!< usb in endpoint infomation struct */
+  usb_ept_info ept_out[USB_EPT_MAX_NUM]; /*!< usb out endpoint infomation struct */
+
+  usb_setup_type setup;                  /*!< usb setup type struct */
+  uint8_t setup_buffer[12];              /*!< usb setup request buffer */
+
+  uint8_t ept0_sts;                      /*!< usb control endpoint 0 state */
+  uint8_t speed;                         /*!< usb speed */
+  uint16_t ept0_wlength;                 /*!< usb endpoint 0 transfer length */
+
+  usbd_conn_state conn_state;            /*!< usb current connect state */
+  usbd_conn_state old_conn_state;        /*!< usb save the previous connect state */
+
+  uint8_t device_addr;                   /*!< device address */
+  uint8_t remote_wakup;                  /*!< remote wakeup state */
+  uint8_t default_config;                /*!< usb default config state */
+  uint8_t dev_config;                    /*!< usb device config state */
+  uint16_t config_status;                /*!< usb configure status */
+
+  void *pdata;
+}usbd_core_type;
+
+/**
+  * @}
+  */
+
+/** @defgroup USBD_core_exported_functions
+  * @{
+  */
+void usbd_core_in_handler(usbd_core_type *udev, uint8_t ept_num);
+void usbd_core_out_handler(usbd_core_type *udev, uint8_t ept_num);
+void usbd_core_setup_handler(usbd_core_type *udev, uint8_t ept_num);
+void usbd_ctrl_unsupport(usbd_core_type *udev);
+void usbd_ctrl_send(usbd_core_type *udev, uint8_t *buffer, uint16_t len);
+void usbd_ctrl_recv(usbd_core_type *udev, uint8_t *buffer, uint16_t len);
+void usbd_ctrl_send_status(usbd_core_type *udev);
+void usbd_ctrl_recv_status(usbd_core_type *udev);
+void usbd_set_stall(usbd_core_type *udev, uint8_t ept_addr);
+void usbd_clear_stall(usbd_core_type *udev, uint8_t ept_addr);
+void usbd_ept_open(usbd_core_type *udev, uint8_t ept_addr, uint8_t ept_type, uint16_t maxpacket);
+void usbd_ept_close(usbd_core_type *udev, uint8_t ept_addr);
+void usbd_ept_send(usbd_core_type *udev, uint8_t ept_num, uint8_t *buffer, uint16_t len);
+void usbd_ept_recv(usbd_core_type *udev, uint8_t ept_num, uint8_t *buffer, uint16_t len);
+void usbd_connect(usbd_core_type *udev);
+void usbd_disconnect(usbd_core_type *udev);
+void usbd_set_device_addr(usbd_core_type *udev, uint8_t address);
+uint32_t usbd_get_recv_len(usbd_core_type *udev, uint8_t ept_addr);
+usbd_conn_state usbd_connect_state_get(usbd_core_type *udev);
+void usbd_ept_dbuffer_enable(usbd_core_type *udev, uint8_t ept_addr);
+void usbd_ept_buf_auto_define(usb_ept_info *ept_info);
+void usbd_ept_buf_custom_define( usbd_core_type *udev, uint8_t ept_addr,
+                                 uint32_t addr);
+void usbd_ept_defaut_init(usbd_core_type *udev);
+void usbd_remote_wakeup(usbd_core_type *udev);
+void usbd_enter_suspend(usbd_core_type *udev);
+void usbd_core_init(usbd_core_type *udev,
+                    usb_reg_type *usb_reg,
+                    uint8_t core_id);
+
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 72 - 0
bsp/at32/libraries/usbd_library/inc/usbd_int.h

@@ -0,0 +1,72 @@
+/**
+  **************************************************************************
+  * @file     usb_int.h
+  * @brief    usb header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_INT_H
+#define __USB_INT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes ------------------------------------------------------------------*/
+#include "usbd_core.h"
+
+/** @addtogroup USBD_drivers_interrupt
+  * @{
+  */
+
+/** @defgroup USBD_int_exported_functions
+  * @{
+  */
+void usbd_irq_handler(usbd_core_type *udev);
+void usbd_ept_loop_handler(usbd_core_type *udev);
+void usbd_eptn_handler(usbd_core_type *udev, usb_ept_number_type ept_num);
+void usbd_reset_handler(usbd_core_type *udev);
+void usbd_sof_handler(usbd_core_type *udev);
+void usbd_suspend_handler(usbd_core_type *udev);
+void usbd_wakeup_handler(usbd_core_type *udev);
+
+/* callback for rt-thread */
+void usbd_reset_callback(usbd_core_type *udev);
+void usbd_setup_phase_done_callback(usbd_core_type *udev);
+void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num);
+void usbd_sof_callback(usbd_core_type *udev);
+void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num);
+void usbd_connectCallback(usbd_core_type *udev);
+void usbd_disconnectCallback(usbd_core_type *udev);
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+

+ 63 - 0
bsp/at32/libraries/usbd_library/inc/usbd_sdr.h

@@ -0,0 +1,63 @@
+/**
+  **************************************************************************
+  * @file     usbd_sdr.h
+  * @brief    usb standard request header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_SDR_H
+#define __USBD_SDR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes ------------------------------------------------------------------*/
+#include "usbd_core.h"
+
+/** @addtogroup USBD_drivers_standard_request
+  * @{
+  */
+
+/** @defgroup USBD_sdr_exported_functions
+  * @{
+  */
+
+void usbd_setup_request_parse(usb_setup_type *setup, uint8_t *buf);
+usb_sts_type usbd_device_request(usbd_core_type *udev);
+usb_sts_type usbd_interface_request(usbd_core_type *udev);
+usb_sts_type usbd_endpoint_request(usbd_core_type *udev);
+
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 689 - 0
bsp/at32/libraries/usbd_library/src/usbd_core.c

@@ -0,0 +1,689 @@
+/**
+  **************************************************************************
+  * @file     usbd_core.c
+  * @brief    usb driver
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+#include "usbd_core.h"
+#include "usbd_sdr.h"
+#include "usbd_int.h"
+
+/** @defgroup USBD_drivers_core
+  * @brief usb device drivers core
+  * @{
+  */
+
+/** @defgroup USBD_core_private_functions
+  * @{
+  */
+
+/**
+  * @brief  usb core in transfer complete handler
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_core_in_handler(usbd_core_type *udev, uint8_t ept_addr)
+{
+  /* get endpoint info*/
+  usb_ept_info *ept_info = &udev->ept_in[ept_addr & 0x7F];
+
+  if(ept_addr == 0)
+  {
+    if(udev->ept0_sts == USB_EPT0_DATA_IN)
+    {
+      if(ept_info->rem0_len > ept_info->maxpacket)
+      {
+        ept_info->rem0_len -= ept_info->maxpacket;
+        usbd_ept_send(udev, 0, ept_info->trans_buf,
+                      MIN(ept_info->rem0_len, ept_info->maxpacket));
+      }
+      /* endpoint 0 */
+      else if(ept_info->last_len == ept_info->maxpacket
+        && ept_info->ept0_slen >= ept_info->maxpacket
+        && ept_info->ept0_slen < udev->ept0_wlength)
+      {
+        ept_info->last_len = 0;
+        usbd_ept_send(udev, 0, 0, 0);
+        usbd_ept_recv(udev, ept_addr, 0, 0);
+      }
+      else
+      {
+
+        usbd_ctrl_recv_status(udev);
+
+      }
+      usbd_data_in_stage_callback(udev,0);
+    }
+  }
+  else if(udev->class_handler->in_handler != 0 &&
+          udev->conn_state == USB_CONN_STATE_CONFIGURED)
+  {
+    /* other user define endpoint */
+    usbd_data_in_stage_callback(udev,ept_addr);
+  }
+}
+
+/**
+  * @brief  usb core out transfer complete handler
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_core_out_handler(usbd_core_type *udev, uint8_t ept_addr)
+{
+   /* get endpoint info*/
+  usb_ept_info *ept_info = &udev->ept_out[ept_addr & 0x7F];
+
+  if(ept_addr == 0)
+  {
+    /* endpoint 0 */
+    if(udev->ept0_sts == USB_EPT0_DATA_OUT)
+    {
+      if(ept_info->rem0_len > ept_info->maxpacket)
+      {
+        ept_info->rem0_len -= ept_info->maxpacket;
+        usbd_ept_recv(udev, ept_addr, ept_info->trans_buf,
+                      MIN(ept_info->rem0_len, ept_info->maxpacket));
+      }
+      else
+      {
+          usbd_ctrl_send_status(udev);
+      }
+
+      usbd_data_out_stage_callback(udev, 0);
+    }
+  }
+  else if(udev->class_handler->out_handler != 0 &&
+          udev->conn_state == USB_CONN_STATE_CONFIGURED)
+  {
+    /* other user define endpoint */
+    usbd_data_out_stage_callback(udev, ept_addr);
+  }
+}
+
+/**
+  * @brief  usb core setup transfer complete handler
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_core_setup_handler(usbd_core_type *udev, uint8_t ept_num)
+{
+  /* setup parse */
+  usbd_setup_request_parse(&udev->setup, udev->setup_buffer);
+
+  /* set ept0 status */
+  udev->ept0_sts = USB_EPT0_SETUP;
+  udev->ept0_wlength = udev->setup.wLength;
+
+  switch(udev->setup.bmRequestType & USB_REQ_RECIPIENT_MASK)
+  {
+    case USB_REQ_RECIPIENT_DEVICE:
+      /* recipient device request */
+      usbd_device_request(udev);
+      break;
+    case USB_REQ_RECIPIENT_INTERFACE:
+      /* recipient interface request */
+      usbd_interface_request(udev);
+      break;
+    case USB_REQ_RECIPIENT_ENDPOINT:
+      /* recipient endpoint request */
+      usbd_endpoint_request(udev);
+      break;
+    default:
+      break;
+  }
+}
+
+/**
+  * @brief  usb control endpoint send data
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  buffer: send data buffer
+  * @param  len: send data length
+  * @retval none
+  */
+void usbd_ctrl_send(usbd_core_type *udev, uint8_t *buffer, uint16_t len)
+{
+  usb_ept_info *ept_info = &udev->ept_in[0];
+
+  ept_info->ept0_slen = len;
+  ept_info->rem0_len = len;
+  udev->ept0_sts = USB_EPT0_DATA_IN;
+}
+
+/**
+  * @brief  usb control endpoint receive data
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  buffer: recv data buffer
+  * @param  len: recv data length
+  * @retval none
+  */
+void usbd_ctrl_recv(usbd_core_type *udev, uint8_t *buffer, uint16_t len)
+{
+  usb_ept_info *ept_info = &udev->ept_out[0];
+
+  ept_info->ept0_slen = len;
+  ept_info->rem0_len = len;
+  udev->ept0_sts = USB_EPT0_DATA_OUT;
+
+  usbd_ept_recv(udev, 0, buffer, len);
+}
+
+/**
+  * @brief  usb control endpoint send in status
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_ctrl_send_status(usbd_core_type *udev)
+{
+  udev->ept0_sts = USB_EPT0_STATUS_IN;
+
+  usbd_ept_send(udev, 0, 0, 0);
+}
+
+/**
+  * @brief  usb control endpoint send out status
+  * @param  udev: usb device core handler type
+  * @retval none
+  */
+void usbd_ctrl_recv_status(usbd_core_type *udev)
+{
+  udev->ept0_sts = USB_EPT0_STATUS_OUT;
+
+  usbd_ept_recv(udev, 0, 0, 0);
+}
+
+/**
+  * @brief  clear endpoint stall
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_clear_stall(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept_info;
+
+  if(ept_addr & 0x80)
+  {
+    /* in endpoint */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+    USB_SET_TXSTS(ept_info->eptn, USB_TX_VALID);
+  }
+  else
+  {
+    /* out endpoint */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+    USB_SET_RXSTS(ept_info->eptn, USB_RX_VALID);
+  }
+  ept_info->stall = 0;
+}
+
+/**
+  * @brief  usb set endpoint to stall.
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_set_stall(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept_info;
+
+  if(ept_addr & 0x80)
+  {
+    /* in endpoint */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+    USB_SET_TXSTS(ept_info->eptn, USB_TX_STALL);
+  }
+  else
+  {
+    /* out endpoint */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+    USB_SET_RXSTS(ept_info->eptn, USB_RX_STALL)
+  }
+
+  ept_info->stall = 1;
+}
+
+/**
+  * @brief  un-support device request
+  * @param  udev: usb device core handler type
+  * @retval none
+  */
+void usbd_ctrl_unsupport(usbd_core_type *udev)
+{
+  /* return stall status */
+  usbd_set_stall(udev, 0x00);
+  usbd_set_stall(udev, 0x80);
+}
+
+/**
+  * @brief  usb endpoint send data
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  buffer: send data buffer
+  * @param  len: send data length
+  * @retval none
+  */
+void usbd_ept_send(usbd_core_type *udev, uint8_t ept_addr, uint8_t *buffer, uint16_t len)
+{
+  /* get endpoint info struct and register */
+  usb_ept_info *ept_info = &udev->ept_in[ept_addr & 0x7F];
+  uint16_t trs_len = 0;
+  usbd_type *usbx = udev->usb_reg;
+
+  /* set send data buffer and length */
+  ept_info->trans_buf = buffer;
+  ept_info->total_len = len;
+  ept_info->trans_len = 0;
+
+  if(ept_info->total_len > ept_info->maxpacket)
+  {
+    trs_len = ept_info->maxpacket;
+    ept_info->total_len -= trs_len;
+  }
+  else
+  {
+    trs_len = len;
+    ept_info->total_len = 0;
+  }
+
+  ept_info->last_len = trs_len;
+
+  if(ept_info->is_double_buffer == 0)
+  {
+    /* write data to endpoint buffer */
+    usb_write_packet(ept_info->trans_buf, ept_info->tx_addr, trs_len);
+
+    /* set send data length */
+    USB_SET_TXLEN((ept_addr & 0x7F), trs_len);
+  }
+  else
+  {
+    if(usbx->ept_bit[ept_addr & 0x7F].txdts)
+    {
+      USB_SET_EPT_DOUBLE_BUF1_LEN((ept_addr & 0x7F), trs_len, DATA_TRANS_IN);
+      usb_write_packet(ept_info->trans_buf, ept_info->rx_addr, trs_len);
+    }
+    else
+    {
+      USB_SET_EPT_DOUBLE_BUF0_LEN((ept_addr & 0x7F), trs_len, DATA_TRANS_IN);
+      usb_write_packet(ept_info->trans_buf, ept_info->tx_addr, trs_len);
+    }
+    USB_FREE_DB_USER_BUFFER((ept_addr & 0x7F), DATA_TRANS_IN);
+  }
+
+  /* set tx status valid */
+  USB_SET_TXSTS((ept_addr & 0x7F), USB_TX_VALID);
+}
+
+/**
+  * @brief  usb endpoint receive data
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  buffer: receive data buffer
+  * @param  len: receive data length
+  * @retval none
+  */
+void usbd_ept_recv(usbd_core_type *udev, uint8_t ept_addr, uint8_t *buffer, uint16_t len)
+{
+  /* get endpoint info struct and register */
+  usb_ept_info *ept_info = &udev->ept_out[ept_addr & 0x7F];
+  uint32_t trs_len = 0;
+
+   /* set receive data buffer and length */
+  ept_info->trans_buf = buffer;
+  ept_info->total_len = len;
+  ept_info->trans_len = 0;
+
+  if(ept_info->total_len > ept_info->maxpacket)
+  {
+    trs_len = ept_info->maxpacket;
+    ept_info->total_len -= trs_len;
+  }
+  else
+  {
+    trs_len = len;
+    ept_info->total_len = 0;
+  }
+
+  /* set rx status valid */
+  USB_SET_RXSTS((ept_addr & 0x7F), USB_RX_VALID);
+}
+
+
+/**
+  * @brief  usb endpoint get receive data length
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+uint32_t usbd_get_recv_len(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept = &udev->ept_out[ept_addr & 0x7F];
+  return ept->trans_len;
+}
+
+/**
+  * @brief  enable endpoint double buffer.
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_ept_dbuffer_enable(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept_info;
+  if((ept_addr & 0x80) == 0)
+  {
+    /* out endpoint info */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+  }
+  else
+  {
+    /* in endpoint info */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+  }
+  ept_info->is_double_buffer = TRUE;
+}
+
+/**
+  * @brief  usb auto define endpoint buffer
+  * @param  usb_ept_info: endpoint information
+  * @retval none
+  */
+void usbd_ept_buf_auto_define(usb_ept_info *ept_info)
+{
+  if(ept_info->is_double_buffer == 0)
+  {
+    if( ept_info->inout == DATA_TRANS_IN )
+    {
+      if(ept_info->tx_addr == 0)
+        ept_info->tx_addr = usb_buffer_malloc(ept_info->maxpacket);
+    }
+    else
+    {
+      if(ept_info->rx_addr == 0)
+        ept_info->rx_addr = usb_buffer_malloc(ept_info->maxpacket);
+    }
+  }
+  else
+  {
+    /* double buffer auto define */
+    if(ept_info->tx_addr == 0)
+      ept_info->tx_addr = usb_buffer_malloc(ept_info->maxpacket);
+    if(ept_info->rx_addr == 0)
+      ept_info->rx_addr = usb_buffer_malloc(ept_info->maxpacket);
+  }
+}
+
+
+
+/**
+  * @brief  usb custom define endpoint buffer
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  addr: usb fifo offset address
+  * @retval none
+  */
+void usbd_ept_buf_custom_define(usbd_core_type *udev, uint8_t ept_addr,
+                                uint32_t addr)
+{
+  usb_ept_info *ept_info;
+  if((ept_addr & 0x80) == 0)
+  {
+    /* out endpoint info */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+  }
+  else
+  {
+    /* in endpoint info */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+  }
+
+  if(ept_info->is_double_buffer == 0)
+  {
+    if( ept_info->inout == DATA_TRANS_IN )
+    {
+      ept_info->tx_addr = addr;
+    }
+    else
+    {
+      ept_info->rx_addr = addr;
+    }
+  }
+  else
+  {
+    /* double buffer malloc */
+    ept_info->tx_addr = addr & 0xFFFF;
+    ept_info->rx_addr = (addr >> 16) & 0xFFFF;
+  }
+}
+
+/**
+  * @brief  usb open endpoint
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  ept_type: endpoint type
+  * @param  maxpacket: endpoint support max buffer size
+  * @retval none
+  */
+void usbd_ept_open(usbd_core_type *udev, uint8_t ept_addr, uint8_t ept_type, uint16_t maxpacket)
+{
+  usbd_type *usbx = udev->usb_reg;
+  usb_ept_info *ept_info;
+
+  if((ept_addr & 0x80) == 0)
+  {
+    /* out endpoint info */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+    ept_info->inout = DATA_TRANS_OUT;
+  }
+  else
+  {
+    /* in endpoint info */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+    ept_info->inout = DATA_TRANS_IN;
+  }
+
+  /* set endpoint maxpacket and type */
+  ept_info->maxpacket = (maxpacket + 1) & 0xFFFE;
+  ept_info->trans_type = ept_type;
+
+#ifdef USB_EPT_AUTO_MALLOC_BUFFER
+  usbd_ept_buf_auto_define(ept_info);
+#endif
+  /* open endpoint */
+  usb_ept_open(usbx, ept_info);
+}
+
+/**
+  * @brief  usb close endpoint
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_ept_close(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept_info;
+  if(ept_addr & 0x80)
+  {
+    /* in endpoint */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+  }
+  else
+  {
+    /* out endpoint */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+  }
+
+  /* close endpoint */
+  usb_ept_close(udev->usb_reg, ept_info);
+}
+
+/**
+  * @brief  usb device connect to host
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_connect(usbd_core_type *udev)
+{
+  usb_connect(udev->usb_reg);
+}
+
+/**
+  * @brief  usb device disconnect to host
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_disconnect(usbd_core_type *udev)
+{
+  usb_disconnect(udev->usb_reg);
+}
+
+/**
+  * @brief  usb device set device address.
+  * @param  udev: to the structure of usbd_core_type
+  * @param  address: host assignment address
+  * @retval none
+  */
+void usbd_set_device_addr(usbd_core_type *udev, uint8_t address)
+{
+  if(address == 0)
+    usb_set_address(udev->usb_reg, address);
+}
+
+/**
+  * @brief  get usb connect state
+  * @param  udev: to the structure of usbd_core_type
+  * @retval usb connect state
+  */
+usbd_conn_state usbd_connect_state_get(usbd_core_type *udev)
+{
+  return udev->conn_state;
+}
+
+/**
+  * @brief  usb device remote wakeup
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_remote_wakeup(usbd_core_type *udev)
+{
+  /* set connect state */
+  udev->conn_state = udev->old_conn_state;
+
+  usb_exit_suspend(udev->usb_reg);
+
+  usb_remote_wkup_set(udev->usb_reg);
+
+  rt_thread_mdelay(10);
+
+  usb_remote_wkup_clear(udev->usb_reg);
+
+}
+
+/**
+  * @brief  usb device enter suspend mode
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_enter_suspend(usbd_core_type *udev)
+{
+  usb_enter_suspend(udev->usb_reg);
+}
+
+/**
+  * @brief  usb endpoint structure initialization
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_ept_defaut_init(usbd_core_type *udev)
+{
+  uint8_t i_index = 0;
+  /* init in endpoint info structure */
+  for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
+  {
+    udev->ept_in[i_index].eptn        = i_index;
+    udev->ept_in[i_index].ept_address = i_index;
+    udev->ept_in[i_index].inout         = DATA_TRANS_IN;
+    udev->ept_in[i_index].maxpacket   = 0;
+    udev->ept_in[i_index].trans_buf   = 0;
+    udev->ept_in[i_index].total_len   = 0;
+    udev->ept_in[i_index].tx_addr     = 0;
+    udev->ept_in[i_index].rx_addr     = 0;
+  }
+
+  /* init out endpoint info structure */
+  for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
+  {
+    udev->ept_out[i_index].eptn        = i_index;
+    udev->ept_out[i_index].ept_address = i_index;
+    udev->ept_out[i_index].inout         = DATA_TRANS_OUT;
+    udev->ept_out[i_index].maxpacket   = 0;
+    udev->ept_out[i_index].trans_buf   = 0;
+    udev->ept_out[i_index].total_len   = 0;
+    udev->ept_out[i_index].rx_addr     = 0;
+    udev->ept_out[i_index].tx_addr     = 0;
+  }
+  return;
+}
+
+/**
+  * @brief  initializes the usb core
+  * @param  udev: to the structure of usbd_core_type
+  * @param  usb_reg: usb register pointer (USB)
+  * @param  class_handler: usb class handler
+  * @param  desc_handler: device config handler
+  * @param  core_id: usb core id number
+  * @retval none
+  */
+void usbd_core_init(usbd_core_type *udev,
+                    usb_reg_type *usb_reg,
+                    uint8_t core_id)
+{
+  /* set usb register type */
+  udev->usb_reg = usb_reg;
+
+  /* set usb connect state to default */
+  udev->conn_state = USB_CONN_STATE_DEFAULT;
+
+  /* init in endpoint info structure */
+  usbd_ept_defaut_init(udev);
+
+#ifdef USB_BUFFER_SIZE_EX
+  /* usb buffer size extend 768-1280 byte */
+  usb_usbbufs_enable(usb_reg, TRUE);
+#endif
+
+  /*usb register config */
+  usb_dev_init(udev->usb_reg);
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 347 - 0
bsp/at32/libraries/usbd_library/src/usbd_int.c

@@ -0,0 +1,347 @@
+/**
+  **************************************************************************
+  * @file     usbd_int.c
+  * @brief    usb interrupt request
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+#include "usbd_int.h"
+
+/** @defgroup USBD_drivers_interrupt
+  * @brief usb device interrupt
+  * @{
+  */
+
+/** @defgroup USBD_int_private_functions
+  * @{
+  */
+
+/**
+  * @brief  usb device interrput request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_irq_handler(usbd_core_type *udev)
+{
+  usbd_type *usbx = udev->usb_reg;
+  uint32_t sts_val = usbx->intsts;
+  uint32_t sts_ien = usbx->ctrl;
+
+  if(sts_val & USB_TC_FLAG)
+  {
+    /* endpoint tc interrupt handler */
+    usbd_ept_loop_handler(udev);
+  }
+
+  if(sts_val & USB_RST_FLAG)
+  {
+    /* clear reset flag */
+    usb_flag_clear(usbx, USB_RST_FLAG);
+
+    /* reset interrupt handler */
+    usbd_reset_handler(udev);
+  }
+
+  if((sts_val & USB_SOF_FLAG) &&
+    (sts_ien & USB_SOF_INT))
+  {
+    /* clear sof flag */
+    usb_flag_clear(usbx, USB_SOF_FLAG);
+
+    /* sof interrupt handler */
+    usbd_sof_callback(udev);
+  }
+
+  if((sts_val & USB_LSOF_FLAG) &&
+    (sts_ien & USB_LSOF_INT))
+  {
+    /* clear lsof flag */
+    usb_flag_clear(usbx, USB_LSOF_FLAG);
+  }
+
+  if((sts_val & USB_SP_FLAG) &&
+    (sts_ien & USB_SP_INT))
+  {
+    /* clear suspend flag */
+    usb_flag_clear(usbx, USB_SP_FLAG);
+
+    /* usb suspend interrupt handler */
+    usbd_suspend_handler(udev);
+  }
+
+  if((sts_val & USB_WK_FLAG) &&
+    (sts_ien & USB_WK_INT))
+  {
+    /* usb wakeup interrupt handler */
+    usbd_wakeup_handler(udev);
+
+    /* clear wakeup flag */
+    usb_flag_clear(usbx, USB_WK_FLAG);
+  }
+}
+
+/**
+  * @brief  usb device endpoint request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_num: endpoint number
+  * @retval none
+  */
+void usbd_eptn_handler(usbd_core_type *udev, usb_ept_number_type ept_num)
+{
+  usbd_type *usbx = udev->usb_reg;
+  usb_ept_info *ept_info;
+  uint32_t ept_val = usbx->ept[ept_num];
+  uint16_t length;
+
+  /* in interrupt request  */
+  if(ept_val & USB_TXTC)
+  {
+    /* get endpoint register and in transfer info struct */
+    ept_info = &udev->ept_in[ept_num];
+
+    /* clear endpoint tc flag */
+    USB_CLEAR_TXTC(ept_num);
+
+    /* get endpoint tx length */
+    ept_info->trans_len = USB_GET_TX_LEN(ept_num);
+
+    /* offset the trans buffer */
+    ept_info->trans_buf += ept_info->trans_len;
+
+    if(ept_info->total_len == 0 || ept_num == USB_EPT0)
+    {
+      /* in transfer complete */
+      usbd_data_in_stage_callback(udev,ept_num);
+    }
+    else
+    {
+      /* endpoint continue send data */
+      usbd_ept_send(udev, ept_num, ept_info->trans_buf, ept_info->total_len);
+    }
+    /* set the host assignment address */
+    if(udev->conn_state == USB_CONN_STATE_ADDRESSED && udev->device_addr > 0)
+    {
+      usb_set_address(udev->usb_reg, udev->device_addr);
+      udev->device_addr = 0;
+    }
+  }
+  else
+  {
+    /* setup and out interrupt request */
+
+    /* get endpoint register and out transfer info struct */
+    ept_info = &udev->ept_out[ept_num];
+
+    if((ept_val & USB_SETUPTC) != 0)
+    {
+      /* endpoint setup interrupt request */
+
+      /* get endpoint received data length */
+      ept_info->trans_len = USB_GET_RX_LEN(ept_num);
+
+      /* read endpoint received data */
+      usb_read_packet(udev->setup_buffer, ept_info->rx_addr, ept_info->trans_len);
+
+      /* clear endpoint rx tc flag */
+      USB_CLEAR_RXTC(USB_EPT0);
+
+      /* endpoint setup complete handler */
+      usbd_core_setup_handler(udev, ept_num);
+      usbd_setup_phase_done_callback(udev);
+    }
+    else if(ept_val & USB_RXTC )
+    {
+      /* endpoint out interrupt request */
+      USB_CLEAR_RXTC(ept_num);
+
+      if(ept_info->is_double_buffer == 0)
+      {
+        /* get endpoint received data length */
+        length = USB_GET_RX_LEN(ept_num);
+
+        /* read endpoint received data */
+        usb_read_packet(ept_info->trans_buf, ept_info->rx_addr, length);
+      }
+      else
+      {
+        if( ept_val & USB_RXDTS)
+        {
+          length = USB_DBUF0_GET_LEN(ept_num);
+          usb_read_packet(ept_info->trans_buf, ept_info->tx_addr, length);
+        }
+        else
+        {
+          length = USB_DBUF1_GET_LEN(ept_num);
+          usb_read_packet(ept_info->trans_buf, ept_info->rx_addr, length);
+        }
+        USB_FREE_DB_USER_BUFFER(ept_num, DATA_TRANS_OUT);
+      }
+
+      /* set received data length */
+      ept_info->trans_len += length;
+      ept_info->trans_buf += length;
+
+      if(ept_info->total_len == 0 || length < ept_info->maxpacket || ept_num == USB_EPT0)
+      {
+        /* out transfer complete */
+        usbd_data_out_stage_callback(udev, ept_num);
+      }
+      else
+      {
+        /* endpoint continue receive data  */
+        usbd_ept_recv(udev, ept_num, ept_info->trans_buf, ept_info->total_len);
+      }
+    }
+  }
+}
+
+/**
+  * @brief  usb device endpoint loop handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_ept_loop_handler(usbd_core_type *udev)
+{
+  usbd_type *usbx = udev->usb_reg;
+  usb_ept_number_type ept_num = USB_EPT0;
+  uint32_t sts_val;
+
+  while((sts_val = usbx->intsts) & USB_TC_FLAG)
+  {
+    /* get the interrupt endpoint number */
+    ept_num = (usb_ept_number_type)(sts_val & USB_EPT_NUM_FLAG);
+
+    usbd_eptn_handler(udev, ept_num);
+  }
+}
+
+/**
+  * @brief  usb device reset interrupt request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_reset_handler(usbd_core_type *udev)
+{
+  /* free usb buffer */
+  usb_buffer_free();
+
+  usbd_ept_defaut_init(udev);
+#ifndef USB_EPT_AUTO_MALLOC_BUFFER
+  usbd_ept_buf_custom_define(udev, 0x80, EPT0_TX_ADDR);
+  usbd_ept_buf_custom_define(udev, 0x00, EPT0_RX_ADDR);
+#endif
+
+  /* open endpoint 0 out */
+  usbd_ept_open(udev, 0x00, EPT_CONTROL_TYPE, 0x40);
+
+  /* open endpoint 0 in */
+  usbd_ept_open(udev, 0x80, EPT_CONTROL_TYPE, 0x40);
+
+  /* set device address to 0 */
+  usb_set_address(udev->usb_reg, 0);
+
+  /* usb connect state set to default */
+  udev->conn_state = USB_CONN_STATE_DEFAULT;
+
+  /* user define reset event */
+  usbd_reset_callback(udev);
+}
+
+/**
+  * @brief  usb device sof interrupt request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_sof_handler(usbd_core_type *udev)
+{
+  /* user sof handler in class define*/
+  if(udev->class_handler->sof_handler)
+    udev->class_handler->sof_handler(udev);
+}
+
+/**
+  * @brief  usb device suspend interrupt request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_suspend_handler(usbd_core_type *udev)
+{
+  /* save connect state */
+  udev->old_conn_state = udev->conn_state;
+
+  /* set current state to suspend */
+  udev->conn_state = USB_CONN_STATE_SUSPENDED;
+
+  /* enter suspend mode */
+  usbd_enter_suspend(udev);
+}
+
+/**
+  * @brief  usb device wakup interrupt request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_wakeup_handler(usbd_core_type *udev)
+{
+  /* exit suspend mode */
+  usb_exit_suspend(udev->usb_reg);
+
+  /* restore connect state */
+  udev->conn_state = udev->old_conn_state;
+
+  /* user define wakeup event */
+}
+
+__weak void usbd_reset_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_setup_phase_done_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+}
+
+__weak void usbd_sof_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+}
+
+__weak void usbd_connectCallback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_disconnectCallback(usbd_core_type *udev)
+{
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 533 - 0
bsp/at32/libraries/usbd_library/src/usbd_sdr.c

@@ -0,0 +1,533 @@
+/**
+  **************************************************************************
+  * @file     usbd_sdr.c
+  * @brief    usb standard device request
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+#include "usbd_sdr.h"
+
+/** @defgroup USBD_drivers_standard_request
+  * @brief usb device standard_request
+  * @{
+  */
+
+/** @defgroup USBD_sdr_private_functions
+  * @{
+  */
+
+static usb_sts_type usbd_get_descriptor(usbd_core_type *udev);
+static usb_sts_type usbd_set_address(usbd_core_type *udev);
+static usb_sts_type usbd_get_status(usbd_core_type *udev);
+static usb_sts_type usbd_clear_feature(usbd_core_type *udev);
+static usb_sts_type usbd_set_feature(usbd_core_type *udev);
+static usb_sts_type usbd_get_configuration(usbd_core_type *udev);
+static usb_sts_type usbd_set_configuration(usbd_core_type *udev);
+
+/**
+  * @brief  usb parse standard setup request
+  * @param  setup: setup structure
+  * @param  buf: setup buffer
+  * @retval none
+  */
+void usbd_setup_request_parse(usb_setup_type *setup, uint8_t *buf)
+{
+  setup->bmRequestType         = *(uint8_t *) buf;
+  setup->bRequest              = *(uint8_t *) (buf + 1);
+  setup->wValue                = SWAPBYTE(buf + 2);
+  setup->wIndex                = SWAPBYTE(buf + 4);
+  setup->wLength               = SWAPBYTE(buf + 6);
+}
+
+/**
+  * @brief  get usb standard device description request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_get_descriptor(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  uint16_t len = 0;
+  uint8_t desc_type = udev->setup.wValue >> 8;
+  usbd_desc_t *desc = NULL, usbd_desc =
+  {
+    .length = 0xA,
+    .descriptor = NULL,
+  };
+
+  switch(desc_type)
+  {
+    case USB_DESCIPTOR_TYPE_DEVICE:
+    case USB_DESCIPTOR_TYPE_CONFIGURATION:
+      desc = &usbd_desc;
+      break;
+    case USB_DESCIPTOR_TYPE_STRING:
+    {
+      uint8_t str_desc = (uint8_t)udev->setup.wValue;
+      switch(str_desc)
+      {
+        case USB_LANGID_STRING:
+        case USB_MFC_STRING:
+        case USB_PRODUCT_STRING:
+        case USB_SERIAL_STRING:
+        case USB_CONFIG_STRING:
+        case USB_INTERFACE_STRING:
+          desc = &usbd_desc;
+          break;
+        default:
+          usbd_ctrl_send(udev, desc->descriptor, len);
+          return ret;
+      }
+      break;
+    }
+    case USB_DESCIPTOR_TYPE_DEVICE_QUALIFIER:
+      usbd_ctrl_unsupport(udev);
+      break;
+    case USB_DESCIPTOR_TYPE_OTHER_SPEED:
+      usbd_ctrl_unsupport(udev);
+      return ret;
+    default:
+      usbd_ctrl_unsupport(udev);
+      return ret;
+  }
+
+  if(desc != NULL)
+  {
+    if((desc->length != 0) && (udev->setup.wLength != 0))
+    {
+      len = MIN(desc->length , udev->setup.wLength);
+      usbd_ctrl_send(udev, desc->descriptor, len);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  this request sets the device address
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_set_address(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  uint8_t dev_addr;
+
+  /* if wIndex or wLength are non-zero, then the behavior of
+     the device is not specified
+  */
+  if(setup->wIndex == 0 && setup->wLength == 0)
+  {
+    dev_addr = (uint8_t)(setup->wValue) & 0x7f;
+
+    /* device behavior when this request is received
+       while the device is in the configured state is not specified.*/
+    if(udev->conn_state == USB_CONN_STATE_CONFIGURED )
+    {
+      usbd_ctrl_unsupport(udev);
+    }
+    else
+    {
+      udev->device_addr = dev_addr;
+
+      if(dev_addr != 0)
+      {
+        udev->conn_state = USB_CONN_STATE_ADDRESSED;
+      }
+      else
+      {
+        udev->conn_state = USB_CONN_STATE_DEFAULT;
+      }
+      usbd_ctrl_send_status(udev);
+    }
+  }
+  else
+  {
+    usbd_ctrl_unsupport(udev);
+  }
+  return ret;
+}
+
+/**
+  * @brief  get usb status request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_get_status(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  switch(udev->conn_state)
+  {
+    case USB_CONN_STATE_ADDRESSED:
+    case USB_CONN_STATE_CONFIGURED:
+      if(udev->remote_wakup)
+      {
+        udev->config_status |= USB_CONF_REMOTE_WAKEUP;
+      }
+      usbd_ctrl_send(udev, (uint8_t *)(&udev->config_status), 2);
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  clear usb feature request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_clear_feature(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  switch(udev->conn_state)
+  {
+    case USB_CONN_STATE_ADDRESSED:
+    case USB_CONN_STATE_CONFIGURED:
+      if(setup->wValue == USB_FEATURE_REMOTE_WAKEUP)
+      {
+        udev->remote_wakup = 0;
+        udev->config_status &= ~USB_CONF_REMOTE_WAKEUP;
+        usbd_ctrl_send_status(udev);
+      }
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  set usb feature request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_set_feature(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  if(setup->wValue == USB_FEATURE_REMOTE_WAKEUP)
+  {
+    udev->remote_wakup = 1;
+    usbd_ctrl_send_status(udev);
+  }
+  return ret;
+}
+
+/**
+  * @brief  get usb configuration request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_get_configuration(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  if(setup->wLength != 1)
+  {
+    usbd_ctrl_unsupport(udev);
+  }
+  else
+  {
+    switch(udev->conn_state)
+    {
+      case USB_CONN_STATE_ADDRESSED:
+        udev->default_config = 0;
+        usbd_ctrl_send(udev, (uint8_t *)(&udev->default_config), 1);
+        break;
+      case USB_CONN_STATE_CONFIGURED:
+        usbd_ctrl_send(udev, (uint8_t *)(&udev->dev_config), 1);
+        break;
+      default:
+        usbd_ctrl_unsupport(udev);
+        break;
+    }
+  }
+  return ret;
+}
+
+/**
+  * @brief  sets the usb device configuration request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_set_configuration(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  static uint8_t config_value;
+  usb_setup_type *setup = &udev->setup;
+  config_value = (uint8_t)setup->wValue;
+
+  if(setup->wIndex == 0 && setup->wLength == 0)
+  {
+    switch(udev->conn_state)
+    {
+      case USB_CONN_STATE_ADDRESSED:
+        if(config_value)
+        {
+          udev->dev_config = config_value;
+          udev->conn_state = USB_CONN_STATE_CONFIGURED;
+          usbd_ctrl_send_status(udev);
+        }
+        else
+        {
+          usbd_ctrl_send_status(udev);
+        }
+
+        break;
+      case USB_CONN_STATE_CONFIGURED:
+        if(config_value == 0)
+        {
+          udev->conn_state = USB_CONN_STATE_ADDRESSED;
+          udev->dev_config = config_value;
+          usbd_ctrl_send_status(udev);
+        }
+        else if(config_value == udev->dev_config)
+        {
+          udev->dev_config = config_value;
+          usbd_ctrl_send_status(udev);
+        }
+        else
+        {
+          usbd_ctrl_send_status(udev);
+        }
+        break;
+      default:
+        usbd_ctrl_unsupport(udev);
+        break;
+    }
+  }
+  else
+  {
+    usbd_ctrl_unsupport(udev);
+  }
+  return ret;
+}
+
+/**
+  * @brief  standard usb device requests
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+usb_sts_type usbd_device_request(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  if((setup->bmRequestType & USB_REQ_TYPE_RESERVED) != USB_REQ_TYPE_STANDARD)
+  {
+    udev->class_handler->setup_handler(udev, &udev->setup);
+    return ret;
+  }
+  switch(udev->setup.bRequest)
+  {
+    case USB_STD_REQ_GET_STATUS:
+      usbd_get_status(udev);
+      break;
+    case USB_STD_REQ_CLEAR_FEATURE:
+      usbd_clear_feature(udev);
+      break;
+    case USB_STD_REQ_SET_FEATURE:
+      usbd_set_feature(udev);
+      break;
+    case USB_STD_REQ_SET_ADDRESS:
+      usbd_set_address(udev);
+      break;
+    case USB_STD_REQ_GET_DESCRIPTOR:
+      usbd_get_descriptor(udev);
+      break;
+    case USB_STD_REQ_GET_CONFIGURATION:
+      usbd_get_configuration(udev);
+      break;
+    case USB_STD_REQ_SET_CONFIGURATION:
+      usbd_set_configuration(udev);
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  standard usb interface requests
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+usb_sts_type usbd_interface_request(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  switch(udev->conn_state)
+  {
+    case USB_CONN_STATE_CONFIGURED:
+      switch(setup->bmRequestType & USB_REQ_TYPE_RESERVED)
+      {
+        case USB_REQ_TYPE_CLASS:
+          if(setup->wLength)
+          {
+            if(setup->bmRequestType & USB_REQ_DIR_DTH)
+            {
+                USB_SET_RXSTS((udev->ept_in[0].ept_address & 0x7F), USB_RX_VALID);
+            }
+            else
+            {
+             usbd_ept_send(udev, 0, 0, 0);
+               USB_SET_TXSTS((udev->ept_in[0].ept_address & 0x7F), USB_TX_VALID);
+            }
+          }
+        default:
+        break;
+      }
+
+      if(setup->wLength == 0)
+      {
+        usbd_ctrl_send_status(udev);
+      }
+      break;
+
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  standard usb endpoint requests
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+usb_sts_type usbd_endpoint_request(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  uint8_t ept_addr = LBYTE(setup->wIndex);
+  usb_ept_info *ept_info;
+
+  if((setup->bmRequestType & USB_REQ_TYPE_RESERVED) == USB_REQ_TYPE_CLASS)
+  {
+    udev->class_handler->setup_handler(udev, &udev->setup);
+  }
+  switch(setup->bRequest)
+  {
+    case USB_STD_REQ_GET_STATUS:
+      switch(udev->conn_state)
+      {
+        case USB_CONN_STATE_ADDRESSED:
+          if((ept_addr & 0x7F) != 0)
+          {
+            usbd_set_stall(udev, ept_addr);
+          }
+          break;
+        case USB_CONN_STATE_CONFIGURED:
+        {
+          if((ept_addr & 0x80) != 0)
+          {
+           ept_info = &udev->ept_in[ept_addr & 0x7F];
+          }
+          else
+          {
+            ept_info = &udev->ept_out[ept_addr & 0x7F];
+          }
+          if(ept_info->stall == 1)
+          {
+            ept_info->status = 0x0001;
+          }
+          else
+          {
+            ept_info->status = 0x0000;
+          }
+          usbd_ctrl_send(udev, (uint8_t *)(&ept_info->status), 2);
+        }
+          break;
+        default:
+          usbd_ctrl_unsupport(udev);
+          break;
+      }
+      break;
+    case USB_STD_REQ_CLEAR_FEATURE:
+      switch(udev->conn_state)
+      {
+        case USB_CONN_STATE_ADDRESSED:
+          if((ept_addr != 0x00) && (ept_addr != 0x80))
+          {
+            usbd_set_stall(udev, ept_addr);
+          }
+          break;
+        case USB_CONN_STATE_CONFIGURED:
+          if(setup->wValue == USB_FEATURE_EPT_HALT)
+          {
+            if((ept_addr & 0x7F) != 0x00 )
+            {
+              usbd_clear_stall(udev, ept_addr);
+              udev->class_handler->setup_handler(udev, &udev->setup);
+            }
+            usbd_ctrl_send_status(udev);
+          }
+          break;
+        default:
+          usbd_ctrl_unsupport(udev);
+          break;
+      }
+      break;
+    case USB_STD_REQ_SET_FEATURE:
+      switch(udev->conn_state)
+      {
+        case USB_CONN_STATE_ADDRESSED:
+          if((ept_addr != 0x00) && (ept_addr != 0x80))
+          {
+            usbd_set_stall(udev, ept_addr);
+          }
+          break;
+        case USB_CONN_STATE_CONFIGURED:
+          if(setup->wValue == USB_FEATURE_EPT_HALT)
+          {
+            if((ept_addr != 0x00) && (ept_addr != 0x80))
+            {
+              usbd_set_stall(udev, ept_addr);
+            }
+          }
+          udev->class_handler->setup_handler(udev, &udev->setup);
+          usbd_ctrl_send_status(udev);
+          break;
+        default:
+          usbd_ctrl_unsupport(udev);
+          break;
+      }
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 27 - 0
bsp/at32/libraries/usbfs_library/SConscript

@@ -0,0 +1,27 @@
+# RT-Thread building script for component
+Import('RTT_ROOT')
+Import('rtconfig')
+from building import *
+
+# get current directory
+cwd = GetCurrentDir()
+
+# add the general drivers.
+src = Split("""
+""")
+
+# The set of source files associated with this SConscript file.
+if GetDepend('BSP_USING_USBFS'):
+    src += ['src/usb_core.c']
+
+if GetDepend('RT_USING_USB_DEVICE'):
+	src += ['src/usbd_core.c', 'src/usbd_int.c', 'src/usbd_sdr.c']
+
+if GetDepend('RT_USING_USB_HOST'):
+	src += ['src/usbh_core.c', 'src/usbh_int.c', 'src/usbh_ctrl.c']
+
+CPPPATH = [cwd + '/inc']
+
+group = DefineGroup('usbfs_library', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 122 - 0
bsp/at32/libraries/usbfs_library/inc/usb_core.h

@@ -0,0 +1,122 @@
+/**
+  **************************************************************************
+  * @file     usb_core.h
+  * @brief    usb core header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_CORE_H
+#define __USB_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "usb_std.h"
+
+#ifdef USE_OTG_DEVICE_MODE
+#include "usbd_core.h"
+#endif
+#ifdef USE_OTG_HOST_MODE
+#include "usbh_core.h"
+#endif
+
+/** @addtogroup USB_drivers_core
+  * @{
+  */
+
+/** @defgroup USB_core_exported_types
+  * @{
+  */
+
+/**
+  * @brief usb core speed select
+  */
+typedef enum
+{
+  USB_LOW_SPEED_CORE_ID,          /*!< usb low speed core id */
+  USB_FULL_SPEED_CORE_ID,         /*!< usb full speed core id */
+  USB_HIGH_SPEED_CORE_ID,         /*!< usb high speed core id */
+} usb_speed_type;
+
+/**
+  * @brief usb core cofig struct
+  */
+typedef struct
+{
+  uint8_t                                speed;                     /*!< otg speed */
+  uint8_t                                dma_en;                    /*!< dma enable state, not use*/
+  uint8_t                                hc_num;                    /*!< the otg host support number of channel */
+  uint8_t                                ept_num;                   /*!< the otg device support number of endpoint */
+
+  uint16_t                               max_size;                  /*!< support max packet size */
+  uint16_t                               fifo_size;                 /*!< the usb otg total file size */
+  uint8_t                                phy_itface;                /*!< usb phy select */
+  uint8_t                                core_id;                   /*!< the usb otg core id */
+  uint8_t                                low_power;                 /*!< the usb otg low power option */
+  uint8_t                                sof_out;                   /*!< the sof signal output */
+  uint8_t                                usb_id;                    /*!< select otgfs1 or otgfs2 */
+  uint8_t                                vbusig;                    /*!< vbus ignore */
+} usb_core_cfg;
+
+/**
+  * @brief usb otg core struct type
+  */
+typedef struct
+{
+  usb_reg_type                           *usb_reg;                  /*!< the usb otg register type */
+#ifdef USE_OTG_DEVICE_MODE
+  usbd_core_type                         dev;                       /*!< the usb device core type */
+#endif
+
+#ifdef USE_OTG_HOST_MODE
+  usbh_core_type                         host;                      /*!< the usb host core type */
+#endif
+
+  usb_core_cfg                           cfg;                       /*!< the usb otg core config type */
+
+} otg_core_type;
+
+usb_sts_type usb_core_config(otg_core_type *otgdev, uint8_t core_id);
+#ifdef USE_OTG_DEVICE_MODE
+usb_sts_type usbd_init(otg_core_type *udev,
+                  uint8_t core_id, uint8_t usb_id);
+#endif
+
+#ifdef USE_OTG_HOST_MODE
+usb_sts_type usbh_init(otg_core_type *hdev,
+                  uint8_t core_id, uint8_t usb_id);
+#endif
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 368 - 0
bsp/at32/libraries/usbfs_library/inc/usb_std.h

@@ -0,0 +1,368 @@
+/**
+  **************************************************************************
+  * @file     usb_std.h
+  * @brief    usb standard header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_STD_H
+#define __USB_STD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes ------------------------------------------------------------------*/
+#include "drv_config.h"
+
+/** @addtogroup USB_standard
+  * @{
+  */
+
+/** @defgroup USB_standard_define
+  * @{
+  */
+
+/**
+  * @brief usb request recipient
+  */
+#define USB_REQ_RECIPIENT_DEVICE         0x00 /*!< usb request recipient device */
+#define USB_REQ_RECIPIENT_INTERFACE      0x01 /*!< usb request recipient interface */
+#define USB_REQ_RECIPIENT_ENDPOINT       0x02 /*!< usb request recipient endpoint */
+#define USB_REQ_RECIPIENT_OTHER          0x03 /*!< usb request recipient other */
+#define USB_REQ_RECIPIENT_MASK           0x1F /*!< usb request recipient mask */
+
+/**
+  * @brief usb request type
+  */
+#define USB_REQ_TYPE_STANDARD            0x00 /*!< usb request type standard */
+#define USB_REQ_TYPE_CLASS               0x20 /*!< usb request type class */
+#define USB_REQ_TYPE_VENDOR              0x40 /*!< usb request type vendor */
+#define USB_REQ_TYPE_RESERVED            0x60 /*!< usb request type reserved */
+
+/**
+  * @brief usb request data transfer direction
+  */
+#define USB_REQ_DIR_HTD                  0x00 /*!< usb request data transfer direction host to device */
+#define USB_REQ_DIR_DTH                  0x80 /*!< usb request data transfer direction device to host */
+
+/**
+  * @brief usb standard device requests codes
+  */
+#define USB_STD_REQ_GET_STATUS           0 /*!< usb request code status */
+#define USB_STD_REQ_CLEAR_FEATURE        1 /*!< usb request code clear feature */
+#define USB_STD_REQ_SET_FEATURE          3 /*!< usb request code feature */
+#define USB_STD_REQ_SET_ADDRESS          5 /*!< usb request code address */
+#define USB_STD_REQ_GET_DESCRIPTOR       6 /*!< usb request code get descriptor */
+#define USB_STD_REQ_SET_DESCRIPTOR       7 /*!< usb request code set descriptor */
+#define USB_STD_REQ_GET_CONFIGURATION    8 /*!< usb request code get configuration */
+#define USB_STD_REQ_SET_CONFIGURATION    9 /*!< usb request code set configuration */
+#define USB_STD_REQ_GET_INTERFACE        10 /*!< usb request code get interface */
+#define USB_STD_REQ_SET_INTERFACE        11 /*!< usb request code set interface */
+#define USB_STD_REQ_SYNCH_FRAME          12 /*!< usb request code synch frame */
+
+/**
+  * @brief usb standard device type
+  */
+#define USB_DESCIPTOR_TYPE_DEVICE        1 /*!< usb standard device type device */
+#define USB_DESCIPTOR_TYPE_CONFIGURATION 2 /*!< usb standard device type configuration */
+#define USB_DESCIPTOR_TYPE_STRING        3 /*!< usb standard device type string */
+#define USB_DESCIPTOR_TYPE_INTERFACE     4 /*!< usb standard device type interface */
+#define USB_DESCIPTOR_TYPE_ENDPOINT      5 /*!< usb standard device type endpoint */
+#define USB_DESCIPTOR_TYPE_DEVICE_QUALIFIER     6 /*!< usb standard device type qualifier */
+#define USB_DESCIPTOR_TYPE_OTHER_SPEED   7 /*!< usb standard device type other speed */
+#define USB_DESCIPTOR_TYPE_INTERFACE_POWER       8 /*!< usb standard device type interface power */
+
+/**
+  * @brief usb standard string type
+  */
+#define  USB_LANGID_STRING               0 /*!< usb standard string type lang id */
+#define  USB_MFC_STRING                  1 /*!< usb standard string type mfc */
+#define  USB_PRODUCT_STRING              2 /*!< usb standard string type product */
+#define  USB_SERIAL_STRING               3 /*!< usb standard string type serial */
+#define  USB_CONFIG_STRING               4 /*!< usb standard string type config */
+#define  USB_INTERFACE_STRING            5 /*!< usb standard string type interface */
+
+/**
+  * @brief usb configuration attributes
+  */
+#define USB_CONF_REMOTE_WAKEUP           2 /*!< usb configuration attributes remote wakeup */
+#define USB_CONF_SELF_POWERED            1 /*!< usb configuration attributes self powered */
+
+/**
+  * @brief usb standard feature selectors
+  */
+#define USB_FEATURE_EPT_HALT             0 /*!< usb standard feature selectors endpoint halt */
+#define USB_FEATURE_REMOTE_WAKEUP        1 /*!< usb standard feature selectors remote wakeup */
+
+/**
+  * @brief usb device connect state
+  */
+typedef enum
+{
+  USB_CONN_STATE_DEFAULT                =1, /*!< usb device connect state default */
+  USB_CONN_STATE_ADDRESSED,                 /*!< usb device connect state address */
+  USB_CONN_STATE_CONFIGURED,                /*!< usb device connect state configured */
+  USB_CONN_STATE_SUSPENDED                  /*!< usb device connect state suspend */
+}usbd_conn_state;
+
+/**
+  * @brief endpoint 0 state
+  */
+#define USB_EPT0_IDLE                    0 /*!< usb endpoint state idle */
+#define USB_EPT0_SETUP                   1 /*!< usb endpoint state setup */
+#define USB_EPT0_DATA_IN                 2 /*!< usb endpoint state data in */
+#define USB_EPT0_DATA_OUT                3 /*!< usb endpoint state data out */
+#define USB_EPT0_STATUS_IN               4 /*!< usb endpoint state status in */
+#define USB_EPT0_STATUS_OUT              5 /*!< usb endpoint state status out */
+#define USB_EPT0_STALL                   6 /*!< usb endpoint state stall */
+
+/**
+  * @brief usb descriptor length
+  */
+#define USB_DEVICE_QUALIFIER_DESC_LEN    0x0A /*!< usb qualifier descriptor length */
+#define USB_DEVICE_DESC_LEN              0x12 /*!< usb device descriptor length */
+#define USB_DEVICE_CFG_DESC_LEN          0x09 /*!< usb configuration descriptor length */
+#define USB_DEVICE_IF_DESC_LEN           0x09 /*!< usb interface descriptor length */
+#define USB_DEVICE_EPT_LEN               0x07 /*!< usb endpoint descriptor length */
+#define USB_DEVICE_OTG_DESC_LEN          0x03 /*!< usb otg descriptor length */
+#define USB_DEVICE_LANGID_STR_DESC_LEN   0x04 /*!< usb lang id string descriptor length */
+#define USB_DEVICE_OTHER_SPEED_DESC_SIZ_LEN 0x09 /*!< usb other speed descriptor length */
+
+/**
+  * @brief usb class code
+  */
+#define USB_CLASS_CODE_AUDIO             0x01 /*!< usb class code audio */
+#define USB_CLASS_CODE_CDC               0x02 /*!< usb class code cdc */
+#define USB_CLASS_CODE_HID               0x03 /*!< usb class code hid */
+#define USB_CLASS_CODE_PRINTER           0x07 /*!< usb class code printer */
+#define USB_CLASS_CODE_MSC               0x08 /*!< usb class code msc */
+#define USB_CLASS_CODE_HUB               0x09 /*!< usb class code hub */
+#define USB_CLASS_CODE_CDCDATA           0x0A /*!< usb class code cdc data */
+#define USB_CLASS_CODE_CCID              0x0B /*!< usb class code ccid */
+#define USB_CLASS_CODE_VIDEO             0x0E /*!< usb class code video */
+#define USB_CLASS_CODE_VENDOR            0xFF /*!< usb class code vendor */
+
+/**
+  * @brief usb endpoint type
+  */
+#define USB_EPT_DESC_CONTROL             0x00 /*!< usb endpoint description type control */
+#define USB_EPT_DESC_ISO                 0x01 /*!< usb endpoint description type iso */
+#define USB_EPT_DESC_BULK                0x02 /*!< usb endpoint description type bulk */
+#define USB_EPT_DESC_INTERRUPT           0x03 /*!< usb endpoint description type interrupt */
+
+#define USB_EPT_DESC_NSYNC               0x00 /*!< usb endpoint description nsync */
+#define USB_ETP_DESC_ASYNC               0x04 /*!< usb endpoint description async */
+#define USB_ETP_DESC_ADAPTIVE            0x08 /*!< usb endpoint description adaptive */
+#define USB_ETP_DESC_SYNC                0x0C /*!< usb endpoint description sync */
+
+#define USB_EPT_DESC_DATA_EPT            0x00 /*!< usb endpoint description data */
+#define USB_EPT_DESC_FD_EPT              0x10 /*!< usb endpoint description fd */
+#define USB_EPT_DESC_FDDATA_EPT          0x20 /*!< usb endpoint description fddata */
+
+/**
+  * @brief usb cdc class descriptor define
+  */
+#define USBD_CDC_CS_INTERFACE             0x24
+#define USBD_CDC_CS_ENDPOINT              0x25
+
+/**
+  * @brief usb cdc class sub-type define
+  */
+#define USBD_CDC_SUBTYPE_HEADER           0x00
+#define USBD_CDC_SUBTYPE_CMF              0x01
+#define USBD_CDC_SUBTYPE_ACM              0x02
+#define USBD_CDC_SUBTYPE_UFD              0x06
+
+/**
+  * @brief usb cdc class request code define
+  */
+#define SET_LINE_CODING                   0x20
+#define GET_LINE_CODING                   0x21
+
+/**
+  * @brief usb cdc class set line coding struct
+  */
+typedef struct
+{
+  uint32_t bitrate;                      /* line coding baud rate */
+  uint8_t format;                        /* line coding foramt */
+  uint8_t parity;                        /* line coding parity */
+  uint8_t data;                          /* line coding data bit */
+}linecoding_type;
+
+/**
+  * @brief usb hid class descriptor define
+  */
+#define HID_CLASS_DESC_HID               0x21
+#define HID_CLASS_DESC_REPORT            0x22
+#define HID_CLASS_DESC_PHYSICAL          0x23
+
+/**
+  * @brief usb hid class request code define
+  */
+#define HID_REQ_SET_PROTOCOL             0x0B
+#define HID_REQ_GET_PROTOCOL             0x03
+#define HID_REQ_SET_IDLE                 0x0A
+#define HID_REQ_GET_IDLE                 0x02
+#define HID_REQ_SET_REPORT               0x09
+#define HID_REQ_GET_REPORT               0x01
+#define HID_DESCRIPTOR_TYPE              0x21
+#define HID_REPORT_DESC                  0x22
+
+/**
+  * @brief endpoint 0 max size
+  */
+#define USB_MAX_EP0_SIZE                 64 /*!< usb endpoint 0 max size */
+
+/**
+  * @brief usb swap address
+  */
+#define SWAPBYTE(addr)        (uint16_t)(((uint16_t)(*((uint8_t *)(addr)))) + \
+                               (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) /*!< swap address */
+
+/**
+  * @brief low byte and high byte define
+  */
+#define LBYTE(x)  ((uint8_t)(x & 0x00FF))        /*!< low byte define */
+#define HBYTE(x)  ((uint8_t)((x & 0xFF00) >>8))  /*!< high byte define*/
+
+/**
+  * @brief usb return status
+  */
+typedef enum
+{
+  USB_OK,              /*!< usb status ok */
+  USB_FAIL,            /*!< usb status fail */
+  USB_WAIT,            /*!< usb status wait */
+  USB_NOT_SUPPORT,     /*!< usb status not support */
+  USB_ERROR,           /*!< usb status error */
+}usb_sts_type;
+
+
+/**
+  * @brief format of usb setup data
+  */
+typedef struct
+{
+  uint8_t                                bmRequestType;                 /*!< characteristics of request */
+  uint8_t                                bRequest;                      /*!< specific request */
+  uint16_t                               wValue;                        /*!< word-sized field that varies according to request */
+  uint16_t                               wIndex;                        /*!< word-sized field that varies according to request
+                                                                           typically used to pass an index or offset */
+  uint16_t                               wLength;                       /*!< number of bytes to transfer if there is a data stage */
+} usb_setup_type;
+
+/**
+  * @brief format of standard device descriptor
+  */
+typedef struct
+{
+  uint8_t                                bLength;                       /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;               /*!< device descriptor type */
+  uint16_t                               bcdUSB;                        /*!< usb specification release number */
+  uint8_t                                bDeviceClass;                  /*!< class code (assigned by the usb-if) */
+  uint8_t                                bDeviceSubClass;               /*!< subclass code (assigned by the usb-if) */
+  uint8_t                                bDeviceProtocol;               /*!< protocol code ((assigned by the usb-if)) */
+  uint8_t                                bMaxPacketSize0;               /*!< maximum packet size for endpoint zero */
+  uint16_t                               idVendor;                      /*!< verndor id ((assigned by the usb-if)) */
+  uint16_t                               idProduct;                     /*!< product id ((assigned by the usb-if)) */
+  uint16_t                               bcdDevice;                     /*!< device release number in binary-coded decimal */
+  uint8_t                                iManufacturer;                 /*!< index of string descriptor describing manufacturer */
+  uint8_t                                iProduct;                      /*!< index of string descriptor describing product */
+  uint8_t                                iSerialNumber;                 /*!< index of string descriptor describing serial number */
+  uint8_t                                bNumConfigurations;            /*!< number of possible configurations */
+} usb_device_desc_type;
+
+/**
+  * @brief format of standard configuration descriptor
+  */
+typedef struct
+{
+  uint8_t                                bLength;                        /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;                /*!< configuration descriptor type */
+  uint16_t                               wTotalLength;                   /*!< total length of data returned for this configuration */
+  uint8_t                                bNumInterfaces;                 /*!< number of interfaces supported by this configuration */
+  uint8_t                                bConfigurationValue;            /*!< value to use as an argument to the SetConfiguration() request */
+  uint8_t                                iConfiguration;                 /*!< index of string descriptor describing this configuration */
+  uint8_t                                bmAttributes;                   /*!< configuration characteristics
+                                                                            D7 reserved
+                                                                            D6 self-powered
+                                                                            D5 remote wakeup
+                                                                            D4~D0 reserved */
+  uint8_t                                bMaxPower;                      /*!< maximum power consumption of the usb device from the bus */
+
+
+}usb_configuration_desc_type;
+
+/**
+  * @brief format of standard interface descriptor
+  */
+typedef struct
+{
+  uint8_t                                bLength;                        /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;                /*!< interface descriptor type */
+  uint8_t                                bInterfaceNumber;               /*!< number of this interface */
+  uint8_t                                bAlternateSetting;              /*!< value used to select this alternate setting for the interface */
+  uint8_t                                bNumEndpoints;                  /*!< number of endpoints used by this interface */
+  uint8_t                                bInterfaceClass;                /*!< class code (assigned by the usb-if) */
+  uint8_t                                bInterfaceSubClass;             /*!< subclass code (assigned by the usb-if) */
+  uint8_t                                bInterfaceProtocol;             /*!< protocol code (assigned by the usb-if) */
+  uint8_t                                iInterface;                     /*!< index of string descriptor describing this interface */
+} usb_interface_desc_type;
+
+/**
+  * @brief format of standard endpoint descriptor
+  */
+typedef struct
+{
+  uint8_t                                bLength;                        /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;                /*!< endpoint descriptor type */
+  uint8_t                                bEndpointAddress;               /*!< the address of the endpoint on the usb device described by this descriptor */
+  uint8_t                                bmAttributes;                   /*!< describes the endpoints attributes when it is configured using bConfiguration value */
+  uint16_t                               wMaxPacketSize;                 /*!< maximum packet size this endpoint */
+  uint8_t                                bInterval;                      /*!< interval for polling endpoint for data transfers */
+} usb_endpoint_desc_type;
+
+/**
+  * @brief format of header
+  */
+typedef struct
+{
+  uint8_t                                bLength;                        /*!< size of this descriptor in bytes */
+  uint8_t                                bDescriptorType;                /*!< descriptor type */
+} usb_header_desc_type;
+
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 176 - 0
bsp/at32/libraries/usbfs_library/inc/usbd_core.h

@@ -0,0 +1,176 @@
+/**
+  **************************************************************************
+  * @file     usbd_core.h
+  * @brief    usb device core header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_CORE_H
+#define __USBD_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "usb_std.h"
+
+/** @addtogroup USBD_drivers_core
+  * @{
+  */
+
+/** @defgroup USBD_core_exported_types
+  * @{
+  */
+
+#ifdef USE_OTG_DEVICE_MODE
+
+/**
+  * @brief usb device event
+  */
+typedef enum
+{
+  USBD_NOP_EVENT,             /*!< usb device nop event */
+  USBD_RESET_EVENT,           /*!< usb device reset event */
+  USBD_SUSPEND_EVENT,         /*!< usb device suspend event */
+  USBD_WAKEUP_EVENT,          /*!< usb device wakeup event */
+  USBD_DISCONNECT_EVNET,      /*!< usb device disconnect event */
+  USBD_INISOINCOM_EVENT,      /*!< usb device inisoincom event */
+  USBD_OUTISOINCOM_EVENT,     /*!< usb device outisoincom event */
+  USBD_ERR_EVENT              /*!< usb device error event */
+}usbd_event_type;
+
+/**
+  * @brief usb device descriptor struct
+  */
+typedef struct
+{
+  uint16_t length;                       /*!< descriptor length */
+  uint8_t *descriptor;                   /*!< descriptor string */
+}usbd_desc_t;
+
+/**
+  * @brief usb device descriptor handler
+  */
+typedef struct
+{
+  usbd_desc_t *(*get_device_descriptor)(void);                       /*!< get device descriptor callback */
+  usbd_desc_t *(*get_device_qualifier)(void);                        /*!< get device qualifier callback */
+  usbd_desc_t *(*get_device_configuration)(void);                    /*!< get device configuration callback */
+  usbd_desc_t *(*get_device_other_speed)(void);                      /*!< get device other speed callback */
+  usbd_desc_t *(*get_device_lang_id)(void);                          /*!< get device lang id callback */
+  usbd_desc_t *(*get_device_manufacturer_string)(void);              /*!< get device manufacturer callback */
+  usbd_desc_t *(*get_device_product_string)(void);                   /*!< get device product callback */
+  usbd_desc_t *(*get_device_serial_string)(void);                    /*!< get device serial callback */
+  usbd_desc_t *(*get_device_interface_string)(void);                 /*!< get device interface string callback */
+  usbd_desc_t *(*get_device_config_string)(void);                    /*!< get device device config callback */
+}usbd_desc_handler;
+
+/**
+  * @brief usb device class handler
+  */
+typedef struct
+{
+  usb_sts_type (*init_handler)(void *udev);                          /*!< usb class init handler */
+  usb_sts_type (*clear_handler)(void *udev);                         /*!< usb class clear handler */
+  usb_sts_type (*setup_handler)(void *udev, usb_setup_type *setup);  /*!< usb class setup handler */
+  usb_sts_type (*ept0_tx_handler)(void *udev);                       /*!< usb class endpoint 0 tx complete handler */
+  usb_sts_type (*ept0_rx_handler)(void *udev);                       /*!< usb class endpoint 0 rx complete handler */
+  usb_sts_type (*in_handler)(void *udev, uint8_t ept_num);           /*!< usb class in transfer complete handler */
+  usb_sts_type (*out_handler)(void *udev, uint8_t ept_num);          /*!< usb class out transfer complete handler */
+  usb_sts_type (*sof_handler)(void *udev);                           /*!< usb class sof handler */
+  usb_sts_type (*event_handler)(void *udev, usbd_event_type event);  /*!< usb class event handler */
+  void         *pdata;                                               /*!< usb class data pointer */
+}usbd_class_handler;
+
+/**
+  * @brief usb device core struct type
+  */
+typedef struct
+{
+  usb_reg_type                           *usb_reg;                   /*!< usb register pointer */
+
+  usbd_class_handler                     *class_handler;             /*!< usb device class handler pointer */
+  usbd_desc_handler                      *desc_handler;              /*!< usb device descriptor handler pointer */
+
+  usb_ept_info                           ept_in[USB_EPT_MAX_NUM];    /*!< usb in endpoint infomation struct */
+  usb_ept_info                           ept_out[USB_EPT_MAX_NUM];   /*!< usb out endpoint infomation struct */
+
+  usb_setup_type                         setup;                      /*!< usb setup type struct */
+  uint8_t                                setup_buffer[12];           /*!< usb setup request buffer */
+
+  uint8_t                                ept0_sts;                   /*!< usb control endpoint 0 state */
+  uint8_t                                speed;                      /*!< usb speed */
+  uint16_t                               ept0_wlength;               /*!< usb endpoint 0 transfer length */
+
+  usbd_conn_state                        conn_state;                 /*!< usb current connect state */
+  usbd_conn_state                        old_conn_state;             /*!< usb save the previous connect state */
+
+  uint8_t                                device_addr;                /*!< device address */
+  uint8_t                                remote_wakup;               /*!< remote wakeup state */
+  uint8_t                                default_config;             /*!< usb default config state */
+  uint8_t                                dev_config;                 /*!< usb device config state */
+  uint32_t                               config_status;              /*!< usb configure status */
+
+  void                                   *pdata;
+}usbd_core_type;
+
+void usbd_core_in_handler(usbd_core_type *udev, uint8_t ept_num);
+void usbd_core_out_handler(usbd_core_type *udev, uint8_t ept_num);
+void usbd_core_setup_handler(usbd_core_type *udev, uint8_t ept_num);
+void usbd_ctrl_unsupport(usbd_core_type *udev);
+void usbd_ctrl_send(usbd_core_type *udev, uint8_t *buffer, uint16_t len);
+void usbd_ctrl_recv(usbd_core_type *udev, uint8_t *buffer, uint16_t len);
+void usbd_ctrl_send_status(usbd_core_type *udev);
+void usbd_ctrl_recv_status(usbd_core_type *udev);
+void usbd_set_stall(usbd_core_type *udev, uint8_t ept_addr);
+void usbd_clear_stall(usbd_core_type *udev, uint8_t ept_addr);
+void usbd_ept_open(usbd_core_type *udev, uint8_t ept_addr, uint8_t ept_type, uint16_t maxpacket);
+void usbd_ept_close(usbd_core_type *udev, uint8_t ept_addr);
+void usbd_ept_send(usbd_core_type *udev, uint8_t ept_num, uint8_t *buffer, uint16_t len);
+void usbd_ept_recv(usbd_core_type *udev, uint8_t ept_num, uint8_t *buffer, uint16_t len);
+void usbd_connect(usbd_core_type *udev);
+void usbd_disconnect(usbd_core_type *udev);
+void usbd_set_device_addr(usbd_core_type *udev, uint8_t address);
+uint32_t usbd_get_recv_len(usbd_core_type *udev, uint8_t ept_addr);
+void usb_ept_defaut_init(usbd_core_type *udev);
+usbd_conn_state usbd_connect_state_get(usbd_core_type *udev);
+void usbd_remote_wakeup(usbd_core_type *udev);
+void usbd_enter_suspend(usbd_core_type *udev);
+void usbd_flush_tx_fifo(usbd_core_type *udev, uint8_t ept_num);
+void usbd_fifo_alloc(usbd_core_type *udev);
+usb_sts_type usbd_core_init(usbd_core_type *udev,
+                            usb_reg_type *usb_reg,
+                            uint8_t core_id);
+#endif
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 85 - 0
bsp/at32/libraries/usbfs_library/inc/usbd_int.h

@@ -0,0 +1,85 @@
+/**
+  **************************************************************************
+  * @file     usbd_int.h
+  * @brief    usb interrupt header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBD_INT_H
+#define __USBD_INT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes ------------------------------------------------------------------*/
+#include "usbd_core.h"
+#include "usb_core.h"
+
+#ifdef USE_OTG_DEVICE_MODE
+
+/** @addtogroup USBD_drivers_int
+  * @{
+  */
+
+/** @defgroup USBD_interrupt_exported_types
+  * @{
+  */
+
+void usbd_irq_handler(otg_core_type *udev);
+void usbd_ept_handler(usbd_core_type *udev);
+void usbd_reset_handler(usbd_core_type *udev);
+void usbd_sof_handler(usbd_core_type *udev);
+void usbd_suspend_handler(usbd_core_type *udev);
+void usbd_wakeup_handler(usbd_core_type *udev);
+void usbd_inept_handler(usbd_core_type *udev);
+void usbd_outept_handler(usbd_core_type *udev);
+void usbd_enumdone_handler(usbd_core_type *udev);
+void usbd_rxflvl_handler(usbd_core_type *udev);
+void usbd_incomisioin_handler(usbd_core_type *udev);
+void usbd_discon_handler(usbd_core_type *udev);
+void usbd_incomisoout_handler(usbd_core_type *udev);
+void usb_write_empty_txfifo(usbd_core_type *udev, uint32_t ept_num);
+
+/* callback for rt-thread */
+void usbd_reset_callback(usbd_core_type *udev);
+void usbd_setup_phase_done_callback(usbd_core_type *udev);
+void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num);
+void usbd_sof_callback(usbd_core_type *udev);
+void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num);
+void usbd_connectCallback(usbd_core_type *udev);
+void usbd_disconnectCallback(usbd_core_type *udev);
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif

+ 65 - 0
bsp/at32/libraries/usbfs_library/inc/usbd_sdr.h

@@ -0,0 +1,65 @@
+/**
+  **************************************************************************
+  * @file     usb_sdr.h
+  * @brief    usb header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_SDR_H
+#define __USB_SDR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes ------------------------------------------------------------------*/
+#include "usb_core.h"
+
+#ifdef USE_OTG_DEVICE_MODE
+
+/** @addtogroup USBD_drivers_standard_request
+  * @{
+  */
+
+/** @defgroup USBD_sdr_exported_functions
+  * @{
+  */
+
+void usbd_setup_request_parse(usb_setup_type *setup, uint8_t *buf);
+usb_sts_type usbd_device_request(usbd_core_type *udev);
+usb_sts_type usbd_interface_request(usbd_core_type *udev);
+usb_sts_type usbd_endpoint_request(usbd_core_type *udev);
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif

+ 367 - 0
bsp/at32/libraries/usbfs_library/inc/usbh_core.h

@@ -0,0 +1,367 @@
+/**
+  **************************************************************************
+  * @file     usbh_core.h
+  * @brief    usb host core header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBH_CORE_H
+#define __USBH_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "usb_std.h"
+
+/** @addtogroup USBH_drivers_core
+  * @{
+  */
+
+/** @defgroup USBH_core_exported_types
+  * @{
+  */
+
+#ifdef USE_OTG_HOST_MODE
+
+/**
+  * @brief usb channel flag
+  */
+typedef enum
+{
+  HCH_IDLE,           /*!< usb host channel idle */
+  HCH_XFRC,           /*!< usb host channel transfer completed */
+  HCH_HALTED,         /*!< usb host channel halted */
+  HCH_NAK,            /*!< usb host channel nak */
+  HCH_NYET,           /*!< usb host channel nyet */
+  HCH_STALL,          /*!< usb host channel stall */
+  HCH_XACTERR,        /*!< usb host channel transaction error */
+  HCH_BBLERR,         /*!< usb host channel babble error */
+  HCH_DATATGLERR      /*!< usb host channel data toggle error */
+} hch_sts_type;
+
+/**
+  * @brief usb channel state
+  */
+typedef enum
+{
+  URB_IDLE = 0,    /*!< usb request idle state */
+  URB_DONE,        /*!< usb request done state */
+  URB_NOTREADY,    /*!< usb request not ready state */
+  URB_NYET,        /*!< usb request nyet stat e*/
+  URB_ERROR,       /*!< usb request error state */
+  URB_STALL        /*!< usb request stall state */
+} urb_sts_type;
+
+/**
+  * @brief usb control channel flag
+  */
+typedef enum
+{
+  CTRL_START = 0,      /*!< usb control request start */
+  CTRL_XFERC,          /*!< usb control request completed */
+  CTRL_HALTED,         /*!< usb control request halted */
+  CTRL_NAK,            /*!< usb control request nak */
+  CTRL_STALL,          /*!< usb control request stall */
+  CTRL_XACTERR,        /*!< usb control request transaction error */
+  CTRL_BBLERR,         /*!< usb control request babble error */
+  CTRL_DATATGLERR,     /*!< usb control request data toggle error */
+  CTRL_FAIL            /*!< usb control request failed */
+} ctrl_sts_type;
+
+/**
+  * @brief usb host control state machine
+  */
+typedef enum
+{
+  CONTROL_IDLE,              /*!< usb control state idle */
+  CONTROL_SETUP,             /*!< usb control state setup */
+  CONTROL_SETUP_WAIT,        /*!< usb control state setup wait */
+  CONTROL_DATA_IN,           /*!< usb control state data in */
+  CONTROL_DATA_IN_WAIT,      /*!< usb control state data in wait */
+  CONTROL_DATA_OUT,          /*!< usb control state data out */
+  CONTROL_DATA_OUT_WAIT,     /*!< usb control state data out wait */
+  CONTROL_STATUS_IN,         /*!< usb control state status in */
+  CONTROL_STATUS_IN_WAIT,    /*!< usb control state status in wait */
+  CONTROL_STATUS_OUT,        /*!< usb control state out */
+  CONTROL_STATUS_OUT_WAIT,   /*!< usb control state out wait */
+  CONTROL_ERROR,             /*!< usb control state error */
+  CONTROL_STALL,             /*!< usb control state stall */
+  CONTROL_COMPLETE           /*!< usb control state complete */
+} ctrl_ept0_sts_type;
+
+/**
+  * @brief usb host enumration state machine
+  */
+typedef enum
+{
+  ENUM_IDLE,                             /*!< usb host enumration state idle */
+  ENUM_GET_MIN_DESC,                     /*!< usb host enumration state get descriptor 8 byte*/
+  ENUM_GET_FULL_DESC,                    /*!< usb host enumration state get descriptor 18 byte*/
+  ENUM_SET_ADDR,                         /*!< usb host enumration state set address */
+  ENUM_GET_CFG,                          /*!< usb host enumration state get configuration */
+  ENUM_GET_FULL_CFG,                     /*!< usb host enumration state get full configuration  */
+  ENUM_GET_MFC_STRING,                   /*!< usb host enumration state get manufacturer string */
+  ENUM_GET_PRODUCT_STRING,               /*!< usb host enumration state get product string */
+  ENUM_GET_SERIALNUM_STRING,             /*!< usb host enumration state get serial number string */
+  ENUM_SET_CONFIG,                       /*!< usb host enumration state set config */
+  ENUM_COMPLETE,                         /*!< usb host enumration state complete */
+} usbh_enum_sts_type;
+
+/**
+  * @brief usb host global state machine
+  */
+typedef enum
+{
+  USBH_IDLE,                            /*!< usb host global state idle */
+  USBH_PORT_EN,                         /*!< usb host global state port enable */
+  USBH_ATTACHED,                        /*!< usb host global state attached */
+  USBH_DISCONNECT,                      /*!< usb host global state disconnect */
+  USBH_DEV_SPEED,                       /*!< usb host global state device speed */
+  USBH_ENUMERATION,                     /*!< usb host global state enumeration */
+  USBH_CLASS_REQUEST,                   /*!< usb host global state class request */
+  USBH_CLASS,                           /*!< usb host global state class */
+  USBH_CTRL_XFER,                       /*!< usb host global state control transfer */
+  USBH_USER_HANDLER,                    /*!< usb host global state user handler */
+  USBH_SUSPEND,                         /*!< usb host global state suspend */
+  USBH_SUSPENDED,                       /*!< usb host have in suspend mode */
+  USBH_WAKEUP,                          /*!< usb host global state wakeup */
+  USBH_UNSUPPORT,                       /*!< usb host global unsupport device */
+  USBH_ERROR_STATE,                     /*!< usb host global state error */
+} usbh_gstate_type;
+
+/**
+  * @brief usb host transfer state
+  */
+typedef enum
+{
+  CMD_IDLE,               /*!< usb host transfer state idle */
+  CMD_SEND,               /*!< usb host transfer state send */
+  CMD_WAIT                /*!< usb host transfer state wait */
+} cmd_sts_type;
+
+/**
+  * @brief usb host channel malloc state
+  */
+#define HCH_OK                           0x0000      /*!< usb channel malloc state ok */
+#define HCH_USED                         0x8000      /*!< usb channel had used  */
+#define HCH_ERROR                        0xFFFF      /*!< usb channel error */
+#define HCH_USED_MASK                    0x7FFF      /*!< usb channel use mask */
+
+/**
+  * @brief  channel pid
+  */
+#define HCH_PID_DATA0                    0           /*!< usb channel pid data 0 */
+#define HCH_PID_DATA2                    1           /*!< usb channel pid data 2 */
+#define HCH_PID_DATA1                    2           /*!< usb channel pid data 1 */
+#define HCH_PID_SETUP                    3           /*!< usb channel pid setup */
+
+/**
+  * @brief channel data transfer direction
+  */
+#define  USB_REQUEST_DIR_MASK            0x80             /*!< usb request direction mask */
+#define  USB_DIR_H2D                     USB_REQ_DIR_HTD  /*!< usb request direction host to device */
+#define  USB_DIR_D2H                     USB_REQ_DIR_DTH  /*!< usb request direction device to host */
+
+/**
+  * @brief request timeout
+  */
+#define DATA_STAGE_TIMEOUT               5000    /*!< usb data stage timeout */
+#define NODATA_STAGE_TIMEOUT             50      /*!< usb no-data stage timeout */
+
+/**
+  * @brief max interface and endpoint
+  */
+#define USBH_MAX_ERROR_COUNT             2   /*!< usb support maximum error */
+#define USBH_MAX_INTERFACE               5   /*!< usb support maximum interface */
+#define USBH_MAX_ENDPOINT                5   /*!< usb support maximum endpoint */
+
+/**
+  * @brief interface descriptor
+  */
+typedef struct
+{
+  usb_interface_desc_type                interface;                      /*!< usb device interface descriptor structure */
+  usb_endpoint_desc_type                 endpoint[USBH_MAX_ENDPOINT];    /*!< usb device endpoint descriptor structure array */
+} usb_itf_desc_type;
+
+/**
+  * @brief configure descriptor
+  */
+typedef struct
+{
+  usb_configuration_desc_type            cfg;                            /*!< usb device configuration descriptor structure */
+  usb_itf_desc_type                      interface[USBH_MAX_INTERFACE];  /*!< usb device interface descriptor structure array*/
+} usb_cfg_desc_type;
+
+/**
+  * @brief device descriptor
+  */
+typedef struct
+{
+  uint8_t                                address;                        /*!< usb device address */
+  uint8_t                                speed;                          /*!< usb device speed */
+  usb_device_desc_type                   dev_desc;                       /*!< usb device descriptor */
+  usb_cfg_desc_type                      cfg_desc;                       /*!< usb device configuration */
+} usbh_dev_desc_type;
+
+/**
+  * @brief usb host control struct type
+  */
+typedef struct
+{
+  uint8_t                                hch_in;                         /*!< in channel number */
+  uint8_t                                hch_out;                        /*!< out channel number */
+  uint8_t                                ept0_size;                      /*!< endpoint 0 size */
+  uint8_t                                *buffer;                        /*!< endpoint 0 transfer buffer */
+  usb_setup_type                         setup;                          /*!< control setup type */
+  uint16_t                               len;                            /*!< transfer length */
+  uint8_t                                err_cnt;                        /*!< error counter */
+  uint32_t                               timer;                          /*!< transfer timer */
+  ctrl_sts_type                          sts;                            /*!< control transfer status */
+  ctrl_ept0_sts_type                     state;                          /*!< endpoint 0 state */
+} usbh_ctrl_type;
+
+/**
+  * @brief host class handler type
+  */
+typedef struct
+{
+  usb_sts_type (*init_handler)(void *uhost);                             /*!< usb host class init handler */
+  usb_sts_type (*reset_handler)(void *uhost);                            /*!< usb host class reset handler */
+  usb_sts_type (*request_handler)(void *uhost);                          /*!< usb host class request handler */
+  usb_sts_type (*process_handler)(void *uhost);                          /*!< usb host class process handler */
+  void *pdata;                                                           /*!< usb host class data */
+} usbh_class_handler_type;
+
+/**
+  * @brief host user handler type
+  */
+typedef struct
+{
+  usb_sts_type (*user_init)(void);                                       /*!< usb host user init handler */
+  usb_sts_type (*user_reset)(void);                                      /*!< usb host user reset handler */
+  usb_sts_type (*user_attached)(void);                                   /*!< usb host user attached handler */
+  usb_sts_type (*user_disconnect)(void);                                 /*!< usb host user disconnect handler */
+  usb_sts_type (*user_speed)(uint8_t speed);                             /*!< usb host user speed handler */
+  usb_sts_type (*user_mfc_string)(void *);                               /*!< usb host user manufacturer string handler */
+  usb_sts_type (*user_product_string)(void *);                           /*!< usb host user product string handler */
+  usb_sts_type (*user_serial_string)(void *);                            /*!< usb host user serial handler */
+  usb_sts_type (*user_enumeration_done)(void);                           /*!< usb host user enumeration done handler */
+  usb_sts_type (*user_application)(void);                                /*!< usb host user application handler */
+  usb_sts_type (*user_active_vbus)(void *uhost, confirm_state state);    /*!< usb host user active vbus */
+  usb_sts_type (*user_not_support)(void);                                /*!< usb host user not support handler */
+} usbh_user_handler_type;
+
+/**
+  * @brief host host core handler type
+  */
+typedef struct
+{
+  usb_reg_type                           *usb_reg;                       /*!< usb register pointer */
+
+  uint8_t                                global_state;                   /*!< usb host global state machine */
+  uint8_t                                enum_state;                     /*!< usb host enumeration state machine */
+  uint8_t                                req_state;                      /*!< usb host request state machine */
+
+  usbh_dev_desc_type                     dev;                            /*!< usb device descriptor */
+  usbh_ctrl_type                         ctrl;                           /*!< usb host control transfer struct */
+
+  usbh_class_handler_type                *class_handler;                 /*!< usb host class handler pointer */
+  usbh_user_handler_type                 *user_handler;                  /*!< usb host user handler pointer */
+
+  usb_hch_type                           hch[USB_HOST_CHANNEL_NUM];      /*!< usb host channel array */
+  uint8_t                                rx_buffer[USB_MAX_DATA_LENGTH]; /*!< usb host rx buffer */
+
+  uint32_t                               conn_sts;                       /*!< connect status */
+  uint32_t                               port_enable;                    /*!< port enable status */
+  uint32_t                               timer;                          /*!< sof timer */
+
+  uint32_t                               err_cnt[USB_HOST_CHANNEL_NUM];  /*!< error counter */
+  uint32_t                               xfer_cnt[USB_HOST_CHANNEL_NUM]; /*!< xfer counter */
+  hch_sts_type                           hch_state[USB_HOST_CHANNEL_NUM];/*!< channel state */
+  urb_sts_type                           urb_state[USB_HOST_CHANNEL_NUM];/*!< usb request state */
+  uint16_t                               channel[USB_HOST_CHANNEL_NUM];  /*!< channel array */
+
+  void                                   *pdata;
+} usbh_core_type;
+
+
+void usbh_free_channel(usbh_core_type *uhost, uint8_t index);
+uint16_t usbh_get_free_channel(usbh_core_type *uhost);
+usb_sts_type usbh_set_toggle(usbh_core_type *uhost, uint8_t hc_num, uint8_t toggle);
+usb_sts_type usbh_in_out_request(usbh_core_type *uhost, uint8_t hc_num);
+usb_sts_type usbh_interrupt_recv(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length);
+usb_sts_type usbh_interrupt_send(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length);
+usb_sts_type usbh_bulk_recv(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length);
+usb_sts_type usbh_bulk_send(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length);
+usb_sts_type usbh_isoc_send(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length);
+usb_sts_type usbh_isoc_recv(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length);
+usb_sts_type usbh_cfg_default_init(usbh_core_type *uhost);
+void usbh_enter_suspend(usbh_core_type *uhost);
+void usbh_resume(usbh_core_type *uhost);
+
+uint16_t usbh_alloc_channel(usbh_core_type *uhost, uint8_t ept_addr);
+urb_sts_type usbh_get_urb_status(usbh_core_type *uhost, uint8_t ch_num);
+usb_sts_type usbh_ctrl_result_check(usbh_core_type *uhost,
+                                    ctrl_ept0_sts_type next_ctrl_state,
+                                    uint8_t next_enum_state);
+uint8_t usbh_alloc_address(void);
+void usbh_reset_port(usbh_core_type *uhost);
+usb_sts_type usbh_loop_handler(usbh_core_type *uhost);
+void usbh_ch_disable(usbh_core_type *uhost, uint8_t chn);
+void usbh_hc_open(usbh_core_type *uhost,
+                   uint8_t chn,
+                   uint8_t ept_num,
+                   uint8_t dev_address,
+                   uint8_t type,
+                   uint16_t maxpacket,
+                   uint8_t speed);
+void usbh_active_vbus(usbh_core_type *uhost, confirm_state state);
+
+usb_sts_type usbh_core_init(usbh_core_type *uhost,
+                            usb_reg_type *usb_reg,
+                            uint8_t core_id);
+
+hch_sts_type usbh_get_status(usbh_core_type *uhost, uint8_t ch_num);
+
+#endif
+
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 98 - 0
bsp/at32/libraries/usbfs_library/inc/usbh_ctrl.h

@@ -0,0 +1,98 @@
+/**
+  **************************************************************************
+  * @file     usbh_ctrl.h
+  * @brief    usb header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBH_CTRL_H
+#define __USBH_CTRL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes ------------------------------------------------------------------*/
+#include "usbh_core.h"
+
+/** @addtogroup USBH_drivers_control
+  * @{
+  */
+
+/** @defgroup USBH_ctrl_exported_types
+  * @{
+  */
+
+usb_sts_type usbh_ctrl_send_setup(usbh_core_type *uhost, uint8_t *buffer, uint8_t hc_num);
+usb_sts_type usbh_ctrl_recv_data(usbh_core_type *uhost, uint8_t *buffer,
+                            uint16_t length, uint16_t hc_num);
+usb_sts_type usbh_ctrl_send_data(usbh_core_type *uhost, uint8_t *buffer,
+                            uint16_t length, uint16_t hc_num);
+usb_sts_type usbh_ctrl_setup_handler(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_setup_wait_handler(usbh_core_type *uhost, uint32_t *timeout);
+usb_sts_type usbh_ctrl_data_in_handler(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_data_in_wait_handler(usbh_core_type *uhost, uint32_t timeout);
+usb_sts_type usbh_ctrl_data_out_handler(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_data_out_wait_handler(usbh_core_type *uhost, uint32_t timeout);
+usb_sts_type usbh_ctrl_status_in_handler(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_status_in_wait_handler(usbh_core_type *uhost, uint32_t timeout);
+usb_sts_type usbh_ctrl_status_out_handler(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_status_out_wait_handler(usbh_core_type *uhost, uint32_t timeout);
+usb_sts_type usbh_ctrl_error_handler(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_stall_handler(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_complete_handler(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_transfer_loop(usbh_core_type *uhost);
+usb_sts_type usbh_ctrl_request(usbh_core_type *uhost, uint8_t *buffer, uint16_t length);
+usb_sts_type usbh_get_descriptor(usbh_core_type *uhost, uint16_t length,
+                            uint8_t req_type, uint16_t wvalue,
+                            uint8_t *buffer);
+void usbh_parse_dev_desc(usbh_core_type *uhost, uint8_t *buffer, uint16_t length);
+usb_header_desc_type *usbh_get_next_header(uint8_t *buf, uint16_t *index_len);
+void usbh_parse_interface_desc(usb_interface_desc_type *intf, uint8_t *buf);
+void usbh_parse_endpoint_desc(usb_endpoint_desc_type *ept_desc, uint8_t *buf);
+usb_sts_type usbh_parse_configure_desc(usbh_core_type *uhost,
+                                  uint8_t *buffer, uint16_t length);
+uint8_t usbh_find_interface(usbh_core_type *uhost, uint8_t class_code, uint8_t sub_class, uint8_t protocol);
+void usbh_parse_string_desc(uint8_t *src, uint8_t *dest, uint16_t length);
+usb_sts_type usbh_get_device_descriptor(usbh_core_type *uhost, uint16_t length);
+usb_sts_type usbh_get_configure_descriptor(usbh_core_type *uhost, uint16_t length);
+usb_sts_type usbh_get_sting_descriptor(usbh_core_type *uhost, uint8_t string_id,
+                                  uint8_t *buffer, uint16_t length);
+usb_sts_type usbh_set_configuration(usbh_core_type *uhost, uint16_t config);
+usb_sts_type usbh_set_address(usbh_core_type *uhost, uint8_t address);
+usb_sts_type usbh_set_interface(usbh_core_type *uhost, uint8_t ept_num, uint8_t altsetting);
+usb_sts_type usbh_set_feature(usbh_core_type *uhost, uint8_t feature, uint16_t index);
+usb_sts_type usbh_clear_dev_feature(usbh_core_type *uhost, uint8_t feature, uint16_t index);
+usb_sts_type usbh_clear_ept_feature(usbh_core_type *uhost, uint8_t ept_num, uint8_t hc_num);
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 71 - 0
bsp/at32/libraries/usbfs_library/inc/usbh_int.h

@@ -0,0 +1,71 @@
+/**
+  **************************************************************************
+  * @file     usbh_int.h
+  * @brief    usb header file
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+/* define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USBH_INT_H
+#define __USBH_INT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* includes ------------------------------------------------------------------*/
+#include "usbh_core.h"
+#include "usb_core.h"
+
+/** @addtogroup USBH_drivers_int
+  * @{
+  */
+
+/** @defgroup USBH_interrupt_exported_types
+  * @{
+  */
+
+void usbh_irq_handler(otg_core_type *hdev);
+void usbh_hch_handler(usbh_core_type *uhost);
+void usbh_port_handler(usbh_core_type *uhost);
+void usbh_disconnect_handler(usbh_core_type *uhost);
+void usbh_hch_in_handler(usbh_core_type *uhost, uint8_t chn);
+void usbh_hch_out_handler(usbh_core_type *uhost, uint8_t chn);
+void usbh_rx_qlvl_handler(usbh_core_type *uhost);
+void usbh_wakeup_handler(usbh_core_type *uhost);
+void usbh_sof_handler(usbh_core_type *uhost);
+void usbh_connect_callback(usbh_core_type *uhost);
+void usbh_disconnect_callback(usbh_core_type *uhost);
+void usbd_notify_urbchange_callback(usbh_core_type *uhost, uint8_t chnum, urb_sts_type sts);
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

+ 171 - 0
bsp/at32/libraries/usbfs_library/src/usb_core.c

@@ -0,0 +1,171 @@
+/**
+  **************************************************************************
+  * @file     usb_core.c
+  * @brief    usb driver
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+#include "usb_core.h"
+
+/** @defgroup USB_drivers_core
+  * @brief usb global drivers core
+  * @{
+  */
+
+/** @defgroup USB_core_private_functions
+  * @{
+  */
+
+usb_sts_type usb_core_config(otg_core_type *udev, uint8_t core_id);
+
+/**
+  * @brief  usb core config
+  * @param  otgdev: to the structure of otg_core_type
+  * @param  core_id: usb core id number (USB_FULL_SPEED_CORE_ID)
+  * @retval usb_sts_type
+  */
+usb_sts_type usb_core_config(otg_core_type *otgdev, uint8_t core_id)
+{
+  /* set usb speed and core id */
+  otgdev->cfg.speed = core_id;
+  otgdev->cfg.core_id = core_id;
+
+  /* default sof out and vbus ignore */
+  otgdev->cfg.sof_out = FALSE;
+  otgdev->cfg.vbusig = FALSE;
+
+  /* set max size */
+  otgdev->cfg.max_size = 64;
+
+  /* set support number of channel and endpoint */
+#ifdef USE_OTG_HOST_MODE
+  otgdev->cfg.hc_num = USB_HOST_CHANNEL_NUM;
+#endif
+#ifdef USE_OTG_DEVICE_MODE
+  otgdev->cfg.ept_num = USB_EPT_MAX_NUM;
+#endif
+  otgdev->cfg.fifo_size = OTG_FIFO_SIZE;
+  if(core_id == USB_FULL_SPEED_CORE_ID)
+  {
+    otgdev->cfg.phy_itface = 2;
+  }
+#ifdef USB_SOF_OUTPUT_ENABLE
+  otgdev->cfg.sof_out = TRUE;
+#endif
+
+#ifdef USB_VBUS_IGNORE
+  otgdev->cfg.vbusig = TRUE;
+#endif
+
+  return USB_OK;
+}
+
+#ifdef USE_OTG_DEVICE_MODE
+/**
+  * @brief  usb device initialization
+  * @param  otgdev: to the structure of otg_core_type
+  * @param  core_id: usb core id number (USB_FULL_SPEED_CORE_ID)
+  * @param  usb_id: select use OTG1 or OTG2
+  *         this parameter can be one of the following values:
+  *         - USB_OTG1_ID
+  *         - USB_OTG2_ID
+  * @param  dev_handler: usb class callback handler
+  * @param  desc_handler: device config callback handler
+  * @retval usb_sts_type
+  */
+usb_sts_type usbd_init(otg_core_type *otgdev,
+                  uint8_t core_id, uint8_t usb_id)
+{
+  usb_sts_type usb_sts = USB_OK;
+
+  /* select use OTG1 or OTG2 */
+  otgdev->usb_reg = usb_global_select_core(usb_id);
+
+  /* usb device core config */
+  usb_core_config(otgdev, core_id);
+
+  if(otgdev->cfg.sof_out)
+  {
+    otgdev->usb_reg->gccfg_bit.sofouten = TRUE;
+  }
+
+  if(otgdev->cfg.vbusig)
+  {
+    otgdev->usb_reg->gccfg_bit.vbusig = TRUE;
+  }
+
+  /* usb device core init */
+  usbd_core_init(&(otgdev->dev), otgdev->usb_reg,
+                core_id);
+
+  return usb_sts;
+}
+#endif
+
+#ifdef USE_OTG_HOST_MODE
+
+/**
+  * @brief  usb host initialization.
+  * @param  otgdev: to the structure of otg_core_type
+  * @param  core_id: usb core id number (USB_FULL_SPEED_CORE_ID)
+  * @param  usb_id: select use OTG1 or OTG2
+  *         this parameter can be one of the following values:
+  *         - USB_OTG1_ID
+  *         - USB_OTG2_ID
+  * @param  class_handler: usb class callback handler
+  * @param  user_handler: user callback handler
+  * @retval usb_sts_type
+  */
+usb_sts_type usbh_init(otg_core_type *otgdev,
+                  uint8_t core_id, uint8_t usb_id)
+{
+  usb_sts_type status = USB_OK;
+
+  /* select use otg1 or otg2 */
+  otgdev->usb_reg = usb_global_select_core(usb_id);
+
+  /* usb core config */
+  usb_core_config(otgdev, core_id);
+
+  if(otgdev->cfg.sof_out)
+  {
+    otgdev->usb_reg->gccfg_bit.sofouten = TRUE;
+  }
+
+  if(otgdev->cfg.vbusig)
+  {
+    otgdev->usb_reg->gccfg_bit.vbusig = TRUE;
+  }
+
+  /* usb host core init */
+  usbh_core_init(&otgdev->host, otgdev->usb_reg,
+                core_id);
+
+  return status;
+}
+#endif
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 870 - 0
bsp/at32/libraries/usbfs_library/src/usbd_core.c

@@ -0,0 +1,870 @@
+/**
+  **************************************************************************
+  * @file     usbd_core.c
+  * @brief    usb device driver
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+#include "usb_core.h"
+#include "usbd_core.h"
+#include "usbd_sdr.h"
+
+/** @defgroup USBD_drivers_core
+  * @brief usb device drivers core
+  * @{
+  */
+
+/** @defgroup USBD_core_private_functions
+  * @{
+  */
+
+#ifdef USE_OTG_DEVICE_MODE
+
+/**
+  * @brief  usb core in transfer complete handler
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_core_in_handler(usbd_core_type *udev, uint8_t ept_addr)
+{
+  /* get endpoint info*/
+  usb_ept_info *ept_info = &udev->ept_in[ept_addr & 0x7F];
+
+  if(ept_addr == 0)
+  {
+    if(udev->ept0_sts == USB_EPT0_DATA_IN)
+    {
+      if(ept_info->rem0_len > ept_info->maxpacket)
+      {
+        ept_info->rem0_len -= ept_info->maxpacket;
+        usbd_ept_send(udev, 0, ept_info->trans_buf,
+                      MIN(ept_info->rem0_len, ept_info->maxpacket));
+      }
+      /* endpoint 0 */
+      else if(ept_info->last_len == ept_info->maxpacket
+        && ept_info->ept0_slen >= ept_info->maxpacket
+        && ept_info->ept0_slen < udev->ept0_wlength)
+      {
+        ept_info->last_len = 0;
+        usbd_ept_send(udev, 0, 0, 0);
+        usbd_ept_recv(udev, ept_addr, 0, 0);
+      }
+      else
+      {
+
+        if(udev->class_handler->ept0_tx_handler != 0 &&
+            udev->conn_state == USB_CONN_STATE_CONFIGURED)
+        {
+          udev->class_handler->ept0_tx_handler(udev);
+        }
+        usbd_ctrl_recv_status(udev);
+
+      }
+    }
+  }
+  else if(udev->class_handler->in_handler != 0 &&
+          udev->conn_state == USB_CONN_STATE_CONFIGURED)
+  {
+    /* other user define endpoint */
+    udev->class_handler->in_handler(udev, ept_addr);
+  }
+}
+
+/**
+  * @brief  usb core out transfer complete handler
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_core_out_handler(usbd_core_type *udev, uint8_t ept_addr)
+{
+   /* get endpoint info*/
+  usb_ept_info *ept_info = &udev->ept_out[ept_addr & 0x7F];
+
+  if(ept_addr == 0)
+  {
+    /* endpoint 0 */
+    if(udev->ept0_sts == USB_EPT0_DATA_OUT)
+    {
+      if(ept_info->rem0_len > ept_info->maxpacket)
+      {
+        ept_info->rem0_len -= ept_info->maxpacket;
+        usbd_ept_recv(udev, ept_addr, ept_info->trans_buf,
+                      MIN(ept_info->rem0_len, ept_info->maxpacket));
+      }
+      else
+      {
+          if(udev->class_handler->ept0_rx_handler != 0)
+          {
+            udev->class_handler->ept0_rx_handler(udev);
+          }
+          usbd_ctrl_send_status(udev);
+      }
+    }
+  }
+  else if(udev->class_handler->out_handler != 0 &&
+          udev->conn_state == USB_CONN_STATE_CONFIGURED)
+  {
+    /* other user define endpoint */
+    udev->class_handler->out_handler(udev, ept_addr);
+  }
+}
+
+/**
+  * @brief  usb core setup transfer complete handler
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_core_setup_handler(usbd_core_type *udev, uint8_t ept_num)
+{
+  /* setup parse */
+  usbd_setup_request_parse(&udev->setup, udev->setup_buffer);
+
+  /* set ept0 status */
+  udev->ept0_sts = USB_EPT0_SETUP;
+  udev->ept0_wlength = udev->setup.wLength;
+
+  switch(udev->setup.bmRequestType & USB_REQ_RECIPIENT_MASK)
+  {
+    case USB_REQ_RECIPIENT_DEVICE:
+      /* recipient device request */
+      usbd_device_request(udev);
+      break;
+    case USB_REQ_RECIPIENT_INTERFACE:
+      /* recipient interface request */
+      usbd_interface_request(udev);
+      break;
+    case USB_REQ_RECIPIENT_ENDPOINT:
+      /* recipient endpoint request */
+      usbd_endpoint_request(udev);
+      break;
+    default:
+      break;
+  }
+}
+
+/**
+  * @brief  usb control endpoint send data
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  buffer: send data buffer
+  * @param  len: send data length
+  * @retval none
+  */
+void usbd_ctrl_send(usbd_core_type *udev, uint8_t *buffer, uint16_t len)
+{
+  usb_ept_info *ept_info = &udev->ept_in[0];
+
+  ept_info->ept0_slen = len;
+  ept_info->rem0_len = len;
+  udev->ept0_sts = USB_EPT0_DATA_IN;
+
+  usbd_ept_send(udev, 0, buffer, len);
+}
+
+/**
+  * @brief  usb control endpoint recv data
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  buffer: recv data buffer
+  * @param  len: recv data length
+  * @retval none
+  */
+void usbd_ctrl_recv(usbd_core_type *udev, uint8_t *buffer, uint16_t len)
+{
+  usb_ept_info *ept_info = &udev->ept_out[0];
+
+  ept_info->ept0_slen = len;
+  ept_info->rem0_len = len;
+  udev->ept0_sts = USB_EPT0_DATA_OUT;
+
+  usbd_ept_recv(udev, 0, buffer, len);
+}
+
+/**
+  * @brief  usb control endpoint send in status
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_ctrl_send_status(usbd_core_type *udev)
+{
+  udev->ept0_sts = USB_EPT0_STATUS_IN;
+
+  usbd_ept_send(udev, 0, 0, 0);
+}
+
+/**
+  * @brief  usb control endpoint send out status
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_ctrl_recv_status(usbd_core_type *udev)
+{
+  udev->ept0_sts = USB_EPT0_STATUS_OUT;
+
+  usbd_ept_recv(udev, 0, 0, 0);
+}
+
+/**
+  * @brief  clear endpoint stall
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_clear_stall(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept_info;
+  usb_reg_type *usbx = udev->usb_reg;
+
+  if(ept_addr & 0x80)
+  {
+    /* in endpoint */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+  }
+  else
+  {
+    /* out endpoint */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+  }
+  usb_ept_clear_stall(usbx, ept_info);
+  ept_info->stall = 0;
+}
+
+/**
+  * @brief  usb set endpoint to stall status
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_set_stall(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept_info;
+  usb_reg_type *usbx = udev->usb_reg;
+
+  if(ept_addr & 0x80)
+  {
+    /* in endpoint */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+  }
+  else
+  {
+    /* out endpoint */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+  }
+  usb_ept_stall(usbx, ept_info);
+
+  ept_info->stall = 1;
+}
+
+/**
+  * @brief  un-support device request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_ctrl_unsupport(usbd_core_type *udev)
+{
+  /* return stall status */
+  usbd_set_stall(udev, 0x00);
+  usbd_set_stall(udev, 0x80);
+}
+
+/**
+  * @brief  get endpoint receive data length
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval data receive len
+  */
+uint32_t usbd_get_recv_len(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept = &udev->ept_out[ept_addr & 0x7F];
+  return ept->trans_len;
+}
+
+/**
+  * @brief  usb open endpoint
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  ept_type: endpoint type
+  * @param  maxpacket: endpoint support max buffer size
+  * @retval none
+  */
+void usbd_ept_open(usbd_core_type *udev, uint8_t ept_addr, uint8_t ept_type, uint16_t maxpacket)
+{
+  usb_reg_type *usbx = udev->usb_reg;
+  usb_ept_info *ept_info;
+
+  if((ept_addr & 0x80) == 0)
+  {
+    /* out endpoint info */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+    ept_info->inout = EPT_DIR_OUT;
+  }
+  else
+  {
+    /* in endpoint info */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+    ept_info->inout = EPT_DIR_IN;
+  }
+
+  /* set endpoint maxpacket and type */
+  ept_info->maxpacket = maxpacket;
+  ept_info->trans_type = ept_type;
+
+  /* open endpoint */
+  usb_ept_open(usbx, ept_info);
+}
+
+/**
+  * @brief  usb close endpoint
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @retval none
+  */
+void usbd_ept_close(usbd_core_type *udev, uint8_t ept_addr)
+{
+  usb_ept_info *ept_info;
+  if(ept_addr & 0x80)
+  {
+    /* in endpoint */
+    ept_info = &udev->ept_in[ept_addr & 0x7F];
+  }
+  else
+  {
+    /* out endpoint */
+    ept_info = &udev->ept_out[ept_addr & 0x7F];
+  }
+
+  /* close endpoint */
+  usb_ept_close(udev->usb_reg, ept_info);
+}
+
+/**
+  * @brief  usb device connect to host
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_connect(usbd_core_type *udev)
+{
+  usb_connect(udev->usb_reg);
+}
+
+/**
+  * @brief  usb device disconnect to host
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_disconnect(usbd_core_type *udev)
+{
+  usb_disconnect(udev->usb_reg);
+}
+
+/**
+  * @brief  usb device set device address.
+  * @param  udev: to the structure of usbd_core_type
+  * @param  address: host assignment address
+  * @retval none
+  */
+void usbd_set_device_addr(usbd_core_type *udev, uint8_t address)
+{
+  usb_set_address(udev->usb_reg, address);
+}
+
+/**
+  * @brief  usb endpoint structure initialization
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usb_ept_default_init(usbd_core_type *udev)
+{
+  uint8_t i_index = 0;
+  /* init in endpoint info structure */
+  for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
+  {
+    udev->ept_in[i_index].eptn        = i_index;
+    udev->ept_in[i_index].ept_address = i_index;
+    udev->ept_in[i_index].inout         = EPT_DIR_IN;
+    udev->ept_in[i_index].maxpacket   = 0;
+    udev->ept_in[i_index].trans_buf   = 0;
+    udev->ept_in[i_index].total_len   = 0;
+  }
+
+  /* init out endpoint info structure */
+  for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
+  {
+    udev->ept_out[i_index].eptn        = i_index;
+    udev->ept_out[i_index].ept_address = i_index;
+    udev->ept_out[i_index].inout       = EPT_DIR_OUT;
+    udev->ept_out[i_index].maxpacket   = 0;
+    udev->ept_out[i_index].trans_buf   = 0;
+    udev->ept_out[i_index].total_len   = 0;
+  }
+}
+
+/**
+  * @brief  endpoint send data
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  buffer: send data buffer
+  * @param  len: send data length
+  * @retval none
+  */
+void usbd_ept_send(usbd_core_type *udev, uint8_t ept_addr, uint8_t *buffer, uint16_t len)
+{
+  /* get endpoint info struct and register */
+  usb_reg_type *usbx = udev->usb_reg;
+  usb_ept_info *ept_info = &udev->ept_in[ept_addr & 0x7F];
+  otg_eptin_type *ept_in = USB_INEPT(usbx, ept_info->eptn);
+  otg_device_type *dev = OTG_DEVICE(usbx);
+  uint32_t pktcnt;
+
+  /* set send data buffer and length */
+  ept_info->trans_buf = buffer;
+  ept_info->total_len = len;
+  ept_info->trans_len = 0;
+
+  /* transfer data len is zero */
+  if(ept_info->total_len == 0)
+  {
+    ept_in->dieptsiz_bit.pktcnt = 1;
+    ept_in->dieptsiz_bit.xfersize = 0;
+  }
+  else
+  {
+    if((ept_addr & 0x7F) == 0) // endpoint 0
+    {
+      /* endpoint 0 */
+      if(ept_info->total_len > ept_info->maxpacket)
+      {
+        ept_info->total_len = ept_info->maxpacket;
+      }
+
+      /* set transfer size  */
+      ept_in->dieptsiz_bit.xfersize = ept_info->total_len;
+
+      /* set packet count */
+      ept_in->dieptsiz_bit.pktcnt = 1;
+
+      ept_info->last_len = ept_info->total_len;
+    }
+    else
+    {
+      /* other endpoint */
+
+      /* packet count */
+      pktcnt = (ept_info->total_len + ept_info->maxpacket - 1) / ept_info->maxpacket;
+
+      /* set transfer size  */
+      ept_in->dieptsiz_bit.xfersize = ept_info->total_len;
+
+      /* set packet count */
+      ept_in->dieptsiz_bit.pktcnt = pktcnt;
+
+      if(ept_info->trans_type == EPT_ISO_TYPE)
+      {
+        ept_in->dieptsiz_bit.mc = 1;
+      }
+    }
+  }
+
+  if(ept_info->trans_type == EPT_ISO_TYPE)
+  {
+    if((dev->dsts_bit.soffn & 0x1) == 0)
+    {
+      ept_in->diepctl_bit.setd1pid = TRUE;
+    }
+    else
+    {
+      ept_in->diepctl_bit.setd0pid = TRUE;
+    }
+  }
+
+  /* clear endpoint nak */
+  ept_in->diepctl_bit.cnak = TRUE;
+
+  /* endpoint enable */
+  ept_in->diepctl_bit.eptena = TRUE;
+
+  if(ept_info->trans_type == EPT_ISO_TYPE)
+  {
+    /* write data to fifo */
+    usb_write_packet(usbx, ept_info->trans_buf, ept_info->eptn, ept_info->total_len);
+  }
+  if(ept_info->trans_type != EPT_ISO_TYPE)
+  {
+    if(ept_info->total_len > 0)
+    {
+      /* set in endpoint tx fifo empty interrupt mask */
+      dev->diepempmsk |= 1 << ept_info->eptn;
+    }
+  }
+}
+
+/**
+  * @brief  endpoint receive data
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_addr: endpoint number
+  * @param  buffer: receive data buffer
+  * @param  len: receive data length
+  * @retval none
+  */
+void usbd_ept_recv(usbd_core_type *udev, uint8_t ept_addr, uint8_t *buffer, uint16_t len)
+{
+  /* get endpoint info struct and register */
+  usb_reg_type *usbx = udev->usb_reg;
+  usb_ept_info *ept_info = &udev->ept_out[ept_addr & 0x7F];
+  otg_eptout_type *ept_out = USB_OUTEPT(usbx, ept_info->eptn);
+  otg_device_type *dev = OTG_DEVICE(usbx);
+  uint32_t pktcnt;
+
+   /* set receive data buffer and length */
+  ept_info->trans_buf = buffer;
+  ept_info->total_len = len;
+  ept_info->trans_len = 0;
+
+  if((ept_addr & 0x7F) == 0)
+  {
+    /* endpoint 0 */
+    ept_info->total_len = ept_info->maxpacket;
+  }
+
+  if(ept_info->total_len == 0 || ((ept_addr & 0x7F) == 0))
+  {
+    /* set transfer size  */
+    ept_out->doeptsiz_bit.xfersize = ept_info->maxpacket;
+
+    /* set packet count */
+    ept_out->doeptsiz_bit.pktcnt = 1;
+  }
+  else
+  {
+    pktcnt = (ept_info->total_len + ept_info->maxpacket - 1) / ept_info->maxpacket;
+
+    /* set transfer size  */
+    ept_out->doeptsiz_bit.xfersize = ept_info->maxpacket * pktcnt;
+
+    /* set packet count */
+    ept_out->doeptsiz_bit.pktcnt = pktcnt;
+  }
+
+  if(ept_info->trans_type == EPT_ISO_TYPE)
+  {
+   if((dev->dsts_bit.soffn & 0x01) == 0)
+   {
+     ept_out->doepctl_bit.setd1pid = TRUE;
+   }
+   else
+   {
+     ept_out->doepctl_bit.setd0pid = TRUE;
+   }
+  }
+
+  /* clear endpoint nak */
+  ept_out->doepctl_bit.cnak = TRUE;
+
+  /* endpoint enable */
+  ept_out->doepctl_bit.eptena = TRUE;
+}
+
+/**
+  * @brief  get usb connect state
+  * @param  udev: to the structure of usbd_core_type
+  * @retval usb connect state
+  */
+usbd_conn_state usbd_connect_state_get(usbd_core_type *udev)
+{
+  return udev->conn_state;
+}
+
+/**
+  * @brief  usb device remote wakeup
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_remote_wakeup(usbd_core_type *udev)
+{
+  /* check device is in suspend mode */
+  if(usb_suspend_status_get(udev->usb_reg) == 1)
+  {
+    /* set connect state */
+    udev->conn_state = udev->old_conn_state;
+
+    /* open phy clock */
+    usb_open_phy_clk(udev->usb_reg);
+
+    /* set remote wakeup */
+    usb_remote_wkup_set(udev->usb_reg);
+
+    /* delay 10 ms */
+    rt_thread_mdelay(10);
+
+    /* clear remote wakup */
+    usb_remote_wkup_clear(udev->usb_reg);
+  }
+}
+
+/**
+  * @brief  usb device enter suspend mode
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_enter_suspend(usbd_core_type *udev)
+{
+  /* check device is in suspend mode */
+  if(usb_suspend_status_get(udev->usb_reg) == 1)
+  {
+    /* stop phy clk */
+    usb_stop_phy_clk(udev->usb_reg);
+  }
+}
+
+/**
+  * @brief  usb device flush in endpoint fifo
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_num: endpoint number
+  * @retval none
+  */
+void usbd_flush_tx_fifo(usbd_core_type *udev, uint8_t ept_num)
+{
+  /* flush endpoint tx fifo */
+  usb_flush_tx_fifo(udev->usb_reg, ept_num & 0x1F);
+}
+
+/**
+  * @brief  usb device endpoint fifo alloc
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_fifo_alloc(usbd_core_type *udev)
+{
+  usb_reg_type *usbx = udev->usb_reg;
+
+  if(usbx == OTG1_GLOBAL)
+  {
+    /* set receive fifo size */
+    usb_set_rx_fifo(usbx, USBD_RX_SIZE);
+
+    /* set endpoint0 tx fifo size */
+    usb_set_tx_fifo(usbx, USB_EPT0, USBD_EP0_TX_SIZE);
+
+    /* set endpoint1 tx fifo size */
+    usb_set_tx_fifo(usbx, USB_EPT1, USBD_EP1_TX_SIZE);
+
+    /* set endpoint2 tx fifo size */
+    usb_set_tx_fifo(usbx, USB_EPT2, USBD_EP2_TX_SIZE);
+
+    /* set endpoint3 tx fifo size */
+    usb_set_tx_fifo(usbx, USB_EPT3, USBD_EP3_TX_SIZE);
+#if (USB_EPT_MAX_NUM == 8)
+    if(USB_EPT_MAX_NUM == 8)
+    {
+      /* set endpoint4 tx fifo size */
+      usb_set_tx_fifo(usbx, USB_EPT4, USBD_EP4_TX_SIZE);
+
+      /* set endpoint5 tx fifo size */
+      usb_set_tx_fifo(usbx, USB_EPT5, USBD_EP5_TX_SIZE);
+
+      /* set endpoint6 tx fifo size */
+      usb_set_tx_fifo(usbx, USB_EPT6, USBD_EP6_TX_SIZE);
+
+      /* set endpoint7 tx fifo size */
+      usb_set_tx_fifo(usbx, USB_EPT7, USBD_EP7_TX_SIZE);
+    }
+#endif
+  }
+#ifdef OTG2_GLOBAL
+  if(usbx == OTG2_GLOBAL)
+  {
+    /* set receive fifo size */
+    usb_set_rx_fifo(usbx, USBD2_RX_SIZE);
+
+    /* set endpoint0 tx fifo size */
+    usb_set_tx_fifo(usbx, USB_EPT0, USBD2_EP0_TX_SIZE);
+
+    /* set endpoint1 tx fifo size */
+    usb_set_tx_fifo(usbx, USB_EPT1, USBD2_EP1_TX_SIZE);
+
+    /* set endpoint2 tx fifo size */
+    usb_set_tx_fifo(usbx, USB_EPT2, USBD2_EP2_TX_SIZE);
+
+    /* set endpoint3 tx fifo size */
+    usb_set_tx_fifo(usbx, USB_EPT3, USBD2_EP3_TX_SIZE);
+
+    if(USB_EPT_MAX_NUM == 8)
+    {
+      /* set endpoint4 tx fifo size */
+      usb_set_tx_fifo(usbx, USB_EPT4, USBD2_EP4_TX_SIZE);
+
+      /* set endpoint5 tx fifo size */
+      usb_set_tx_fifo(usbx, USB_EPT5, USBD2_EP5_TX_SIZE);
+
+      /* set endpoint6 tx fifo size */
+      usb_set_tx_fifo(usbx, USB_EPT6, USBD2_EP6_TX_SIZE);
+
+      /* set endpoint7 tx fifo size */
+      usb_set_tx_fifo(usbx, USB_EPT7, USBD2_EP7_TX_SIZE);
+    }
+  }
+#endif
+}
+
+/**
+  * @brief  usb device core initialization
+  * @param  udev: to the structure of usbd_core_type
+  * @param  usb_reg: usb otgfs peripheral global register
+  *         this parameter can be one of the following values:
+  *         OTG1_GLOBAL , OTG2_GLOBAL
+  * @param  class_handler: usb class handler
+  * @param  desc_handler: device config handler
+  * @param  core_id: usb core id number
+  * @retval usb_sts_type
+  */
+usb_sts_type usbd_core_init(usbd_core_type *udev,
+                            usb_reg_type *usb_reg,
+                            uint8_t core_id)
+{
+  usb_reg_type *usbx;
+  otg_device_type *dev;
+  otg_eptin_type *ept_in;
+  otg_eptout_type *ept_out;
+  uint32_t i_index;
+
+  udev->usb_reg = usb_reg;
+  usbx = usb_reg;
+  dev = OTG_DEVICE(usbx);
+
+  /* set connect state */
+  udev->conn_state = USB_CONN_STATE_DEFAULT;
+
+  /* device class config */
+  udev->device_addr = 0;
+  /* set device disconnect */
+  usbd_disconnect(udev);
+
+  /* set endpoint to default status */
+  usb_ept_default_init(udev);
+
+  /* disable usb global interrupt */
+  usb_interrupt_disable(usbx);
+
+  /* init global register */
+  usb_global_init(usbx);
+
+  /* set device mode */
+  usb_global_set_mode(usbx, OTG_DEVICE_MODE);
+
+  /* open phy clock */
+  usb_open_phy_clk(udev->usb_reg);
+
+  /* set periodic frame interval */
+  dev->dcfg_bit.perfrint = DCFG_PERFRINT_80;
+
+  /* set device speed to full-speed */
+  dev->dcfg_bit.devspd = USB_DCFG_FULL_SPEED;
+
+  /* flush all tx fifo */
+  usb_flush_tx_fifo(usbx, 16);
+
+  /* flush share rx fifo */
+  usb_flush_rx_fifo(usbx);
+
+  /* clear all endpoint interrupt flag and mask */
+  dev->daint = 0xFFFFFFFF;
+  dev->daintmsk = 0;
+  dev->diepmsk = 0;
+  dev->doepmsk = 0;
+
+  for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
+  {
+    usbx->dieptxfn[i_index] = 0;
+  }
+
+  /* endpoint fifo alloc */
+  usbd_fifo_alloc(udev);
+
+  /* disable all in endpoint */
+  for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
+  {
+    ept_in = USB_INEPT(usbx, i_index);
+    if(ept_in->diepctl_bit.eptena)
+    {
+      ept_in->diepctl = 0;
+      ept_in->diepctl_bit.eptdis = TRUE;
+      ept_in->diepctl_bit.snak = TRUE;
+    }
+    else
+    {
+      ept_in->diepctl = 0;
+    }
+    ept_in->dieptsiz = 0;
+    ept_in->diepint = 0xFF;
+  }
+
+  /* disable all out endpoint */
+  for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
+  {
+    ept_out = USB_OUTEPT(usbx, i_index);
+    if(ept_out->doepctl_bit.eptena)
+    {
+      ept_out->doepctl = 0;
+      ept_out->doepctl_bit.eptdis = TRUE;
+      ept_out->doepctl_bit.snak = TRUE;
+    }
+    else
+    {
+      ept_out->doepctl = 0;
+    }
+    ept_out->doeptsiz = 0;
+    ept_out->doepint = 0xFF;
+  }
+  dev->diepmsk_bit.txfifoudrmsk = TRUE;
+
+  /* clear global interrupt and mask */
+  usbx->gintmsk = 0;
+  usbx->gintsts = 0xBFFFFFFF;
+
+  /* enable global interrupt mask */
+  usbx->gintmsk = USB_OTG_SOF_INT | USB_OTG_RXFLVL_INT |
+                  USB_OTG_USBSUSP_INT | USB_OTG_USBRST_INT |
+                  USB_OTG_ENUMDONE_INT | USB_OTG_IEPT_INT |
+                  USB_OTG_OEPT_INT | USB_OTG_INCOMISOIN_INT |
+                  USB_OTG_INCOMPIP_INCOMPISOOUT_INT | USB_OTG_WKUP_INT |
+                  USB_OTG_OTGINT_INT;
+
+  /* usb connect */
+  usbd_connect(udev);
+
+  /* enable global interrupt */
+  usb_interrupt_enable(usbx);
+
+  return USB_OK;
+
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#endif

+ 560 - 0
bsp/at32/libraries/usbfs_library/src/usbd_int.c

@@ -0,0 +1,560 @@
+/**
+  **************************************************************************
+  * @file     usbd_int.c
+  * @brief    usb interrupt request
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+#include "usbd_int.h"
+
+/** @defgroup USBD_drivers_interrupt
+  * @brief usb device interrupt
+  * @{
+  */
+
+/** @defgroup USBD_int_private_functions
+  * @{
+  */
+
+#ifdef USE_OTG_DEVICE_MODE
+
+/**
+  * @brief  usb device interrput request handler.
+  * @param  otgdev: to the structure of otg_core_type
+  * @retval none
+  */
+void usbd_irq_handler(otg_core_type *otgdev)
+{
+  otg_global_type *usbx = otgdev->usb_reg;
+  usbd_core_type *udev = &otgdev->dev;
+  uint32_t intsts = usb_global_get_all_interrupt(usbx);
+
+  /* check current device mode */
+  if(usbx->gintsts_bit.curmode == 0)
+  {
+    /* mode mismatch interrupt */
+    if(intsts & USB_OTG_MODEMIS_FLAG)
+    {
+      usb_global_clear_interrupt(usbx, USB_OTG_MODEMIS_FLAG);
+    }
+
+    /* in endpoint interrupt */
+    if(intsts & USB_OTG_IEPT_FLAG)
+    {
+      usbd_inept_handler(udev);
+    }
+
+    /* out endpoint interrupt */
+    if(intsts & USB_OTG_OEPT_FLAG)
+    {
+      usbd_outept_handler(udev);
+    }
+
+    /* usb reset interrupt */
+    if(intsts & USB_OTG_USBRST_FLAG)
+    {
+      usbd_reset_handler(udev);
+      usbd_connectCallback(udev);
+      usb_global_clear_interrupt(usbx, USB_OTG_USBRST_FLAG);
+    }
+
+    /* sof interrupt */
+    if(intsts & USB_OTG_SOF_FLAG)
+    {
+      usbd_sof_handler(udev);
+      usbd_sof_callback(udev);
+      usb_global_clear_interrupt(usbx, USB_OTG_SOF_FLAG);
+    }
+
+    /* enumeration done interrupt */
+    if(intsts & USB_OTG_ENUMDONE_FLAG)
+    {
+      usbd_enumdone_handler(udev);
+      usb_global_clear_interrupt(usbx, USB_OTG_ENUMDONE_FLAG);
+    }
+
+    /* rx non-empty interrupt, indicates that there is at least one
+       data packet pending to be read in rx fifo */
+    if(intsts & USB_OTG_RXFLVL_FLAG)
+    {
+      usbd_rxflvl_handler(udev);
+    }
+
+    /* incomplete isochronous in transfer interrupt */
+    if(intsts & USB_OTG_INCOMISOIN_FLAG)
+    {
+      usbd_incomisioin_handler(udev);
+      usb_global_clear_interrupt(usbx, USB_OTG_INCOMISOIN_FLAG);
+    }
+ #ifndef USB_VBUS_IGNORE
+    /* disconnect detected interrupt  */
+    if(intsts & USB_OTG_OTGINT_FLAG)
+    {
+      uint32_t tmp = udev->usb_reg->gotgint;
+      if(udev->usb_reg->gotgint_bit.sesenddet)
+        usbd_disconnectCallback(udev);
+      udev->usb_reg->gotgint = tmp;
+      usb_global_clear_interrupt(usbx, USB_OTG_OTGINT_FLAG);
+    }
+#endif
+    /* incomplete isochronous out transfer interrupt */
+    if(intsts & USB_OTG_INCOMPIP_INCOMPISOOUT_FLAG)
+    {
+      usbd_incomisoout_handler(udev);
+      usb_global_clear_interrupt(usbx, USB_OTG_INCOMPIP_INCOMPISOOUT_FLAG);
+    }
+
+    /* resume/remote wakeup interrupt */
+    if(intsts & USB_OTG_WKUP_FLAG)
+    {
+      usbd_wakeup_handler(udev);
+      usb_global_clear_interrupt(usbx, USB_OTG_WKUP_FLAG);
+    }
+
+    /* usb suspend interrupt */
+    if(intsts & USB_OTG_USBSUSP_FLAG)
+    {
+      usbd_suspend_handler(udev);
+      usb_global_clear_interrupt(usbx, USB_OTG_USBSUSP_FLAG);
+    }
+  }
+}
+
+/**
+  * @brief  usb write tx fifo.
+  * @param  udev: to the structure of usbd_core_type
+  * @param  ept_num: endpoint number
+  * @retval none
+  */
+void usb_write_empty_txfifo(usbd_core_type *udev, uint32_t ept_num)
+{
+  otg_global_type *usbx = udev->usb_reg;
+  usb_ept_info *ept_info = &udev->ept_in[ept_num];
+  uint32_t length = ept_info->total_len - ept_info->trans_len;
+  uint32_t wlen = 0;
+
+  if(length > ept_info->maxpacket)
+  {
+    length = ept_info->maxpacket;
+  }
+  wlen = (length + 3) / 4;
+
+  while((USB_INEPT(usbx, ept_num)->dtxfsts & USB_OTG_DTXFSTS_INEPTFSAV) > wlen &&
+    (ept_info->trans_len < ept_info->total_len) && (ept_info->total_len != 0))
+  {
+    length = ept_info->total_len - ept_info->trans_len;
+    if(length > ept_info->maxpacket)
+    {
+      length = ept_info->maxpacket;
+    }
+    wlen = (length + 3) / 4;
+    usb_write_packet(usbx, ept_info->trans_buf, ept_num, length);
+
+    ept_info->trans_buf += length;
+    ept_info->trans_len += length;
+
+  }
+  if(length <= 0)
+  {
+    OTG_DEVICE(usbx)->diepempmsk &= ~(0x1 << ept_num);
+  }
+}
+
+
+/**
+  * @brief  usb in endpoint handler
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_inept_handler(usbd_core_type *udev)
+{
+  otg_global_type *usbx = udev->usb_reg;
+  uint32_t ept_num = 0, ept_int;
+  uint32_t intsts;
+
+  /*get all endpoint interrut */
+  intsts = usb_get_all_in_interrupt(usbx);
+  while(intsts)
+  {
+    if(intsts & 0x1)
+    {
+      /* get endpoint interrupt flag */
+      ept_int = usb_ept_in_interrupt(usbx, ept_num);
+
+      /* transfer completed interrupt */
+      if(ept_int & USB_OTG_DIEPINT_XFERC_FLAG)
+      {
+        OTG_DEVICE(usbx)->diepempmsk &= ~(1 << ept_num);
+        usb_ept_in_clear(usbx, ept_num , USB_OTG_DIEPINT_XFERC_FLAG);
+        usbd_data_in_stage_callback(udev, ept_num);
+      }
+
+      /* timeout condition interrupt */
+      if(ept_int & USB_OTG_DIEPINT_TIMEOUT_FLAG)
+      {
+        usb_ept_in_clear(usbx, ept_num , USB_OTG_DIEPINT_TIMEOUT_FLAG);
+      }
+
+      /* in token received when tx fifo is empty */
+      if(ept_int & USB_OTG_DIEPINT_INTKNTXFEMP_FLAG)
+      {
+        usb_ept_in_clear(usbx, ept_num , USB_OTG_DIEPINT_INTKNTXFEMP_FLAG);
+      }
+
+      /* in endpoint nak effective */
+      if(ept_int & USB_OTG_DIEPINT_INEPTNAK_FLAG)
+      {
+        usb_ept_in_clear(usbx, ept_num , USB_OTG_DIEPINT_INEPTNAK_FLAG);
+      }
+
+      /* endpoint disable interrupt */
+      if(ept_int & USB_OTG_DIEPINT_EPTDISD_FLAG)
+      {
+        usb_ept_in_clear(usbx, ept_num , USB_OTG_DIEPINT_EPTDISD_FLAG);
+      }
+
+      /* transmit fifo empty interrupt */
+      if(ept_int & USB_OTG_DIEPINT_TXFEMP_FLAG)
+      {
+        usb_write_empty_txfifo(udev, ept_num);
+      }
+    }
+    ept_num ++;
+    intsts >>= 1;
+  }
+}
+
+/**
+  * @brief  usb out endpoint handler
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_outept_handler(usbd_core_type *udev)
+{
+  otg_global_type *usbx = udev->usb_reg;
+  uint32_t ept_num = 0, ept_int;
+  uint32_t intsts;
+
+  /* get all out endpoint interrupt */
+  intsts = usb_get_all_out_interrupt(usbx);
+
+  while(intsts)
+  {
+    if(intsts & 0x1)
+    {
+      /* get out endpoint interrupt */
+      ept_int = usb_ept_out_interrupt(usbx, ept_num);
+
+      /* transfer completed interrupt */
+      if(ept_int & USB_OTG_DOEPINT_XFERC_FLAG)
+      {
+        usb_ept_out_clear(usbx, ept_num , USB_OTG_DOEPINT_XFERC_FLAG);
+        usbd_data_out_stage_callback(udev, ept_num);
+      }
+
+      /* setup phase done interrupt */
+      if(ept_int & USB_OTG_DOEPINT_SETUP_FLAG)
+      {
+        usb_ept_out_clear(usbx, ept_num , USB_OTG_DOEPINT_SETUP_FLAG);
+
+        usbd_setup_phase_done_callback(udev);
+        if(udev->device_addr != 0)
+        {
+          OTG_DEVICE(udev->usb_reg)->dcfg_bit.devaddr = udev->device_addr;
+          udev->device_addr = 0;
+        }
+      }
+
+      /* endpoint disable interrupt */
+      if(ept_int & USB_OTG_DOEPINT_OUTTEPD_FLAG)
+      {
+        usb_ept_out_clear(usbx, ept_num , USB_OTG_DOEPINT_OUTTEPD_FLAG);
+      }
+    }
+    ept_num ++;
+    intsts >>= 1;
+  }
+}
+
+/**
+  * @brief  usb enumeration done handler
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_enumdone_handler(usbd_core_type *udev)
+{
+  otg_global_type *usbx = udev->usb_reg;
+
+  usb_ept0_setup(usbx);
+
+  usbx->gusbcfg_bit.usbtrdtim = USB_TRDTIM_16;
+
+  /* open endpoint 0 out */
+  usbd_ept_open(udev, 0x00, EPT_CONTROL_TYPE, 0x40);
+
+  /* open endpoint 0 in */
+  usbd_ept_open(udev, 0x80, EPT_CONTROL_TYPE, 0x40);
+
+  /* usb connect state set to default */
+  usbd_reset_callback(udev);
+}
+
+/**
+  * @brief  usb rx non-empty handler
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_rxflvl_handler(usbd_core_type *udev)
+{
+  otg_global_type *usbx = udev->usb_reg;
+  uint32_t stsp;
+  uint32_t count;
+  uint32_t pktsts;
+  usb_ept_info *ept_info;
+
+  /* disable rxflvl interrupt */
+  usb_global_interrupt_enable(usbx, USB_OTG_RXFLVL_INT, FALSE);
+
+  /* get rx status */
+  stsp = usbx->grxstsp;
+
+  /*get the byte count of receive */
+  count = (stsp & USB_OTG_GRXSTSP_BCNT) >> 4;
+
+  /* get packet status */
+  pktsts = (stsp &USB_OTG_GRXSTSP_PKTSTS) >> 17;
+
+  /* get endpoint infomation struct */
+  ept_info = &udev->ept_out[stsp & USB_OTG_GRXSTSP_EPTNUM];
+
+  /* received out data packet */
+  if(pktsts == USB_OUT_STS_DATA)
+  {
+    if(count != 0)
+    {
+      /* read packet to buffer */
+      usb_read_packet(usbx, ept_info->trans_buf, (stsp & USB_OTG_GRXSTSP_EPTNUM), count);
+      ept_info->trans_buf += count;
+      ept_info->trans_len += count;
+
+    }
+  }
+  /* setup data received */
+  else if ( pktsts == USB_SETUP_STS_DATA)
+  {
+    /* read packet to buffer */
+    usb_read_packet(usbx, udev->setup_buffer, (stsp & USB_OTG_GRXSTSP_EPTNUM), count);
+    ept_info->trans_len += count;
+  }
+
+  /* enable rxflvl interrupt */
+  usb_global_interrupt_enable(usbx, USB_OTG_RXFLVL_INT, TRUE);
+
+}
+
+/**
+  * @brief  usb disconnect handler
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_discon_handler(usbd_core_type *udev)
+{
+  /* disconnect callback handler */
+  if(udev->class_handler->event_handler != 0)
+    udev->class_handler->event_handler(udev, USBD_DISCONNECT_EVNET);
+}
+
+
+/**
+  * @brief  usb incomplete out handler
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_incomisoout_handler(usbd_core_type *udev)
+{
+    if(udev->class_handler->event_handler != 0)
+      udev->class_handler->event_handler(udev, USBD_OUTISOINCOM_EVENT);
+}
+
+/**
+  * @brief  usb incomplete in handler
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_incomisioin_handler(usbd_core_type *udev)
+{
+  if(udev->class_handler->event_handler != 0)
+    udev->class_handler->event_handler(udev, USBD_INISOINCOM_EVENT);
+}
+
+/**
+  * @brief  usb device reset interrupt request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_reset_handler(usbd_core_type *udev)
+{
+  otg_global_type *usbx = udev->usb_reg;
+  otg_device_type *dev = OTG_DEVICE(usbx);
+  uint32_t i_index = 0;
+
+  /* disable remote wakeup singal */
+  dev->dctl_bit.rwkupsig = FALSE;
+
+  /* endpoint fifo alloc */
+  usbd_fifo_alloc(udev);
+
+  /* flush all tx fifo */
+  usb_flush_tx_fifo(usbx, 0x10);
+
+  /* clear in and out endpoint interrupt flag */
+  for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++)
+  {
+    USB_INEPT(usbx, i_index)->diepint = 0xFF;
+    USB_OUTEPT(usbx, i_index)->doepint = 0xFF;
+  }
+
+  /* clear endpoint flag */
+  dev->daint = 0xFFFFFFFF;
+
+  /*clear endpoint interrupt mask */
+  dev->daintmsk = 0x10001;
+
+  /* enable out endpoint xfer, eptdis, setup interrupt mask */
+  dev->doepmsk_bit.xfercmsk = TRUE;
+  dev->doepmsk_bit.eptdismsk = TRUE;
+  dev->doepmsk_bit.setupmsk = TRUE;
+
+  /* enable in endpoint xfer, eptdis, timeout interrupt mask */
+  dev->diepmsk_bit.xfercmsk = TRUE;
+  dev->diepmsk_bit.eptdismsk = TRUE;
+  dev->diepmsk_bit.timeoutmsk = TRUE;
+
+  /* set device address to 0 */
+  usb_set_address(usbx, 0);
+
+  /* enable endpoint 0 */
+  usb_ept0_start(usbx);
+
+  /* usb connect state set to default */
+  udev->conn_state = USB_CONN_STATE_DEFAULT;
+
+  /* user define reset event */
+  if(udev->class_handler->event_handler)
+    udev->class_handler->event_handler(udev, USBD_RESET_EVENT);
+}
+
+/**
+  * @brief  usb device sof interrupt request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_sof_handler(usbd_core_type *udev)
+{
+  /* user sof handler in class define */
+  if(udev->class_handler->sof_handler)
+    udev->class_handler->sof_handler(udev);
+}
+
+/**
+  * @brief  usb device suspend interrupt request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_suspend_handler(usbd_core_type *udev)
+{
+  otg_global_type *usbx = udev->usb_reg;
+
+  if(OTG_DEVICE(usbx)->dsts_bit.suspsts)
+  {
+    /* save connect state */
+    udev->old_conn_state = udev->conn_state;
+
+    /* set current state to suspend */
+    udev->conn_state = USB_CONN_STATE_SUSPENDED;
+
+    /* enter suspend mode */
+    usbd_enter_suspend(udev);
+
+    /* user suspend handler */
+    if(udev->class_handler->event_handler != 0)
+      udev->class_handler->event_handler(udev, USBD_SUSPEND_EVENT);
+  }
+}
+
+/**
+  * @brief  usb device wakup interrupt request handler.
+  * @param  udev: to the structure of usbd_core_type
+  * @retval none
+  */
+void usbd_wakeup_handler(usbd_core_type *udev)
+{
+  otg_global_type *usbx = udev->usb_reg;
+
+  /* clear remote wakeup bit */
+  OTG_DEVICE(usbx)->dctl_bit.rwkupsig = FALSE;
+
+  /* exit suspend mode */
+  usb_open_phy_clk(udev->usb_reg);
+
+  /* restore connect state */
+  udev->conn_state = udev->old_conn_state;
+
+    /* user suspend handler */
+  if(udev->class_handler->event_handler != 0)
+    udev->class_handler->event_handler(udev, USBD_WAKEUP_EVENT);
+}
+
+__weak void usbd_reset_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_setup_phase_done_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+}
+
+__weak void usbd_sof_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+}
+
+__weak void usbd_connectCallback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_disconnectCallback(usbd_core_type *udev)
+{
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#endif

+ 535 - 0
bsp/at32/libraries/usbfs_library/src/usbd_sdr.c

@@ -0,0 +1,535 @@
+/**
+  **************************************************************************
+  * @file     usbd_sdr.c
+  * @brief    usb standard device request
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+#include "usbd_sdr.h"
+
+/** @addtogroup AT32F435_437_middlewares_usbd_drivers
+  * @{
+  */
+
+/** @defgroup USBD_drivers_standard_request
+  * @brief usb device standard_request
+  * @{
+  */
+
+#ifdef USE_OTG_DEVICE_MODE
+
+/** @defgroup USBD_sdr_private_functions
+  * @{
+  */
+
+static usb_sts_type usbd_get_descriptor(usbd_core_type *udev);
+static usb_sts_type usbd_set_address(usbd_core_type *udev);
+static usb_sts_type usbd_get_status(usbd_core_type *udev);
+static usb_sts_type usbd_clear_feature(usbd_core_type *udev);
+static usb_sts_type usbd_set_feature(usbd_core_type *udev);
+static usb_sts_type usbd_get_configuration(usbd_core_type *udev);
+static usb_sts_type usbd_set_configuration(usbd_core_type *udev);
+
+/**
+  * @brief  usb parse standard setup request
+  * @param  setup: setup structure
+  * @param  buf: setup buffer
+  * @retval none
+  */
+void usbd_setup_request_parse(usb_setup_type *setup, uint8_t *buf)
+{
+  setup->bmRequestType         = *(uint8_t *) buf;
+  setup->bRequest              = *(uint8_t *) (buf + 1);
+  setup->wValue                = SWAPBYTE(buf + 2);
+  setup->wIndex                = SWAPBYTE(buf + 4);
+  setup->wLength               = SWAPBYTE(buf + 6);
+}
+
+/**
+  * @brief  get usb standard device description request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_get_descriptor(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  uint16_t len = 0;
+  usbd_desc_t *desc = NULL;
+  uint8_t desc_type = udev->setup.wValue >> 8;
+  switch(desc_type)
+  {
+    case USB_DESCIPTOR_TYPE_DEVICE:
+      desc = udev->desc_handler->get_device_descriptor();
+      break;
+    case USB_DESCIPTOR_TYPE_CONFIGURATION:
+      desc = udev->desc_handler->get_device_configuration();
+      break;
+    case USB_DESCIPTOR_TYPE_STRING:
+    {
+      uint8_t str_desc = (uint8_t)udev->setup.wValue;
+      switch(str_desc)
+      {
+        case USB_LANGID_STRING:
+          desc = udev->desc_handler->get_device_lang_id();
+          break;
+        case USB_MFC_STRING:
+          desc = udev->desc_handler->get_device_manufacturer_string();
+          break;
+        case USB_PRODUCT_STRING:
+          desc = udev->desc_handler->get_device_product_string();
+          break;
+        case USB_SERIAL_STRING:
+          desc = udev->desc_handler->get_device_serial_string();
+          break;
+        case USB_CONFIG_STRING:
+          desc = udev->desc_handler->get_device_config_string();
+          break;
+        case USB_INTERFACE_STRING:
+          desc = udev->desc_handler->get_device_interface_string();
+          break;
+        default:
+          udev->class_handler->setup_handler(udev, &udev->setup);
+          return ret;
+      }
+      break;
+    }
+    case USB_DESCIPTOR_TYPE_DEVICE_QUALIFIER:
+      usbd_ctrl_unsupport(udev);
+      break;
+    case USB_DESCIPTOR_TYPE_OTHER_SPEED:
+      usbd_ctrl_unsupport(udev);
+      return ret;
+    default:
+      usbd_ctrl_unsupport(udev);
+      return ret;
+  }
+
+  if(desc != NULL)
+  {
+    if((desc->length != 0) && (udev->setup.wLength != 0))
+    {
+      len = MIN(desc->length , udev->setup.wLength);
+      usbd_ctrl_send(udev, desc->descriptor, len);
+    }
+  }
+  return ret;
+}
+
+/**
+  * @brief  this request sets the device address
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_set_address(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  uint8_t dev_addr;
+
+  /* if wIndex or wLength are non-zero, then the behavior of
+     the device is not specified
+  */
+  if(setup->wIndex == 0 && setup->wLength == 0)
+  {
+    dev_addr = (uint8_t)(setup->wValue) & 0x7f;
+
+    /* device behavior when this request is received
+       while the device is in the configured state is not specified.*/
+    if(udev->conn_state == USB_CONN_STATE_CONFIGURED )
+    {
+      usbd_ctrl_unsupport(udev);
+    }
+    else
+    {
+      udev->device_addr = dev_addr;
+
+      if(dev_addr != 0)
+      {
+        udev->conn_state = USB_CONN_STATE_ADDRESSED;
+      }
+      else
+      {
+        udev->conn_state = USB_CONN_STATE_DEFAULT;
+      }
+      usbd_ctrl_send_status(udev);
+    }
+  }
+  else
+  {
+    usbd_ctrl_unsupport(udev);
+  }
+  return ret;
+}
+
+/**
+  * @brief  get usb status request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_get_status(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  switch(udev->conn_state)
+  {
+    case USB_CONN_STATE_ADDRESSED:
+    case USB_CONN_STATE_CONFIGURED:
+      if(udev->remote_wakup)
+      {
+        udev->config_status |= USB_CONF_REMOTE_WAKEUP;
+      }
+      usbd_ctrl_send(udev, (uint8_t *)(&udev->config_status), 2);
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  clear usb feature request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_clear_feature(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  switch(udev->conn_state)
+  {
+    case USB_CONN_STATE_ADDRESSED:
+    case USB_CONN_STATE_CONFIGURED:
+      if(setup->wValue == USB_FEATURE_REMOTE_WAKEUP)
+      {
+        udev->remote_wakup = 0;
+        udev->config_status &= ~USB_CONF_REMOTE_WAKEUP;
+        udev->class_handler->setup_handler(udev, &udev->setup);
+        usbd_ctrl_send_status(udev);
+      }
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  set usb feature request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_set_feature(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  if(setup->wValue == USB_FEATURE_REMOTE_WAKEUP)
+  {
+    udev->remote_wakup = 1;
+    udev->class_handler->setup_handler(udev, &udev->setup);
+    usbd_ctrl_send_status(udev);
+  }
+  return ret;
+}
+
+/**
+  * @brief  get usb configuration request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_get_configuration(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  if(setup->wLength != 1)
+  {
+    usbd_ctrl_unsupport(udev);
+  }
+  else
+  {
+    switch(udev->conn_state)
+    {
+      case USB_CONN_STATE_ADDRESSED:
+        udev->default_config = 0;
+        usbd_ctrl_send(udev, (uint8_t *)(&udev->default_config), 1);
+        break;
+      case USB_CONN_STATE_CONFIGURED:
+        usbd_ctrl_send(udev, (uint8_t *)(&udev->dev_config), 1);
+        break;
+      default:
+        usbd_ctrl_unsupport(udev);
+        break;
+    }
+  }
+  return ret;
+}
+
+/**
+  * @brief  sets the usb device configuration request
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+static usb_sts_type usbd_set_configuration(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  static uint8_t config_value;
+  usb_setup_type *setup = &udev->setup;
+  config_value = (uint8_t)setup->wValue;
+
+  if(setup->wIndex == 0 && setup->wLength == 0)
+  {
+    switch(udev->conn_state)
+    {
+      case USB_CONN_STATE_ADDRESSED:
+        if(config_value)
+        {
+          udev->dev_config = config_value;
+          udev->conn_state = USB_CONN_STATE_CONFIGURED;
+          udev->class_handler->init_handler(udev);
+          usbd_ctrl_send_status(udev);
+        }
+        else
+        {
+          usbd_ctrl_send_status(udev);
+        }
+
+        break;
+      case USB_CONN_STATE_CONFIGURED:
+        if(config_value == 0)
+        {
+          udev->conn_state = USB_CONN_STATE_ADDRESSED;
+          udev->dev_config = config_value;
+          udev->class_handler->clear_handler(udev);
+          usbd_ctrl_send_status(udev);
+        }
+        else if(config_value == udev->dev_config)
+        {
+          udev->class_handler->clear_handler(udev);
+          udev->dev_config = config_value;
+          udev->class_handler->init_handler(udev);
+          usbd_ctrl_send_status(udev);
+        }
+        else
+        {
+          usbd_ctrl_send_status(udev);
+        }
+        break;
+      default:
+        usbd_ctrl_unsupport(udev);
+        break;
+    }
+  }
+  else
+  {
+    usbd_ctrl_unsupport(udev);
+  }
+  return ret;
+}
+
+/**
+  * @brief  standard usb device requests
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+usb_sts_type usbd_device_request(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  if((setup->bmRequestType & USB_REQ_TYPE_RESERVED) != USB_REQ_TYPE_STANDARD)
+  {
+    udev->class_handler->setup_handler(udev, &udev->setup);
+    return ret;
+  }
+  switch(udev->setup.bRequest)
+  {
+    case USB_STD_REQ_GET_STATUS:
+      usbd_get_status(udev);
+      break;
+    case USB_STD_REQ_CLEAR_FEATURE:
+      usbd_clear_feature(udev);
+      break;
+    case USB_STD_REQ_SET_FEATURE:
+      usbd_set_feature(udev);
+      break;
+    case USB_STD_REQ_SET_ADDRESS:
+      usbd_set_address(udev);
+      break;
+    case USB_STD_REQ_GET_DESCRIPTOR:
+      usbd_get_descriptor(udev);
+      break;
+    case USB_STD_REQ_GET_CONFIGURATION:
+      usbd_get_configuration(udev);
+      break;
+    case USB_STD_REQ_SET_CONFIGURATION:
+      usbd_set_configuration(udev);
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  standard usb interface requests
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+usb_sts_type usbd_interface_request(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  switch(udev->conn_state)
+  {
+    case USB_CONN_STATE_CONFIGURED:
+      udev->class_handler->setup_handler(udev, &udev->setup);
+      if(setup->wLength == 0)
+      {
+        usbd_ctrl_send_status(udev);
+      }
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  standard usb endpoint requests
+  * @param  udev: to the structure of usbd_core_type
+  * @retval status of usb_sts_type
+  */
+usb_sts_type usbd_endpoint_request(usbd_core_type *udev)
+{
+  usb_sts_type ret = USB_OK;
+  usb_setup_type *setup = &udev->setup;
+  uint8_t ept_addr = LBYTE(setup->wIndex);
+  usb_ept_info *ept_info;
+
+  if((setup->bmRequestType & USB_REQ_TYPE_RESERVED) == USB_REQ_TYPE_CLASS)
+  {
+    udev->class_handler->setup_handler(udev, &udev->setup);
+  }
+  switch(setup->bRequest)
+  {
+    case USB_STD_REQ_GET_STATUS:
+      switch(udev->conn_state)
+      {
+        case USB_CONN_STATE_ADDRESSED:
+          if((ept_addr & 0x7F) != 0)
+          {
+            usbd_set_stall(udev, ept_addr);
+          }
+          break;
+        case USB_CONN_STATE_CONFIGURED:
+        {
+          if((ept_addr & 0x80) != 0)
+          {
+           ept_info = &udev->ept_in[ept_addr & 0x7F];
+          }
+          else
+          {
+            ept_info = &udev->ept_out[ept_addr & 0x7F];
+          }
+          if(ept_info->stall == 1)
+          {
+            ept_info->status = 0x0001;
+          }
+          else
+          {
+            ept_info->status = 0x0000;
+          }
+          usbd_ctrl_send(udev, (uint8_t *)(&ept_info->status), 2);
+        }
+          break;
+        default:
+          usbd_ctrl_unsupport(udev);
+          break;
+      }
+      break;
+    case USB_STD_REQ_CLEAR_FEATURE:
+      switch(udev->conn_state)
+      {
+        case USB_CONN_STATE_ADDRESSED:
+          if((ept_addr != 0x00) && (ept_addr != 0x80))
+          {
+            usbd_set_stall(udev, ept_addr);
+          }
+          break;
+        case USB_CONN_STATE_CONFIGURED:
+          if(setup->wValue == USB_FEATURE_EPT_HALT)
+          {
+            if((ept_addr & 0x7F) != 0x00 )
+            {
+              usbd_clear_stall(udev, ept_addr);
+              udev->class_handler->setup_handler(udev, &udev->setup);
+            }
+            usbd_ctrl_send_status(udev);
+          }
+          break;
+        default:
+          usbd_ctrl_unsupport(udev);
+          break;
+      }
+      break;
+    case USB_STD_REQ_SET_FEATURE:
+      switch(udev->conn_state)
+      {
+        case USB_CONN_STATE_ADDRESSED:
+          if((ept_addr != 0x00) && (ept_addr != 0x80))
+          {
+            usbd_set_stall(udev, ept_addr);
+          }
+          break;
+        case USB_CONN_STATE_CONFIGURED:
+          if(setup->wValue == USB_FEATURE_EPT_HALT)
+          {
+            if((ept_addr != 0x00) && (ept_addr != 0x80))
+            {
+              usbd_set_stall(udev, ept_addr);
+            }
+          }
+          udev->class_handler->setup_handler(udev, &udev->setup);
+          usbd_ctrl_send_status(udev);
+          break;
+        default:
+          usbd_ctrl_unsupport(udev);
+          break;
+      }
+      break;
+    default:
+      usbd_ctrl_unsupport(udev);
+      break;
+  }
+  return ret;
+}
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#endif

+ 1222 - 0
bsp/at32/libraries/usbfs_library/src/usbh_core.c

@@ -0,0 +1,1222 @@
+/**
+  **************************************************************************
+  * @file     usbh_core.c
+  * @brief    usb host driver
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+#include "usbh_core.h"
+#include "usb_core.h"
+#include "usbh_ctrl.h"
+
+/** @defgroup USBH_drivers_core
+  * @brief usb host drivers core
+  * @{
+  */
+
+/** @defgroup USBH_core_private_functions
+  * @{
+  */
+
+static void usbh_attached(usbh_core_type *uhost);
+static void usbh_enumeration(usbh_core_type *uhost);
+static void usbh_class_request(usbh_core_type *uhost);
+static void usbh_class(usbh_core_type *uhost);
+static void usbh_suspend(usbh_core_type *uhost);
+static void usbh_wakeup(usbh_core_type *uhost);
+static void usbh_disconnect(usbh_core_type *uhost);
+/**
+  * @brief  usb host free channel
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  index: channle number
+  * @retval none
+  */
+void usbh_free_channel(usbh_core_type *uhost, uint8_t index)
+{
+  if(index < USB_HOST_CHANNEL_NUM)
+  {
+    /* free host channel */
+    uhost->channel[index] = 0x0;
+  }
+}
+
+/**
+  * @brief  get usb host free channel
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval channel index
+  */
+uint16_t usbh_get_free_channel(usbh_core_type *uhost)
+{
+  uint16_t i_index = 0;
+  for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
+  {
+    /* find unuse channel */
+    if((uhost->channel[i_index] & HCH_USED) == 0)
+    {
+      /* return channel index */
+      return i_index;
+    }
+  }
+  return HCH_ERROR;
+}
+
+
+/**
+  * @brief  usb host set toggle
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  hc_num: channel number
+  * @param  toggle: toggle value
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_set_toggle(usbh_core_type *uhost, uint8_t hc_num, uint8_t toggle)
+{
+  if(uhost->hch[hc_num].dir)
+  {
+    /* direction in */
+    uhost->hch[hc_num].toggle_in = toggle;
+  }
+  else
+  {
+    /* direction out */
+    uhost->hch[hc_num].toggle_out = toggle;
+  }
+  return USB_OK;
+}
+
+/**
+  * @brief  usb host in out request
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  hc_num: channel number
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_in_out_request(usbh_core_type *uhost, uint8_t hc_num)
+{
+  usb_sts_type status = USB_OK;
+  uint32_t n_packet = 0;
+  uint32_t num_words = 0;
+  uint32_t tmp;
+  otg_global_type *usbx = uhost->usb_reg;
+  otg_hchannel_type *ch = USB_CHL(uhost->usb_reg, hc_num);
+
+  /* set usb request block to idle */
+  uhost->urb_state[hc_num] = URB_IDLE;
+  uhost->hch[hc_num].state = HCH_IDLE;
+
+  /* set usb channel transmit count to zero */
+  uhost->hch[hc_num].trans_count = 0;
+
+  /* check transmit data len */
+  if(uhost->hch[hc_num].trans_len > 0)
+  {
+    /* count how many packet need to send */
+    n_packet = (uhost->hch[hc_num].trans_len + \
+               uhost->hch[hc_num].maxpacket - 1) / \
+               uhost->hch[hc_num].maxpacket;
+
+    /* packet count max 256 */
+    if(n_packet > 256)
+    {
+      n_packet = 256;
+      uhost->hch[hc_num].trans_len = n_packet * uhost->hch[hc_num].maxpacket;
+    }
+  }
+  else
+  {
+    /* zero data len */
+    n_packet = 1;
+  }
+
+  /* direction is in */
+  if(uhost->hch[hc_num].dir)
+  {
+    uhost->hch[hc_num].trans_len = n_packet * uhost->hch[hc_num].maxpacket;
+  }
+
+  /* set transfer information to channel register */
+  ch->hctsiz = (uhost->hch[hc_num].trans_len & USB_OTG_HCTSIZ_XFERSIZE) |
+               ((n_packet << 19) & USB_OTG_HCTSIZ_PKTCNT) |
+               ((uhost->hch[hc_num].data_pid << 29) & USB_OTG_HCTSIZ_PID);
+
+  /* set odd frame */
+  ch->hcchar_bit.oddfrm = !(OTG_HOST(uhost->usb_reg)->hfnum & 0x1);
+
+  /* clear channel disable bit and enable channel */
+  tmp = ch->hcchar;
+  tmp &= ~(USB_OTG_HCCHAR_CHDIS);
+  tmp |= USB_OTG_HCCHAR_CHENA;
+  ch->hcchar = tmp;
+
+  /* channel direction is out and transfer len > 0 */
+  if((uhost->hch[hc_num].dir == 0) &&
+    (uhost->hch[hc_num].trans_len > 0 ))
+  {
+    switch(uhost->hch[hc_num].ept_type)
+    {
+      case EPT_CONTROL_TYPE:
+      case EPT_BULK_TYPE:
+        num_words = (uhost->hch[hc_num].trans_len + 3) / 4;
+
+        /* non-periodic transfer */
+        if(num_words > usbx->gnptxsts_bit.nptxfspcavail)
+        {
+          usbx->gintmsk_bit.nptxfempmsk = 1;
+        }
+        break;
+      case EPT_ISO_TYPE:
+      case EPT_INT_TYPE:
+        num_words = (uhost->hch[hc_num].trans_len + 3) / 4;
+
+        /* periodic transfer */
+        if(num_words > OTG_HOST(usbx)->hptxsts_bit.ptxfspcavil)
+        {
+          usbx->gintmsk_bit.ptxfempmsk = 1;
+        }
+        break;
+      default:
+        break;
+    }
+    /* write data to fifo */
+    usb_write_packet(usbx, uhost->hch[hc_num].trans_buf,
+                    hc_num, uhost->hch[hc_num].trans_len);
+  }
+
+  return status;
+}
+
+/**
+  * @brief  usb host interrupt receive request
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  hc_num: channel number
+  * @param  buffer: receive buffer
+  * @param  length: receive length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_interrupt_recv(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length)
+{
+  /* set direction is in */
+  uhost->hch[hc_num].dir = 1;
+
+  /* set transfer buffer */
+  uhost->hch[hc_num].trans_buf = buffer;
+
+  /* set transfer len*/
+  uhost->hch[hc_num].trans_len = length;
+
+  if(uhost->hch[hc_num].toggle_in == 0)
+  {
+    /* pid: data0 */
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
+  }
+  else
+  {
+    /* pid: data1 */
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
+  }
+
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+/**
+  * @brief  usb host interrupt send request
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  hc_num: channel number
+  * @param  buffer: send buffer
+  * @param  length: send length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_interrupt_send(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length)
+{
+  /* set direction is out */
+  uhost->hch[hc_num].dir = 0;
+
+  /* set transfer buffer */
+  uhost->hch[hc_num].trans_buf = buffer;
+
+  /* set transfer len*/
+  uhost->hch[hc_num].trans_len = length;
+
+  if(uhost->hch[hc_num].toggle_out == 0)
+  {
+    /* pid: data0 */
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
+  }
+  else
+  {
+    /* pid: data1 */
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
+  }
+
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+
+/**
+  * @brief  usb host bulk receive request
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  hc_num: channel number
+  * @param  buffer: receive buffer
+  * @param  length: receive length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_bulk_recv(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length)
+{
+  /* set direction is in */
+  uhost->hch[hc_num].dir = 1;
+
+  /* set transfer buffer */
+  uhost->hch[hc_num].trans_buf = buffer;
+
+  /* set transfer len*/
+  uhost->hch[hc_num].trans_len = length;
+
+  if(uhost->hch[hc_num].toggle_in == 0)
+  {
+    /* pid: data0 */
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
+  }
+  else
+  {
+    /* pid: data1 */
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
+  }
+
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+
+/**
+  * @brief  usb host bulk send request
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  hc_num: channel number
+  * @param  buffer: receive buffer
+  * @param  length: receive length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_bulk_send(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length)
+{
+  /* set direction is out */
+  uhost->hch[hc_num].dir = 0;
+
+  /* set transfer buffer */
+  uhost->hch[hc_num].trans_buf = buffer;
+
+  /* set transfer len*/
+  uhost->hch[hc_num].trans_len = length;
+
+  if(uhost->hch[hc_num].toggle_out == 0)
+  {
+    /* pid: data0 */
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
+  }
+  else
+  {
+    /* pid: data1 */
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
+  }
+
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+
+/**
+  * @brief  usb host iso send request
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  hc_num: channel number
+  * @param  buffer: send buffer
+  * @param  length: send length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_isoc_send(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length)
+{
+  /* set direction is out */
+  uhost->hch[hc_num].dir = 0;
+
+  /* set transfer buffer */
+  uhost->hch[hc_num].trans_buf = buffer;
+
+  /* set transfer len*/
+  uhost->hch[hc_num].trans_len = length;
+
+  /* pid: data0 */
+  uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
+
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+/**
+  * @brief  usb host iso receive request
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  hc_num: channel number
+  * @param  buffer: receive buffer
+  * @param  length: receive length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_isoc_recv(usbh_core_type *uhost, uint8_t hc_num,
+                            uint8_t *buffer, uint16_t length)
+{
+  /* set direction is in */
+  uhost->hch[hc_num].dir = 1;
+
+  /* set transfer buffer */
+  uhost->hch[hc_num].trans_buf = buffer;
+
+  /* set transfer len*/
+  uhost->hch[hc_num].trans_len = length;
+
+  /* pid: data0 */
+  uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
+
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+/**
+  * @brief  usb host cfg default init
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_cfg_default_init(usbh_core_type *uhost)
+{
+  /* set global state to idle */
+  uhost->global_state = USBH_IDLE;
+
+  /* enumeration state to get description */
+  uhost->enum_state = ENUM_GET_MIN_DESC;
+
+  /* request state send */
+  uhost->req_state = CMD_SEND;
+
+  /* control transfer state is idle*/
+  uhost->ctrl.state = CONTROL_IDLE;
+
+  /* defaut endpoint 0 max size is 8byte */
+  uhost->ctrl.ept0_size = 8;
+
+  /* default device address is 0 */
+  uhost->dev.address = 0;
+
+  /* default speed is full speed */
+  uhost->dev.speed = USB_FULL_SPEED_CORE_ID;
+
+  uhost->timer = 0;
+
+  uhost->ctrl.err_cnt = 0;
+
+  /* free all channel */
+  usbh_free_channel(uhost, uhost->ctrl.hch_in);
+  usbh_free_channel(uhost, uhost->ctrl.hch_out);
+  return USB_OK;
+}
+
+/**
+  * @brief  usb host enter suspend
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+void usbh_enter_suspend(usbh_core_type *uhost)
+{
+  otg_host_type *host = OTG_HOST(uhost->usb_reg);
+  uint32_t hprt_val = host->hprt;
+
+  hprt_val &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
+               USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET);
+
+  /* set port suspend */
+  host->hprt = hprt_val | USB_OTG_HPRT_PRTSUSP;
+
+  /* stop phy clock */
+  usb_stop_phy_clk(uhost->usb_reg);
+
+}
+
+/**
+  * @brief  usb host resume
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+void usbh_resume(usbh_core_type *uhost)
+{
+  otg_host_type *host = OTG_HOST(uhost->usb_reg);
+  uint32_t temp = host->hprt;
+
+  /* open phy clock */
+  usb_open_phy_clk(uhost->usb_reg);
+
+  /* clear port suspend and set port resume*/
+  temp &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
+           USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET
+           | USB_OTG_HPRT_PRTSUSP);
+  host->hprt = temp | USB_OTG_HPRT_PRTRES;
+
+  /* delay 20 ms */
+  rt_thread_mdelay(20);
+
+  /*clear port resume */
+  temp = host->hprt;
+  temp &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
+           USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET
+           | USB_OTG_HPRT_PRTRES);
+  host->hprt = temp;
+  rt_thread_mdelay(5);
+}
+
+/**
+  * @brief  usb host core initialize
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  usb_reg: usb otgfs peripheral global register
+  *         this parameter can be one of the following values:
+  *         OTG1_GLOBAL , OTG2_GLOBAL
+  * @param  class_handler: usb host class handler type pointer
+  * @param  user_handler: usb host user handler type pointer
+  * @param  core_id: usb core select id
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_core_init(usbh_core_type *uhost,
+                            usb_reg_type *usb_reg,
+                            uint8_t core_id)
+{
+  usb_sts_type status = USB_OK;
+  uint32_t i_index;
+  otg_global_type *usbx = usb_reg;
+  otg_host_type *host =  OTG_HOST(usbx);
+  uhost->usb_reg = usb_reg;
+
+  uhost->timer = 0;
+
+  /* usb host cfg default init */
+  usbh_cfg_default_init(uhost);
+
+  /* clear host config to default value */
+  for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
+  {
+    uhost->err_cnt[i_index] = 0;
+    uhost->xfer_cnt[i_index] = 0;
+    uhost->hch_state[i_index] = HCH_IDLE;
+    uhost->hch[0].maxpacket = 8;
+  }
+
+  /* no device connect */
+  uhost->conn_sts = 0;
+
+  /* disable usb interrupt */
+  usb_interrupt_disable(usbx);
+
+  /* usb global init */
+  usb_global_init(usbx);
+
+  /* set usb host mode */
+  usb_global_set_mode(usbx, OTG_HOST_MODE);
+
+  /* open usb phy clock*/
+  usb_open_phy_clk(usbx);
+
+  /* clock select */
+  usbh_fsls_clksel(usbx, USB_HCFG_CLK_48M);
+
+  /* set support ls and fs device */
+  host->hcfg_bit.fslssupp = 0;
+
+  if(usbx == OTG1_GLOBAL)
+  {
+    /* set receive fifo size */
+    usbx->grxfsiz = USBH_RX_FIFO_SIZE;
+
+    /* set non-periodic transmit fifo start address and depth */
+    usbx->gnptxfsiz_ept0tx_bit.nptxfstaddr = USBH_RX_FIFO_SIZE;
+    usbx->gnptxfsiz_ept0tx_bit.nptxfdep = USBH_NP_TX_FIFO_SIZE;
+
+    /* set periodic transmit fifo start address and depth */
+    usbx->hptxfsiz_bit.ptxfstaddr = USBH_RX_FIFO_SIZE + USBH_NP_TX_FIFO_SIZE;
+    usbx->hptxfsiz_bit.ptxfsize = USBH_P_TX_FIFO_SIZE;
+  }
+#ifdef OTG2_GLOBAL
+  if(usbx == OTG2_GLOBAL)
+  {
+    /* set receive fifo size */
+    usbx->grxfsiz = USBH2_RX_FIFO_SIZE;
+
+    /* set non-periodic transmit fifo start address and depth */
+    usbx->gnptxfsiz_ept0tx_bit.nptxfstaddr = USBH2_RX_FIFO_SIZE;
+    usbx->gnptxfsiz_ept0tx_bit.nptxfdep = USBH2_NP_TX_FIFO_SIZE;
+
+    /* set periodic transmit fifo start address and depth */
+    usbx->hptxfsiz_bit.ptxfstaddr = USBH2_RX_FIFO_SIZE + USBH2_NP_TX_FIFO_SIZE;
+    usbx->hptxfsiz_bit.ptxfsize = USBH2_P_TX_FIFO_SIZE;
+  }
+#endif
+  /* flush tx fifo */
+  usb_flush_tx_fifo(usbx, 16);
+
+  /* flush rx fifo */
+  usb_flush_rx_fifo(usbx);
+
+  /* clear host channel interrut mask and status */
+  for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
+  {
+    USB_CHL(usbx, i_index)->hcintmsk = 0;
+    USB_CHL(usbx, i_index)->hcint = 0xFFFFFFFF;
+  }
+
+  /* power on to this port */
+  usb_port_power_on(usbx, TRUE);
+
+  /* clear global interrupt mask and status */
+  usbx->gintmsk = 0;
+  usbx->gintsts = 0xBFFFFFFF;
+
+  /* set global interrut mask */
+  usbx->gintmsk = USB_OTG_SOF_INT | USB_OTG_RXFLVL_INT |
+                  USB_OTG_USBSUSP_INT | USB_OTG_PRT_INT |
+                   USB_OTG_HCH_INT | USB_OTG_INCOMISOIN_INT |
+                  USB_OTG_INCOMPIP_INCOMPISOOUT_INT | USB_OTG_WKUP_INT |
+                  USB_OTG_DISCON_INT;
+
+  /* enable usb global interrupt */
+  usb_interrupt_enable(usbx);
+
+  /* active vbus */
+  usbh_active_vbus(uhost, TRUE);
+  return status;
+}
+
+/**
+  * @brief  usb host open channel
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  chn: host channel number
+  * @param  ept_num: devvice endpoint number
+  * @param  dev_address: device address
+  * @param  type: channel transfer type
+  *         this parameter can be one of the following values:
+  *         - EPT_CONTROL_TYPE
+  *         - EPT_BULK_TYPE
+  *         - EPT_INT_TYPE
+  *         - EPT_ISO_TYPE
+  * @param  maxpacket: support max packe size for this channel
+  * @param  speed: device speed
+  *         this parameter can be one of the following values:
+  *         - USB_PRTSPD_FULL_SPEED
+  *         - USB_PRTSPD_LOW_SPEED
+  * @param  ept_addr: endpoint address
+  * @retval usb_sts_type
+  */
+void usbh_hc_open(usbh_core_type *uhost,
+                   uint8_t chn,
+                   uint8_t ept_num,
+                   uint8_t dev_address,
+                   uint8_t type,
+                   uint16_t maxpacket,
+                   uint8_t speed)
+{
+  /* device address */
+  uhost->hch[chn].address = dev_address;
+
+  /* device speed */
+  uhost->hch[chn].speed = speed;
+
+  /* endpoint transfer type */
+  uhost->hch[chn].ept_type = type;
+
+  /* endpoint support maxpacket */
+  uhost->hch[chn].maxpacket = maxpacket;
+
+  /* endpoint direction in or out */
+  uhost->hch[chn].dir = (ept_num & 0x80)?1:0;;
+
+  /* host channel number */
+  uhost->hch[chn].ch_num = chn;
+
+  /* device endpoint number */
+  uhost->hch[chn].ept_num = ept_num;
+
+  /* enable channel */
+  usb_hc_enable(uhost->usb_reg, chn,
+                ept_num, dev_address,
+                type, maxpacket, speed
+           );
+}
+
+/**
+  * @brief  disable host channel
+  * @param  usbx: to select the otgfs peripheral.
+  *         this parameter can be one of the following values:
+  *         - OTG1_GLOBAL
+  *         - OTG2_GLOBAL
+  * @param  chn: channel number
+  * @retval none
+  */
+void usbh_ch_disable(usbh_core_type *uhost, uint8_t chn)
+{
+  usb_hch_halt(uhost->usb_reg, chn);
+}
+
+/**
+  * @brief  usb host alloc channel
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  ept_addr: endpoint address
+  * @retval usb_sts_type
+  */
+uint16_t usbh_alloc_channel(usbh_core_type *uhost, uint8_t ept_addr)
+{
+  /* get one free channel */
+  uint16_t ch_num = usbh_get_free_channel(uhost);
+
+  if(ch_num == HCH_ERROR)
+    return USB_FAIL;
+
+  /* set channel to used */
+  uhost->channel[ch_num] = HCH_USED | ept_addr;
+  return ch_num;
+}
+
+hch_sts_type usbh_get_status(usbh_core_type *uhost, uint8_t ch_num)
+{
+   return uhost->hch_state[ch_num];
+}
+
+/**
+  * @brief  usb host get urb status
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  ch_num: channel number
+  * @retval urb_sts_type: urb status
+  */
+urb_sts_type usbh_get_urb_status(usbh_core_type *uhost, uint8_t ch_num)
+{
+  return uhost->urb_state[ch_num];
+}
+/**
+  * @brief  usb wait control setup complete
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  next_ctrl_state: next ctrl state when setup complete
+  * @param  next_enum_state: next enum state when setup complete
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_result_check(usbh_core_type *uhost, ctrl_ept0_sts_type next_ctrl_state, uint8_t next_enum_state)
+{
+  usb_sts_type status;
+
+  /* control transfer loop */
+  status = usbh_ctrl_transfer_loop(uhost);
+
+  if(status == USB_OK)
+  {
+    uhost->ctrl.state = next_ctrl_state;
+    uhost->enum_state = next_enum_state;
+    uhost->req_state = CMD_SEND;
+  }
+  else if(status == USB_ERROR)
+  {
+    uhost->ctrl.state = CONTROL_IDLE;
+    uhost->req_state = CMD_SEND;
+  }
+  else if(status == USB_NOT_SUPPORT)
+  {
+    uhost->ctrl.state = next_ctrl_state;
+    uhost->enum_state = next_enum_state;
+    uhost->req_state = CMD_SEND;
+  }
+  return status;
+}
+
+/**
+  * @brief  auto alloc address (1...20)
+  * @param  none
+  * @retval address (1...20)
+  */
+uint8_t usbh_alloc_address(void)
+{
+  static uint8_t address = 1;
+  if(address == 20)
+    address = 1;
+  return address ++;
+}
+
+
+/**
+  * @brief  usb host enumeration handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_enum_handler(usbh_core_type *uhost)
+{
+  usb_sts_type status = USB_WAIT;
+  switch(uhost->enum_state)
+  {
+    case ENUM_IDLE:
+      break;
+    case ENUM_GET_MIN_DESC:
+      /* get description */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        usbh_get_device_descriptor(uhost, 8);
+      }
+      if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_FULL_DESC) == USB_OK)
+      {
+        usbh_parse_dev_desc(uhost, uhost->rx_buffer, 8);
+
+        /* set new control endpoint maxpacket size */
+        uhost->ctrl.ept0_size = (uhost->dev).dev_desc.bMaxPacketSize0;
+
+        /* enable channel */
+        usbh_hc_open(uhost, uhost->ctrl.hch_in,0x80,
+                      uhost->dev.address, EPT_CONTROL_TYPE,
+                      uhost->ctrl.ept0_size,
+                      uhost->dev.speed);
+
+        /* enable channel */
+        usbh_hc_open(uhost, uhost->ctrl.hch_out,0x00,
+                      uhost->dev.address, EPT_CONTROL_TYPE,
+                      uhost->ctrl.ept0_size,
+                      uhost->dev.speed);
+      }
+      break;
+
+    case ENUM_GET_FULL_DESC:
+      /* get description */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        usbh_get_device_descriptor(uhost, 18);
+      }
+      if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_SET_ADDR) == USB_OK)
+      {
+        usbh_parse_dev_desc(uhost, uhost->rx_buffer, 18);
+      }
+      break;
+
+    case ENUM_SET_ADDR:
+      /* set device address */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        uhost->dev.address = usbh_alloc_address();
+        usbh_set_address(uhost, uhost->dev.address);
+      }
+      if (usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_CFG) == USB_OK)
+      {
+        /* enable channel */
+        usbh_hc_open(uhost, uhost->ctrl.hch_in,0x80,
+                      uhost->dev.address, EPT_CONTROL_TYPE,
+                      uhost->ctrl.ept0_size,
+                      uhost->dev.speed);
+
+        /* enable channel */
+        usbh_hc_open(uhost, uhost->ctrl.hch_out,0x00,
+                      uhost->dev.address, EPT_CONTROL_TYPE,
+                      uhost->ctrl.ept0_size,
+                      uhost->dev.speed);
+      }
+      break;
+
+    case ENUM_GET_CFG:
+      /* get device confiuration */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        usbh_get_configure_descriptor(uhost, 9);
+      }
+
+      if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_FULL_CFG) == USB_OK)
+      {
+        usbh_parse_configure_desc(uhost, uhost->rx_buffer, 9);
+      }
+      break;
+
+    case ENUM_GET_FULL_CFG:
+      /* get device confiuration */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        usbh_get_configure_descriptor(uhost, uhost->dev.cfg_desc.cfg.wTotalLength);
+      }
+
+      if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_MFC_STRING) == USB_OK)
+      {
+        usbh_parse_configure_desc(uhost, uhost->rx_buffer, uhost->dev.cfg_desc.cfg.wTotalLength);
+      }
+      break;
+
+    case ENUM_GET_MFC_STRING:
+      /* get device mfc string */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        usbh_get_sting_descriptor(uhost, uhost->dev.dev_desc.iManufacturer,
+                                  uhost->rx_buffer, 0xFF);
+      }
+
+      if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_PRODUCT_STRING) == USB_OK)
+      {
+        usbh_parse_string_desc(uhost->rx_buffer, uhost->rx_buffer, 0xFF);
+        uhost->user_handler->user_mfc_string(uhost->rx_buffer);
+      }
+      break;
+
+    case ENUM_GET_PRODUCT_STRING:
+      /* get device product string */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        usbh_get_sting_descriptor(uhost, uhost->dev.dev_desc.iProduct,
+                                  uhost->rx_buffer, 0xFF);
+      }
+
+      if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_GET_SERIALNUM_STRING) == USB_OK)
+      {
+        usbh_parse_string_desc(uhost->rx_buffer, uhost->rx_buffer, 0xFF);
+        uhost->user_handler->user_product_string(uhost->rx_buffer);
+      }
+      break;
+
+    case ENUM_GET_SERIALNUM_STRING:
+      /* get device serial string */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        usbh_get_sting_descriptor(uhost, uhost->dev.dev_desc.iSerialNumber,
+                                  uhost->rx_buffer, 0xFF);
+      }
+
+      if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_SET_CONFIG) == USB_OK)
+      {
+        usbh_parse_string_desc(uhost->rx_buffer, uhost->rx_buffer, 0xFF);
+        uhost->user_handler->user_serial_string(uhost->rx_buffer);
+      }
+      break;
+
+    case ENUM_SET_CONFIG:
+      /* set device config */
+      if(uhost->ctrl.state == CONTROL_IDLE)
+      {
+        usbh_set_configuration(uhost, uhost->dev.cfg_desc.cfg.bConfigurationValue);
+      }
+      usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_COMPLETE);
+
+      break;
+
+    case ENUM_COMPLETE:
+      /* enum complete */
+      status = USB_OK;
+      break;
+    default:
+      break;
+  }
+  return status;
+}
+
+/**
+  * @brief  active vbus.
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  state: vbus state
+  * @retval none
+  */
+void usbh_active_vbus(usbh_core_type *uhost, confirm_state state)
+{
+}
+
+/**
+  * @brief  reset usb port
+  * @param  usbx: to the structure of otg_global_type
+  * @retval none
+  */
+void usbh_reset_port(usbh_core_type *uhost)
+{
+  otg_host_type *usb_host = OTG_HOST(uhost->usb_reg);
+  uint32_t hprt_val = usb_host->hprt;
+
+  hprt_val &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
+               USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET);
+
+  /* set port reset */
+  usb_host->hprt = hprt_val | USB_OTG_HPRT_PRTRST;
+
+  rt_thread_mdelay(100);
+
+  /* clear port reset */
+  usb_host->hprt = hprt_val & (~USB_OTG_HPRT_PRTRST);
+
+  rt_thread_mdelay(20);
+}
+
+/**
+  * @brief  usb host attached
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+static void usbh_attached(usbh_core_type *uhost)
+{
+  /* get free channel */
+  uhost->ctrl.hch_in = usbh_alloc_channel(uhost, 0x80);
+  uhost->ctrl.hch_out = usbh_alloc_channel(uhost, 0x00);
+
+  /* user reset callback handler */
+  uhost->user_handler->user_reset();
+
+  /* get device speed */
+  uhost->dev.speed = OTG_HOST(uhost->usb_reg)->hprt_bit.prtspd;
+  uhost->global_state  = USBH_ENUMERATION;
+  uhost->user_handler->user_speed(uhost->dev.speed);
+
+  /* enable channel */
+  usbh_hc_open(uhost, uhost->ctrl.hch_in,0x80,
+                uhost->dev.address, EPT_CONTROL_TYPE,
+                uhost->ctrl.ept0_size,
+                uhost->dev.speed);
+
+  /* enable channel */
+  usbh_hc_open(uhost, uhost->ctrl.hch_out,0x00,
+                uhost->dev.address, EPT_CONTROL_TYPE,
+                uhost->ctrl.ept0_size,
+                uhost->dev.speed);
+
+  usb_flush_tx_fifo(uhost->usb_reg, 0x10);
+  usb_flush_rx_fifo(uhost->usb_reg);
+
+  /* user attached callback */
+  uhost->user_handler->user_attached();
+}
+
+
+/**
+  * @brief  usb host enumeration
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+static void usbh_enumeration(usbh_core_type *uhost)
+{
+  /* enumeration process */
+  if(usbh_enum_handler(uhost) == USB_OK)
+  {
+    /* user enumeration done callback */
+    uhost->user_handler->user_enumeration_done();
+    uhost->global_state  = USBH_USER_HANDLER;
+  }
+}
+
+/**
+  * @brief  usb host class request
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+static void usbh_class_request(usbh_core_type *uhost)
+{
+  usb_sts_type status;
+
+  /* class request callback */
+  status = uhost->class_handler->request_handler((void *)uhost);
+  if(status == USB_OK)
+  {
+    uhost->global_state = USBH_CLASS;
+  }
+  else if(status == USB_ERROR || status == USB_FAIL)
+  {
+    uhost->global_state = USBH_ERROR_STATE;
+  }
+  else if(status == USB_NOT_SUPPORT)
+  {
+    uhost->global_state = USBH_ERROR_STATE;
+  }
+}
+
+/**
+  * @brief  usb host class handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+static void usbh_class(usbh_core_type *uhost)
+{
+  /* process handler */
+  if(uhost->class_handler->process_handler((void *)uhost) == USB_OK)
+  {
+  }
+}
+
+/**
+  * @brief  usb host suspend
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+static void usbh_suspend(usbh_core_type *uhost)
+{
+  /* set device feature */
+  if(uhost->ctrl.state == CONTROL_IDLE)
+  {
+    usbh_set_feature(uhost, 0x01, 0);
+  }
+  if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
+  {
+    /* enter suspend mode */
+    rt_thread_mdelay(3);
+    usbh_enter_suspend(uhost);
+    uhost->global_state = USBH_SUSPENDED;
+
+  }
+}
+
+/**
+  * @brief  usb host wakeup
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+static void usbh_wakeup(usbh_core_type *uhost)
+{
+  /* clear device feature */
+  if(uhost->ctrl.state == CONTROL_IDLE)
+  {
+   /* usb host resume */
+    usbh_resume(uhost);
+    usbh_clear_dev_feature(uhost, 0x01, 0);
+  }
+  if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
+  {
+    uhost->global_state = USBH_CLASS_REQUEST;
+  }
+}
+
+/**
+  * @brief  usb host disconnect
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+static void usbh_disconnect(usbh_core_type *uhost)
+{
+  uint8_t i_index = 0;
+
+  /* set host to default state */
+  usbh_cfg_default_init(uhost);
+
+  /* free host channel */
+  for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
+  {
+    usbh_free_channel(uhost, i_index);
+  }
+
+  /* call class reset handler */
+  if(uhost->class_handler->reset_handler != NULL)
+  {
+    uhost->class_handler->reset_handler(uhost);
+  }
+
+  /* set global state to idle */
+  uhost->global_state = USBH_IDLE;
+
+  /*call user disconnect function */
+  uhost->user_handler->user_disconnect();
+}
+
+
+/**
+  * @brief  usb host enum loop handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+usb_sts_type usbh_loop_handler(usbh_core_type *uhost)
+{
+  usb_sts_type status = USB_FAIL;
+
+  if(uhost->conn_sts == 0 &&
+      uhost->global_state != USBH_IDLE &&
+      uhost->global_state != USBH_DISCONNECT)
+  {
+    uhost->global_state  = USBH_IDLE;
+  }
+  switch(uhost->global_state)
+  {
+    case USBH_IDLE:
+      if(uhost->conn_sts == 1)
+      {
+        uhost->global_state  = USBH_PORT_EN;
+
+        /* wait stable */
+        rt_thread_mdelay(200);
+
+        /* port reset */
+        usbh_reset_port(uhost);
+
+        /* user reset */
+        uhost->user_handler->user_reset();
+      }
+      break;
+
+    case USBH_PORT_EN:
+      if(uhost->port_enable)
+      {
+        uhost->global_state  = USBH_ATTACHED;
+        rt_thread_mdelay(50);
+      }
+      break;
+
+    case USBH_ATTACHED:
+      usbh_attached(uhost);
+      break;
+
+    case USBH_ENUMERATION:
+      usbh_enumeration(uhost);
+      break;
+
+    case USBH_USER_HANDLER:
+      uhost->global_state  = USBH_CLASS_REQUEST;
+      if( uhost->class_handler->init_handler(uhost) == USB_NOT_SUPPORT)
+      {
+        uhost->global_state = USBH_UNSUPPORT;
+      }
+      break;
+
+    case USBH_CLASS_REQUEST:
+      usbh_class_request(uhost);
+      break;
+
+    case USBH_CLASS:
+      usbh_class(uhost);
+      break;
+
+    case USBH_SUSPEND:
+      usbh_suspend(uhost);
+      break;
+
+    case USBH_SUSPENDED:
+      break;
+
+    case USBH_WAKEUP:
+      usbh_wakeup(uhost);
+      break;
+
+    case USBH_DISCONNECT:
+      usbh_disconnect(uhost);
+      break;
+
+    case USBH_ERROR_STATE:
+      usbh_cfg_default_init(uhost);
+      uhost->class_handler->reset_handler(uhost);
+      uhost->user_handler->user_reset();
+      break;
+    case USBH_UNSUPPORT:
+      break;
+    default:
+      break;
+  }
+
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 958 - 0
bsp/at32/libraries/usbfs_library/src/usbh_ctrl.c

@@ -0,0 +1,958 @@
+/**
+  **************************************************************************
+  * @file     usbh_ctrl.c
+  * @brief    usb host control request
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+#include "usbh_ctrl.h"
+#include "usbh_core.h"
+#include "usb_std.h"
+
+/** @defgroup USBH_drivers_control
+  * @brief usb host drivers control
+  * @{
+  */
+
+/** @defgroup USBH_ctrl_private_functions
+  * @{
+  */
+
+/* control timeout 5s */
+#define CTRL_TIMEOUT          5000
+
+/**
+  * @brief  usb host control send setup packet
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  buffer: usb control setup send buffer
+  * @param  hc_num: channel number
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_send_setup(usbh_core_type *uhost, uint8_t *buffer, uint8_t hc_num)
+{
+  uhost->hch[hc_num].dir = 0;
+  uhost->hch[hc_num].data_pid = HCH_PID_SETUP;
+  uhost->hch[hc_num].trans_buf = buffer;
+  uhost->hch[hc_num].trans_len = 8; /*setup */
+
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+/**
+  * @brief  usb host control receive data from device
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  buffer: usb control receive data buffer
+  * @param  length: usb control receive data length
+  * @param  hc_num: channel number
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_recv_data(usbh_core_type *uhost, uint8_t *buffer,
+                            uint16_t length, uint16_t hc_num)
+{
+  uhost->hch[hc_num].dir = 1;
+  uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
+  uhost->hch[hc_num].trans_buf = buffer;
+  uhost->hch[hc_num].trans_len = length;
+
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+/**
+  * @brief  usb host control send data packet
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  buffer: usb control send data buffer
+  * @param  length: usb control send data length
+  * @param  hc_num: channel number
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_send_data(usbh_core_type *uhost, uint8_t *buffer,
+                            uint16_t length, uint16_t hc_num)
+{
+  uhost->hch[hc_num].dir = 0;
+  uhost->hch[hc_num].trans_buf = buffer;
+  uhost->hch[hc_num].trans_len = length;
+
+  if(length == 0)
+  {
+    uhost->hch[uhost->ctrl.hch_out].toggle_out = 1;
+  }
+  if(uhost->hch[uhost->ctrl.hch_out].toggle_out == 0)
+  {
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA0;
+  }
+  else
+  {
+    uhost->hch[hc_num].data_pid = HCH_PID_DATA1;
+  }
+  return usbh_in_out_request(uhost, hc_num);
+}
+
+/**
+  * @brief  usb host control setup request handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_setup_handler(usbh_core_type *uhost)
+{
+  usbh_ctrl_send_setup(uhost, (uint8_t *)(&uhost->ctrl.setup),
+                       uhost->ctrl.hch_out);
+  uhost->ctrl.state = CONTROL_SETUP_WAIT;
+  return USB_OK;
+}
+
+/**
+  * @brief  usb host control setup request wait handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  timeout: pointer of wait timeout
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_setup_wait_handler(usbh_core_type *uhost, uint32_t *timeout)
+{
+  urb_sts_type urb_state;
+  usb_sts_type status = USB_WAIT;
+  uint8_t dir;
+  urb_state = uhost->urb_state[uhost->ctrl.hch_out];
+  if(urb_state == URB_DONE)
+  {
+    dir = uhost->ctrl.setup.bmRequestType &  USB_REQUEST_DIR_MASK;
+    if(uhost->ctrl.setup.wLength != 0)
+    {
+      *timeout = DATA_STAGE_TIMEOUT;
+      if(dir == USB_DIR_D2H) //in
+      {
+        uhost->ctrl.state = CONTROL_DATA_IN;
+      }
+      else //out
+      {
+        uhost->ctrl.state = CONTROL_DATA_OUT;
+      }
+    }
+    else
+    {
+      *timeout = NODATA_STAGE_TIMEOUT;
+      if(dir == USB_DIR_D2H) //no data, send status
+      {
+        uhost->ctrl.state = CONTROL_STATUS_OUT;
+      }
+      else //out
+      {
+        uhost->ctrl.state = CONTROL_STATUS_IN;
+      }
+    }
+    uhost->ctrl.timer = uhost->timer;
+    status = USB_OK;
+  }
+  else if(urb_state == URB_ERROR || urb_state == URB_NOTREADY)
+  {
+    uhost->ctrl.state = CONTROL_ERROR;
+    uhost->ctrl.sts = CTRL_XACTERR;
+    status = USB_ERROR;
+  }
+  else
+  {
+    /* wait nak timeout 5s*/
+    if(uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT)
+    {
+      uhost->ctrl.state = CONTROL_ERROR;
+      uhost->ctrl.sts = CTRL_XACTERR;
+      status = USB_ERROR;
+    }
+  }
+  return status;
+}
+
+/**
+  * @brief  usb host control data in request handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_data_in_handler(usbh_core_type *uhost)
+{
+  usb_sts_type status = USB_OK;
+  usbh_ctrl_recv_data(uhost, uhost->ctrl.buffer,
+                      uhost->ctrl.len,
+                      uhost->ctrl.hch_in);
+  uhost->ctrl.state = CONTROL_DATA_IN_WAIT;
+
+  return status;
+}
+
+/**
+  * @brief  usb host control data in wait handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  timeout: wait timeout
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_data_in_wait_handler(usbh_core_type *uhost, uint32_t timeout)
+{
+  usb_sts_type status = USB_OK;
+  urb_sts_type urb_state;
+  urb_state = uhost->urb_state[uhost->ctrl.hch_in];
+
+  if(urb_state == URB_DONE)
+  {
+    uhost->ctrl.state = CONTROL_STATUS_OUT;
+  }
+  else if(urb_state == URB_STALL)
+  {
+    uhost->ctrl.state = CONTROL_STALL;
+  }
+  else if(urb_state == URB_ERROR)
+  {
+    uhost->ctrl.state = CONTROL_ERROR;
+  }
+  else
+  {
+    /* wait nak timeout 5s*/
+    if(uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT)
+    {
+      uhost->ctrl.state = CONTROL_ERROR;
+      uhost->ctrl.sts = CTRL_XACTERR;
+      status = USB_ERROR;
+    }
+
+  }
+  return status;
+}
+
+/**
+  * @brief  usb host control data out request handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_data_out_handler(usbh_core_type *uhost)
+{
+  usb_sts_type status = USB_OK;
+  uhost->hch[uhost->ctrl.hch_out].toggle_out = 1;
+
+  usbh_ctrl_send_data(uhost, uhost->ctrl.buffer,
+                      uhost->ctrl.len,
+                      uhost->ctrl.hch_out);
+  uhost->ctrl.state = CONTROL_DATA_OUT_WAIT;
+
+  return status;
+}
+
+/**
+  * @brief  usb host control data out wait handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  timeout: wait timeout
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_data_out_wait_handler(usbh_core_type *uhost, uint32_t timeout)
+{
+  usb_sts_type status = USB_OK;
+  urb_sts_type urb_state;
+  urb_state = uhost->urb_state[uhost->ctrl.hch_out];
+  if(urb_state == URB_DONE)
+  {
+    uhost->ctrl.state = CONTROL_STATUS_IN;
+  }
+  else if(urb_state == URB_STALL)
+  {
+    uhost->ctrl.state = CONTROL_STALL;
+  }
+  else if(urb_state == URB_ERROR)
+  {
+    uhost->ctrl.state = CONTROL_ERROR;
+  }
+  else if(urb_state == URB_NOTREADY)
+  {
+    uhost->ctrl.state = CONTROL_DATA_OUT;
+  }
+
+  /* wait nak timeout 5s*/
+  if((uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT) && (urb_state == URB_NOTREADY))
+  {
+    uhost->ctrl.state = CONTROL_ERROR;
+    uhost->ctrl.sts = CTRL_XACTERR;
+    status = USB_ERROR;
+  }
+  return status;
+}
+
+/**
+  * @brief  usb host control status data in handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_status_in_handler(usbh_core_type *uhost)
+{
+  usb_sts_type status = USB_OK;
+  usbh_ctrl_recv_data(uhost, 0, 0,
+                      uhost->ctrl.hch_in);
+  uhost->ctrl.state = CONTROL_STATUS_IN_WAIT;
+
+
+  return status;
+}
+
+/**
+  * @brief  usb host control status data in wait handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  timeout: wait timeout
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_status_in_wait_handler(usbh_core_type *uhost, uint32_t timeout)
+{
+  usb_sts_type status = USB_OK;
+  urb_sts_type urb_state;
+  urb_state = uhost->urb_state[uhost->ctrl.hch_in];
+  if(urb_state == URB_DONE)
+  {
+    uhost->ctrl.state = CONTROL_COMPLETE;
+  }
+  else if(urb_state == URB_STALL)
+  {
+    uhost->ctrl.state = CONTROL_STALL;
+    status = USB_NOT_SUPPORT;
+  }
+  else if(urb_state == URB_ERROR)
+  {
+    uhost->ctrl.state = CONTROL_ERROR;
+  }
+  else
+  {
+    /* wait nak timeout 5s*/
+    if(uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT)
+    {
+      uhost->ctrl.state = CONTROL_ERROR;
+      uhost->ctrl.sts = CTRL_XACTERR;
+      status = USB_ERROR;
+    }
+  }
+  return status;
+}
+
+/**
+  * @brief  usb host control status data out wait handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_status_out_handler(usbh_core_type *uhost)
+{
+  usb_sts_type status = USB_OK;
+  uhost->hch[uhost->ctrl.hch_out].toggle_out ^= 1;
+
+  usbh_ctrl_send_data(uhost, 0, 0, uhost->ctrl.hch_out);
+  uhost->ctrl.state = CONTROL_STATUS_OUT_WAIT;
+
+  return status;
+}
+
+/**
+  * @brief  usb host control status data out wait handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  timeout: wait timeout
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_status_out_wait_handler(usbh_core_type *uhost, uint32_t timeout)
+{
+  usb_sts_type status = USB_OK;
+  urb_sts_type urb_state;
+  urb_state = uhost->urb_state[uhost->ctrl.hch_out];
+  if(urb_state == URB_DONE)
+  {
+    uhost->ctrl.state = CONTROL_COMPLETE;
+  }
+  else if(urb_state == URB_STALL)
+  {
+    uhost->ctrl.state = CONTROL_STALL;
+  }
+  else if(urb_state == URB_ERROR)
+  {
+    uhost->ctrl.state = CONTROL_ERROR;
+  }
+  else if(urb_state == URB_NOTREADY)
+  {
+    uhost->ctrl.state = CONTROL_STATUS_OUT;
+  }
+  /* wait nak timeout 5s*/
+  if((uhost->timer - uhost->ctrl.timer > CTRL_TIMEOUT) && (urb_state == URB_NOTREADY))
+  {
+    uhost->ctrl.state = CONTROL_ERROR;
+    uhost->ctrl.sts = CTRL_XACTERR;
+    status = USB_ERROR;
+  }
+  return status;
+}
+
+/**
+  * @brief  usb host control error handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_error_handler(usbh_core_type *uhost)
+{
+  usb_sts_type status =  USB_WAIT;
+  if(++ uhost->ctrl.err_cnt <= USBH_MAX_ERROR_COUNT)
+  {
+    uhost->ctrl.state = CONTROL_SETUP;
+  }
+  else
+  {
+    uhost->ctrl.sts = CTRL_FAIL;
+    uhost->global_state = USBH_ERROR_STATE;
+    uhost->ctrl.err_cnt = 0;
+    status = USB_ERROR;
+  }
+  return status;
+}
+
+/**
+  * @brief  usb host control stall handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval usb_sts_type
+  */
+usb_sts_type usbh_ctrl_stall_handler(usbh_core_type *uhost)
+{
+  return USB_NOT_SUPPORT;
+}
+
+/**
+  * @brief  usb host control complete handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_complete_handler(usbh_core_type *uhost)
+{
+  return USB_OK;
+}
+
+/**
+  * @brief  usb host control transfer loop function
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_transfer_loop(usbh_core_type *uhost)
+{
+  usb_sts_type status = USB_WAIT;
+  static uint32_t timeout = 0;
+  uhost->ctrl.sts = CTRL_START;
+
+  switch(uhost->ctrl.state)
+  {
+    case CONTROL_SETUP:
+      usbh_ctrl_setup_handler(uhost);
+      uhost->ctrl.timer = uhost->timer;
+      break;
+
+    case CONTROL_SETUP_WAIT:
+      usbh_ctrl_setup_wait_handler(uhost, &timeout);
+      break;
+
+    case CONTROL_DATA_IN:
+      usbh_ctrl_data_in_handler(uhost);
+      break;
+
+    case CONTROL_DATA_IN_WAIT:
+      usbh_ctrl_data_in_wait_handler(uhost, timeout);
+      break;
+
+    case CONTROL_DATA_OUT:
+      usbh_ctrl_data_out_handler(uhost);
+      break;
+
+    case CONTROL_DATA_OUT_WAIT:
+      usbh_ctrl_data_out_wait_handler(uhost, timeout);
+      break;
+
+    case CONTROL_STATUS_IN:
+      usbh_ctrl_status_in_handler(uhost);
+      break;
+
+    case CONTROL_STATUS_IN_WAIT:
+      usbh_ctrl_status_in_wait_handler(uhost, timeout);
+      break;
+
+    case CONTROL_STATUS_OUT:
+      usbh_ctrl_status_out_handler(uhost);
+      break;
+
+    case CONTROL_STATUS_OUT_WAIT:
+      usbh_ctrl_status_out_wait_handler(uhost, timeout);
+      break;
+    case CONTROL_STALL:
+      status = usbh_ctrl_stall_handler(uhost);
+      break;
+    case CONTROL_ERROR:
+      status = usbh_ctrl_error_handler(uhost);
+      break;
+    case CONTROL_COMPLETE:
+      status = usbh_ctrl_complete_handler(uhost);
+      break;
+
+    default:
+      break;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  usb host control request
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  buffer: usb request buffer
+  * @param  length: usb request length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_ctrl_request(usbh_core_type *uhost, uint8_t *buffer, uint16_t length)
+{
+  usb_sts_type status = USB_OK;
+  if(uhost->req_state == CMD_SEND)
+  {
+    uhost->req_state = CMD_WAIT;
+    uhost->ctrl.buffer = buffer;
+    uhost->ctrl.len = length;
+    uhost->ctrl.state = CONTROL_SETUP;
+  }
+  return status;
+}
+
+/**
+  * @brief  usb host get device descriptor
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  length: get descriptor request length
+  * @param  req_type: usb request type
+  * @param  wvalue: usb wvalue
+  * @param  buffer: request buffer
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_get_descriptor(usbh_core_type *uhost, uint16_t length,
+                            uint8_t req_type, uint16_t wvalue,
+                            uint8_t *buffer)
+{
+  usb_sts_type status;
+  uhost->ctrl.setup.bmRequestType = USB_DIR_D2H | req_type;
+  uhost->ctrl.setup.bRequest = USB_STD_REQ_GET_DESCRIPTOR;
+  uhost->ctrl.setup.wValue = wvalue;
+  uhost->ctrl.setup.wLength = length;
+
+  if((wvalue & 0xFF00) == ((USB_DESCIPTOR_TYPE_STRING << 8) & 0xFF00))
+  {
+    uhost->ctrl.setup.wIndex = 0x0409;
+  }
+  else
+  {
+    uhost->ctrl.setup.wIndex = 0;
+  }
+
+  status = usbh_ctrl_request(uhost, buffer, length);
+  return status;
+}
+
+/**
+  * @brief  usb host parse device descriptor
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  buffer: usb device descriptor buffer
+  * @param  length: usb device descriptor length
+  * @retval status: usb_sts_type status
+  */
+void usbh_parse_dev_desc(usbh_core_type *uhost, uint8_t *buffer, uint16_t length)
+{
+  usbh_dev_desc_type *desc = &(uhost->dev);
+
+  desc->dev_desc.bLength = *(uint8_t *)(buffer + 0);
+  desc->dev_desc.bDescriptorType = *(uint8_t *)(buffer + 1);
+  desc->dev_desc.bcdUSB = SWAPBYTE(buffer + 2);
+  desc->dev_desc.bDeviceClass = *(uint8_t *)(buffer + 4);
+  desc->dev_desc.bDeviceSubClass = *(uint8_t *)(buffer + 5);
+  desc->dev_desc.bDeviceProtocol = *(uint8_t *)(buffer + 6);
+  desc->dev_desc.bMaxPacketSize0 = *(uint8_t *)(buffer + 7);
+
+  if(length > 8)
+  {
+    desc->dev_desc.idVendor = SWAPBYTE(buffer + 8);
+    desc->dev_desc.idProduct = SWAPBYTE(buffer + 10);
+    desc->dev_desc.bcdDevice = SWAPBYTE(buffer + 12);
+    desc->dev_desc.iManufacturer = *(uint8_t *)(buffer + 14);
+    desc->dev_desc.iProduct = *(uint8_t *)(buffer + 15);
+    desc->dev_desc.iSerialNumber = *(uint8_t *)(buffer + 16);
+    desc->dev_desc.bNumConfigurations = *(uint8_t *)(buffer + 17);
+  }
+}
+
+/**
+  * @brief  usb host get next header
+  * @param  buffer: usb data buffer
+  * @param  index_len: pointer of index len
+  * @retval status: usb_sts_type status
+  */
+usb_header_desc_type *usbh_get_next_header(uint8_t *buf, uint16_t *index_len)
+{
+  *index_len += ((usb_header_desc_type *)buf)->bLength;
+  return (usb_header_desc_type *)
+          ((uint8_t *)buf + ((usb_header_desc_type *)buf)->bLength);
+}
+
+/**
+  * @brief  usb host parse interface descriptor
+  * @param  intf: usb interface description type
+  * @param  buf: interface description data buffer
+  * @retval none
+  */
+void usbh_parse_interface_desc(usb_interface_desc_type *intf, uint8_t *buf)
+{
+  intf->bLength                          = *(uint8_t *)buf;
+  intf->bDescriptorType                  = *(uint8_t *)(buf + 1);
+  intf->bInterfaceNumber                 = *(uint8_t *)(buf + 2);
+  intf->bAlternateSetting                = *(uint8_t *)(buf + 3);
+  intf->bNumEndpoints                    = *(uint8_t *)(buf + 4);
+  intf->bInterfaceClass                  = *(uint8_t *)(buf + 5);
+  intf->bInterfaceSubClass               = *(uint8_t *)(buf + 6);
+  intf->bInterfaceProtocol               = *(uint8_t *)(buf + 7);
+  intf->iInterface                       = *(uint8_t *)(buf + 8);
+}
+
+/**
+  * @brief  usb host parse endpoint descriptor
+  * @param  ept_desc: endpoint type
+  * @param  buf: endpoint description data buffer
+  * @retval none
+  */
+void usbh_parse_endpoint_desc(usb_endpoint_desc_type *ept_desc, uint8_t *buf)
+{
+  ept_desc->bLength                      = *(uint8_t *)(buf + 0);
+  ept_desc->bDescriptorType              = *(uint8_t *)(buf + 1);
+  ept_desc->bEndpointAddress             = *(uint8_t *)(buf + 2);
+  ept_desc->bmAttributes                 = *(uint8_t *)(buf + 3);
+  ept_desc->wMaxPacketSize               = SWAPBYTE(buf + 4);
+  ept_desc->bInterval                    = *(uint8_t *)(buf + 6);
+}
+
+/**
+  * @brief  usb host parse configure descriptor
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  buffer: configure buffer
+  * @param  length: configure length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_parse_configure_desc(usbh_core_type *uhost,
+                                  uint8_t *buffer, uint16_t length)
+{
+  usb_cfg_desc_type *cfg_desc = &(uhost->dev.cfg_desc);
+  usb_interface_desc_type *intf_desc;
+  usb_endpoint_desc_type *ept_desc;
+  usb_header_desc_type *desc;
+  uint16_t index_len;
+  uint8_t index_intf = 0;
+  uint8_t index_ept = 0;
+
+  desc = (usb_header_desc_type *)buffer;
+  cfg_desc->cfg.bLength                      = *(uint8_t *)buffer;
+  cfg_desc->cfg.bDescriptorType              = *(uint8_t *)(buffer + 1);
+  cfg_desc->cfg.wTotalLength                 = SWAPBYTE(buffer + 2);
+  cfg_desc->cfg.bNumInterfaces               = *(uint8_t *)(buffer + 4);
+  cfg_desc->cfg.bConfigurationValue          = *(uint8_t *)(buffer + 5);
+  cfg_desc->cfg.iConfiguration               = *(uint8_t *)(buffer + 6);
+  cfg_desc->cfg.bmAttributes                 = *(uint8_t *)(buffer + 7);
+  cfg_desc->cfg.bMaxPower                    = *(uint8_t *)(buffer + 8);
+
+  if(length > USB_DEVICE_CFG_DESC_LEN)
+  {
+    index_len = USB_DEVICE_CFG_DESC_LEN;
+
+    while((index_intf < USBH_MAX_INTERFACE) && index_len < cfg_desc->cfg.wTotalLength)
+    {
+      desc = usbh_get_next_header((uint8_t *)desc, &index_len);
+      if(desc->bDescriptorType == USB_DESCIPTOR_TYPE_INTERFACE)
+      {
+        index_ept = 0;
+        intf_desc = &cfg_desc->interface[index_intf].interface;
+        usbh_parse_interface_desc(intf_desc, (uint8_t *)desc);
+
+        while(index_ept < intf_desc->bNumEndpoints && index_len < cfg_desc->cfg.wTotalLength)
+        {
+          desc = usbh_get_next_header((uint8_t *)desc, &index_len);
+          if(desc->bDescriptorType == USB_DESCIPTOR_TYPE_ENDPOINT)
+          {
+            ept_desc = &(cfg_desc->interface[index_intf].endpoint[index_ept]);
+            usbh_parse_endpoint_desc(ept_desc, (uint8_t *)desc);
+            index_ept ++;
+          }
+        }
+        index_intf ++;
+      }
+    }
+  }
+  return USB_OK;
+}
+
+/**
+  * @brief  usb host find interface
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  class_code: class code
+  * @param  sub_class: subclass code
+  * @param  protocol: prtocol code
+  * @retval idx: interface index
+  */
+uint8_t usbh_find_interface(usbh_core_type *uhost, uint8_t class_code, uint8_t sub_class, uint8_t protocol)
+{
+  uint8_t idx = 0;
+  usb_itf_desc_type *usbitf;
+  for(idx = 0; idx < uhost->dev.cfg_desc.cfg.bNumInterfaces; idx ++)
+  {
+    usbitf = &uhost->dev.cfg_desc.interface[idx];
+    if(((usbitf->interface.bInterfaceClass == class_code) || (class_code == 0xFF)) &&
+      ((usbitf->interface.bInterfaceSubClass == sub_class) || (sub_class == 0xFF)) &&
+      ((usbitf->interface.bInterfaceProtocol == protocol) || (protocol == 0xFF))
+       )
+    {
+      return idx;
+    }
+  }
+  return 0xFF;
+}
+
+/**
+  * @brief  usbh parse string descriptor
+  * @param  src: string source pointer
+  * @param  dest: string destination pointer
+  * @param  length: string length
+  * @retval none
+  */
+void usbh_parse_string_desc(uint8_t *src, uint8_t *dest, uint16_t length)
+{
+  uint16_t len;
+  uint16_t i_index;
+
+  if(src[1] == USB_DESCIPTOR_TYPE_STRING)
+  {
+    len = ((src[0] - 2) <= length ? (src[0] - 2) : length);
+    src += 2;
+    for(i_index = 0; i_index < len; i_index += 2)
+    {
+      *dest = src[i_index];
+      dest ++;
+    }
+    *dest = 0;
+  }
+}
+
+/**
+  * @brief  usb host get device descriptor
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  length: get device descriptor length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_get_device_descriptor(usbh_core_type *uhost, uint16_t length)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  uint16_t wvalue;
+
+  bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
+  wvalue = (USB_DESCIPTOR_TYPE_DEVICE << 8) & 0xFF00;
+
+  status = usbh_get_descriptor(uhost, length, bm_req,
+                               wvalue, uhost->rx_buffer);
+  return status;
+}
+
+/**
+  * @brief  usb host get configure descriptor
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  length: get device configure length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_get_configure_descriptor(usbh_core_type *uhost, uint16_t length)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  uint16_t wvalue;
+
+  bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
+  wvalue = (USB_DESCIPTOR_TYPE_CONFIGURATION << 8) & 0xFF00;
+
+  status = usbh_get_descriptor(uhost, length, bm_req,
+                               wvalue, uhost->rx_buffer);
+
+  return status;
+}
+
+/**
+  * @brief  usb host get string descriptor
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  string_id: string id
+  * @param  buffer: receive data buffer
+  * @param  length: get device string length
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_get_sting_descriptor(usbh_core_type *uhost, uint8_t string_id,
+                                  uint8_t *buffer, uint16_t length)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  uint16_t wvalue;
+
+  bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
+  wvalue = (USB_DESCIPTOR_TYPE_STRING << 8) | string_id;
+
+  status = usbh_get_descriptor(uhost, length, bm_req,
+                               wvalue, uhost->rx_buffer);
+
+  return status;
+}
+
+/**
+  * @brief  usb host set configurtion
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  config: usb configuration
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_set_configuration(usbh_core_type *uhost, uint16_t config)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
+
+  uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
+  uhost->ctrl.setup.bRequest = USB_STD_REQ_SET_CONFIGURATION;
+  uhost->ctrl.setup.wValue = config;
+  uhost->ctrl.setup.wLength = 0;
+  uhost->ctrl.setup.wIndex = 0;
+  status = usbh_ctrl_request(uhost, 0, 0);
+  return status;
+}
+
+/**
+  * @brief  usb host set device address
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  address: device address
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_set_address(usbh_core_type *uhost, uint8_t address)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
+
+  uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
+  uhost->ctrl.setup.bRequest = USB_STD_REQ_SET_ADDRESS;
+  uhost->ctrl.setup.wValue = (uint16_t)address;
+  uhost->ctrl.setup.wLength = 0;
+  uhost->ctrl.setup.wIndex = 0;
+  status = usbh_ctrl_request(uhost, 0, 0);
+  return status;
+}
+
+/**
+  * @brief  usb host set interface
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  ept_num: endpoint number
+  * @param  altsetting: alter setting
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_set_interface(usbh_core_type *uhost, uint8_t ept_num, uint8_t altsetting)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  bm_req = USB_REQ_RECIPIENT_INTERFACE | USB_REQ_TYPE_STANDARD;
+
+  uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
+  uhost->ctrl.setup.bRequest = USB_STD_REQ_SET_INTERFACE;
+  uhost->ctrl.setup.wValue = (uint16_t)altsetting;
+  uhost->ctrl.setup.wLength = 0;
+  uhost->ctrl.setup.wIndex = ept_num;
+  status = usbh_ctrl_request(uhost, 0, 0);
+  return status;
+}
+
+/**
+  * @brief  usb host set feature
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  feature: feature number
+  * @param  index: index number
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_set_feature(usbh_core_type *uhost, uint8_t feature, uint16_t index)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
+
+  uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
+  uhost->ctrl.setup.bRequest = USB_STD_REQ_SET_FEATURE;
+  uhost->ctrl.setup.wValue = (uint16_t)feature;
+  uhost->ctrl.setup.wLength = 0;
+  uhost->ctrl.setup.wIndex = index;
+  status = usbh_ctrl_request(uhost, 0, 0);
+  return status;
+}
+
+
+/**
+  * @brief  usb host clear device feature
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  feature: feature number
+  * @param  index: index number
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_clear_dev_feature(usbh_core_type *uhost, uint8_t feature, uint16_t index)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  bm_req = USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD;
+
+  uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
+  uhost->ctrl.setup.bRequest = USB_STD_REQ_CLEAR_FEATURE;
+  uhost->ctrl.setup.wValue = (uint16_t)feature;
+  uhost->ctrl.setup.wLength = 0;
+  uhost->ctrl.setup.wIndex = index;
+  status = usbh_ctrl_request(uhost, 0, 0);
+  return status;
+}
+
+/**
+  * @brief  usb host clear endpoint feature
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  ept_num: endpoint number
+  * @param  hc_num: host channel number
+  * @retval status: usb_sts_type status
+  */
+usb_sts_type usbh_clear_ept_feature(usbh_core_type *uhost, uint8_t ept_num, uint8_t hc_num)
+{
+  usb_sts_type status = USB_WAIT;
+  uint8_t bm_req;
+  if(uhost->ctrl.state == CONTROL_IDLE )
+  {
+    bm_req = USB_REQ_RECIPIENT_ENDPOINT | USB_REQ_TYPE_STANDARD;
+
+    uhost->ctrl.setup.bmRequestType = USB_DIR_H2D | bm_req;
+    uhost->ctrl.setup.bRequest = USB_STD_REQ_CLEAR_FEATURE;
+    uhost->ctrl.setup.wValue = USB_FEATURE_EPT_HALT;
+    uhost->ctrl.setup.wLength = 0;
+    uhost->ctrl.setup.wIndex = ept_num;
+    usbh_ctrl_request(uhost, 0, 0);
+  }
+  if(usbh_ctrl_result_check(uhost, CONTROL_IDLE, ENUM_IDLE) == USB_OK)
+  {
+    status = USB_OK;
+  }
+  return status;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 540 - 0
bsp/at32/libraries/usbfs_library/src/usbh_int.c

@@ -0,0 +1,540 @@
+/**
+  **************************************************************************
+  * @file     usbh_int.c
+  * @brief    usb host interrupt request
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+#include "usbh_int.h"
+
+/** @defgroup USBH_drivers_interrupt
+  * @brief usb host interrupt
+  * @{
+  */
+
+/** @defgroup USBH_int_private_functions
+  * @{
+  */
+
+/**
+  * @brief  usb host interrupt handler
+  * @param  otgdev: to the structure of otg_core_type
+  * @retval none
+  */
+void usbh_irq_handler(otg_core_type *otgdev)
+{
+  otg_global_type *usbx = otgdev->usb_reg;
+  usbh_core_type *uhost = &otgdev->host;
+  uint32_t intsts = usb_global_get_all_interrupt(usbx);
+
+  if(usbx->gintsts_bit.curmode == 1)
+  {
+    if(intsts & USB_OTG_HCH_FLAG)
+    {
+      usbh_hch_handler(uhost);
+      usb_global_clear_interrupt(usbx, USB_OTG_HCH_FLAG);
+    }
+    if(intsts & USB_OTG_SOF_FLAG)
+    {
+      usbh_sof_handler(uhost);
+      usb_global_clear_interrupt(usbx, USB_OTG_SOF_FLAG);
+    }
+    if(intsts & USB_OTG_MODEMIS_FLAG)
+    {
+      usb_global_clear_interrupt(usbx, USB_OTG_MODEMIS_FLAG);
+    }
+    if(intsts & USB_OTG_WKUP_FLAG)
+    {
+      usbh_wakeup_handler(uhost);
+      usb_global_clear_interrupt(usbx, USB_OTG_WKUP_FLAG);
+    }
+    while(usbx->gintsts & USB_OTG_RXFLVL_FLAG)
+    {
+      usbh_rx_qlvl_handler(uhost);
+      usb_global_clear_interrupt(usbx, USB_OTG_RXFLVL_FLAG);
+    }
+    if(intsts & USB_OTG_DISCON_FLAG)
+    {
+      usbh_disconnect_handler(uhost);
+      usb_global_clear_interrupt(usbx, USB_OTG_DISCON_FLAG);
+    }
+    if(intsts & USB_OTG_PRT_FLAG)
+    {
+      usbh_port_handler(uhost);
+    }
+    if(intsts & USB_OTG_INCOMPIP_INCOMPISOOUT_FLAG)
+    {
+      usb_global_clear_interrupt(usbx, USB_OTG_INCOMPIP_INCOMPISOOUT_FLAG);
+    }
+    if(intsts & USB_OTG_INCOMISOIN_FLAG)
+    {
+      usb_global_clear_interrupt(usbx, USB_OTG_INCOMISOIN_FLAG);
+    }
+    if(intsts & USB_OTG_PTXFEMP_FLAG)
+    {
+      usb_global_clear_interrupt(usbx, USB_OTG_PTXFEMP_FLAG);
+    }
+    if(intsts & USB_OTG_ISOOUTDROP_FLAG)
+    {
+      usb_global_clear_interrupt(usbx, USB_OTG_ISOOUTDROP_FLAG);
+    }
+
+  }
+}
+
+/**
+  * @brief  usb host wakeup handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+void usbh_wakeup_handler(usbh_core_type *uhost)
+{
+  uhost->global_state = USBH_WAKEUP;
+}
+
+/**
+  * @brief  usb host sof handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+void usbh_sof_handler(usbh_core_type *uhost)
+{
+  uhost->timer ++;
+}
+
+/**
+  * @brief  usb host disconnect handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+void usbh_disconnect_handler(usbh_core_type *uhost)
+{
+  otg_global_type *usbx = uhost->usb_reg;
+
+  uint8_t i_index;
+
+  usb_host_disable(usbx);
+
+  uhost->conn_sts = 0;
+
+  uhost->global_state = USBH_DISCONNECT;
+
+  for(i_index = 0; i_index < USB_HOST_CHANNEL_NUM; i_index ++)
+  {
+    usbh_free_channel(uhost, i_index);
+  }
+  usbh_fsls_clksel(usbx, USB_HCFG_CLK_48M);
+
+  usbh_disconnect_callback(uhost);
+}
+
+/**
+  * @brief  usb host in transfer request handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  chn: channel number
+  * @retval none
+  */
+void usbh_hch_in_handler(usbh_core_type *uhost, uint8_t chn)
+{
+  otg_global_type *usbx = uhost->usb_reg;
+  otg_hchannel_type *usb_chh = USB_CHL(usbx, chn);
+  uint32_t hcint_value = usb_chh->hcint & usb_chh->hcintmsk;
+
+  if( hcint_value & USB_OTG_HC_ACK_FLAG)
+  {
+    usb_chh->hcint = USB_OTG_HC_ACK_FLAG;
+  }
+  else if(hcint_value & USB_OTG_HC_STALL_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    usb_chh->hcint = USB_OTG_HC_NAK_FLAG | USB_OTG_HC_STALL_FLAG;
+    uhost->hch[chn].state = HCH_STALL;
+    usb_hch_halt(usbx, chn);
+  }
+  else if(hcint_value & USB_OTG_HC_DTGLERR_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    usb_hch_halt(usbx, chn);
+    usb_chh->hcint = USB_OTG_HC_DTGLERR_FLAG | USB_OTG_HC_NAK_FLAG;
+    uhost->hch[chn].state = HCH_DATATGLERR;
+  }
+
+  else if(hcint_value & USB_OTG_HC_FRMOVRRUN_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    usb_hch_halt(usbx, chn);
+    usb_chh->hcint = USB_OTG_HC_FRMOVRRUN_FLAG;
+  }
+  else if(hcint_value & USB_OTG_HC_XFERC_FLAG)
+  {
+    uhost->hch[chn].state = HCH_XFRC;
+    usb_chh->hcint = USB_OTG_HC_XFERC_FLAG;
+
+    if(usb_chh->hcchar_bit.eptype == EPT_BULK_TYPE || usb_chh->hcchar_bit.eptype == EPT_CONTROL_TYPE)
+    {
+      usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+      usb_hch_halt(usbx, chn);
+      usb_chh->hcint = USB_OTG_HC_NAK_FLAG;
+    }
+    else if(usb_chh->hcchar_bit.eptype == EPT_INT_TYPE)
+    {
+      usb_chh->hcchar_bit.oddfrm = TRUE;
+      uhost->urb_state[chn] = URB_DONE;
+
+      usbd_notify_urbchange_callback(uhost, chn, uhost->urb_state[chn]);
+    }
+    else if(usb_chh->hcchar_bit.eptype == EPT_ISO_TYPE)
+    {
+      uhost->urb_state[chn] = URB_DONE;
+      usbd_notify_urbchange_callback(uhost, chn, uhost->urb_state[chn]);
+    }
+    uhost->hch[chn].toggle_in ^= 1;
+  }
+  else if(hcint_value & USB_OTG_HC_CHHLTD_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = FALSE;
+    if(uhost->hch[chn].state == HCH_XFRC )
+    {
+      uhost->urb_state[chn]  = URB_DONE;
+    }
+    else if(uhost->hch[chn].state == HCH_STALL)
+    {
+      uhost->urb_state[chn]  = URB_STALL;
+    }
+    else if(uhost->hch[chn].state == HCH_XACTERR ||
+            uhost->hch[chn].state == HCH_DATATGLERR)
+    {
+      uhost->err_cnt[chn] ++;
+      if(uhost->err_cnt[chn] > 3)
+      {
+        uhost->urb_state[chn] = URB_ERROR;
+        uhost->err_cnt[chn] = 0;
+      }
+      else
+      {
+        uhost->urb_state[chn] = URB_NOTREADY;
+      }
+      usb_chh->hcchar_bit.chdis = FALSE;
+      usb_chh->hcchar_bit.chena = TRUE;
+    }
+    else if(uhost->hch[chn].state == HCH_NAK)
+    {
+      usb_chh->hcchar_bit.chdis = FALSE;
+      usb_chh->hcchar_bit.chena = TRUE;
+      uhost->urb_state[chn] = URB_NOTREADY;
+    }
+    usb_chh->hcint = USB_OTG_HC_CHHLTD_FLAG;
+    usbd_notify_urbchange_callback(uhost, chn, uhost->urb_state[chn]);
+  }
+  else if(hcint_value & USB_OTG_HC_XACTERR_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    uhost->hch[chn].state = HCH_XACTERR;
+    usb_hch_halt(usbx, chn);
+    uhost->err_cnt[chn] ++;
+    usb_chh->hcint = USB_OTG_HC_XACTERR_FLAG;
+  }
+  else if(hcint_value & USB_OTG_HC_NAK_FLAG)
+  {
+    if(usb_chh->hcchar_bit.eptype == EPT_INT_TYPE)
+    {
+      uhost->err_cnt[chn] = 0;
+      usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+      usb_hch_halt(usbx, chn);
+    }
+    else if(usb_chh->hcchar_bit.eptype == EPT_BULK_TYPE ||
+      usb_chh->hcchar_bit.eptype == EPT_CONTROL_TYPE)
+    {
+      uhost->err_cnt[chn] = 0;
+      usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+      usb_hch_halt(usbx, chn);
+    }
+    uhost->hch[chn].state = HCH_NAK;
+    usb_chh->hcint = USB_OTG_HC_NAK_FLAG;
+  }
+  else if(hcint_value & USB_OTG_HC_BBLERR_FLAG)
+  {
+    usb_chh->hcint = USB_OTG_HC_BBLERR_FLAG;
+  }
+}
+
+/**
+  * @brief  usb host out transfer request handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @param  chn: channel number
+  * @retval none
+  */
+void usbh_hch_out_handler(usbh_core_type *uhost, uint8_t chn)
+{
+  otg_global_type *usbx = uhost->usb_reg;
+  otg_hchannel_type *usb_chh = USB_CHL(usbx, chn);
+  uint32_t hcint_value = usb_chh->hcint & usb_chh->hcintmsk;
+
+  if( hcint_value & USB_OTG_HC_ACK_FLAG)
+  {
+    usb_chh->hcint = USB_OTG_HC_ACK_FLAG;
+  }
+  else if( hcint_value & USB_OTG_HC_FRMOVRRUN_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    usb_hch_halt(usbx, chn);
+    usb_chh->hcint = USB_OTG_HC_FRMOVRRUN_FLAG;
+  }
+  else if( hcint_value & USB_OTG_HC_XFERC_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    usb_hch_halt(usbx, chn);
+    uhost->hch[chn].state = HCH_XFRC;
+    usb_chh->hcint = USB_OTG_HC_XFERC_FLAG;
+  }
+  else if( hcint_value & USB_OTG_HC_STALL_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    usb_chh->hcint =  USB_OTG_HC_STALL_FLAG;
+    uhost->hch[chn].state = HCH_STALL;
+    usb_hch_halt(usbx, chn);
+  }
+  else if( hcint_value & USB_OTG_HC_DTGLERR_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    usb_hch_halt(usbx, chn);
+    usb_chh->hcint = USB_OTG_HC_DTGLERR_FLAG | USB_OTG_HC_NAK_FLAG;
+    uhost->hch[chn].state = HCH_DATATGLERR;
+  }
+  else if( hcint_value & USB_OTG_HC_CHHLTD_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = FALSE;
+    if(uhost->hch[chn].state == HCH_XFRC)
+    {
+      uhost->urb_state[chn] = URB_DONE;
+      if(uhost->hch[chn].ept_type == EPT_BULK_TYPE ||
+        uhost->hch[chn].ept_type == EPT_INT_TYPE)
+      {
+        uhost->hch[chn].toggle_out ^= 1;
+      }
+    }
+    else if(uhost->hch[chn].state == HCH_NAK)
+    {
+      uhost->urb_state[chn] = URB_NOTREADY;
+    }
+    else if(uhost->hch[chn].state == HCH_STALL)
+    {
+      uhost->hch[chn].urb_sts = URB_STALL;
+    }
+    else if(uhost->hch[chn].state == HCH_XACTERR ||
+            uhost->hch[chn].state == HCH_DATATGLERR)
+    {
+      uhost->err_cnt[chn] ++;
+      if(uhost->err_cnt[chn] > 3)
+      {
+        uhost->urb_state[chn] = URB_ERROR;
+        uhost->err_cnt[chn] = 0;
+        usbd_notify_urbchange_callback(uhost, chn, uhost->urb_state[chn]);
+      }
+      else
+      {
+        uhost->urb_state[chn] = URB_NOTREADY;
+      }
+
+      usb_chh->hcchar_bit.chdis = FALSE;
+      usb_chh->hcchar_bit.chena = TRUE;
+    }
+    usb_chh->hcint = USB_OTG_HC_CHHLTD_FLAG;
+    usbd_notify_urbchange_callback(uhost, chn, uhost->urb_state[chn]);
+  }
+  else if( hcint_value & USB_OTG_HC_XACTERR_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    uhost->err_cnt[chn] ++;
+    uhost->hch[chn].state = HCH_XACTERR;
+    usb_hch_halt(usbx, chn);
+    usb_chh->hcint = USB_OTG_HC_XACTERR_FLAG | USB_OTG_HC_NAK_FLAG;
+  }
+  else if( hcint_value & USB_OTG_HC_NAK_FLAG)
+  {
+    usb_chh->hcintmsk_bit.chhltdmsk = TRUE;
+    uhost->err_cnt[chn] = 0;
+    usb_hch_halt(usbx, chn);
+    uhost->hch[chn].state = HCH_NAK;
+    usb_chh->hcint = USB_OTG_HC_NAK_FLAG;
+  }
+}
+
+/**
+  * @brief  usb host channel request handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+void usbh_hch_handler(usbh_core_type *uhost)
+{
+  otg_global_type *usbx = uhost->usb_reg;
+  otg_host_type *usb_host = OTG_HOST(usbx);
+  uint32_t intsts, i_index;
+
+  intsts = usb_host->haint & 0xFFFF;
+  for(i_index = 0; i_index < 16; i_index ++)
+  {
+    if(intsts & (1 << i_index))
+    {
+      if(USB_CHL(usbx, i_index)->hcchar_bit.eptdir)
+      {
+        //hc in
+        usbh_hch_in_handler(uhost, i_index);
+      }
+      else
+      {
+        //hc out
+        usbh_hch_out_handler(uhost, i_index);
+      }
+    }
+  }
+}
+
+/**
+  * @brief  usb host rx buffer not empty request handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+void usbh_rx_qlvl_handler(usbh_core_type *uhost)
+{
+  uint8_t chn;
+  uint32_t pktsts;
+  uint32_t pktcnt;
+  uint32_t tmp;
+  otg_hchannel_type *ch;
+  otg_global_type *usbx = uhost->usb_reg;
+
+  usbx->gintmsk_bit.rxflvlmsk = 0;
+
+  tmp = usbx->grxstsp;
+  chn = tmp & 0xF;
+  pktsts = (tmp >> 17) & 0xF;
+  pktcnt = (tmp >> 4) & 0x7FF;
+  ch = USB_CHL(usbx, chn);
+  switch(pktsts)
+  {
+    case PKTSTS_IN_DATA_PACKET_RECV:
+      if(pktcnt > 0 && (uhost->hch[chn].trans_buf) != 0)
+      {
+        usb_read_packet(usbx, uhost->hch[chn].trans_buf, chn, pktcnt);
+        uhost->hch[chn].trans_buf += pktcnt;
+        uhost->hch[chn].trans_count += pktcnt;
+
+        if(ch->hctsiz_bit.pktcnt > 0)
+        {
+          ch->hcchar_bit.chdis = FALSE;
+          ch->hcchar_bit.chena = TRUE;
+          uhost->hch[chn].toggle_in ^= 1;
+        }
+      }
+      break;
+    case PKTSTS_IN_TRANSFER_COMPLETE:
+      break;
+    case PKTSTS_DATA_BIT_ERROR:
+      break;
+    case PKTSTS_CHANNEL_STOP:
+      break;
+    default:
+      break;
+
+  }
+  usbx->gintmsk_bit.rxflvlmsk = 1;
+}
+
+/**
+  * @brief  usb host port request handler
+  * @param  uhost: to the structure of usbh_core_type
+  * @retval none
+  */
+void usbh_port_handler(usbh_core_type *uhost)
+{
+  otg_global_type *usbx = uhost->usb_reg;
+  otg_host_type *usb_host = OTG_HOST(usbx);
+
+  uint32_t prt = 0, prt_0;
+
+  prt = usb_host->hprt;
+  prt_0 = prt;
+
+  prt_0 &= ~(USB_OTG_HPRT_PRTENA | USB_OTG_HPRT_PRTENCHNG |
+               USB_OTG_HPRT_PRTOVRCACT | USB_OTG_HPRT_PRTCONDET);
+  if(prt & USB_OTG_HPRT_PRTCONDET)
+  {
+    if(prt & USB_OTG_HPRT_PRTCONSTS)
+    {
+      /* connect callback */
+      uhost->conn_sts = 1;
+    }
+
+    usbh_connect_callback(uhost);
+    prt_0 |= USB_OTG_HPRT_PRTCONDET;
+  }
+
+  if(prt & USB_OTG_HPRT_PRTENCHNG)
+  {
+    prt_0 |= USB_OTG_HPRT_PRTENCHNG;
+
+    if(prt & USB_OTG_HPRT_PRTENA)
+    {
+      if((prt & USB_OTG_HPRT_PRTSPD) == (USB_PRTSPD_LOW_SPEED << 17))
+      {
+        usbh_fsls_clksel(usbx, USB_HCFG_CLK_6M);
+      }
+      else
+      {
+        usbh_fsls_clksel(usbx, USB_HCFG_CLK_48M);
+      }
+      /* connect callback */
+      uhost->port_enable = 1;
+    }
+    else
+    {
+      /* clean up hprt */
+      uhost->port_enable = 0;
+    }
+  }
+
+  if(prt & USB_OTG_HPRT_PRTOVRCACT)
+  {
+    prt_0 |= USB_OTG_HPRT_PRTOVRCACT;
+  }
+
+  usb_host->hprt = prt_0;
+}
+
+__weak void usbh_connect_callback(usbh_core_type *uhost)
+{
+}
+
+__weak void usbh_disconnect_callback(usbh_core_type *uhost)
+{
+}
+
+__weak void usbd_notify_urbchange_callback(usbh_core_type *uhost, uint8_t chnum, urb_sts_type sts)
+{
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

+ 2 - 0
bsp/at32/tools/sdk_dist.py

@@ -35,5 +35,7 @@ def dist_do_building(BSP_ROOT, dist_dir):
 
     print("=> copy bsp drivers")
     bsp_copy_files(os.path.join(library_path, 'rt_drivers'), os.path.join(library_dir, 'rt_drivers'))
+    bsp_copy_files(os.path.join(library_path, 'usbd_library'), os.path.join(library_dir, 'usbd_library'))
+    bsp_copy_files(os.path.join(library_path, 'usbfs_library'), os.path.join(library_dir, 'usbfs_library'))
     shutil.copyfile(os.path.join(library_path, 'Kconfig'), os.path.join(library_dir, 'Kconfig'))
     bsp_update_kconfig_library(dist_dir)