26 Commits

Author SHA1 Message Date
sakumisu
f3b5025b64 update(cherryusb): update to v1.5.1
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-14 11:49:37 +08:00
sakumisu
e32486f9a8 feat: support sifli
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-13 20:25:58 +08:00
sakumisu
064507bfe8 update(core/usbd_core): add ep0 state log
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-13 17:17:38 +08:00
sakumisu
e61141a45e update(port/dwc2/usb_dc_dwc2): use usbd_get_ep0_next_state for reading setup
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-13 17:17:19 +08:00
sakumisu
4ce8c507b0 update(demo): remove ep num check
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-13 16:39:33 +08:00
sakumisu
85e420eb54 update(port/fsdev): assert for fsdev log
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-13 16:39:20 +08:00
sakumisu
40a052ba7f chore(kconfig): add more config
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-11 18:34:46 +08:00
sakumisu
3249811a90 fix(port/dwc2/usb_dc_dwc2): align with CONFIG_USB_ALIGN_SIZE not only 32
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-11 18:34:26 +08:00
sakumisu
c5b1e1af27 fix typo
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-11 15:16:01 +08:00
sakumisu
78a802faa6 update(port/dwc2/usb_glue_at): update at glue with dwc2 param
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-10 21:52:58 +08:00
sakumisu
811550ad25 chore(port/dwc2): update readme
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-10 21:52:14 +08:00
mlwang
4093a3b01d fix(port/ehci): Fix the urb leak when there is no data in the control transmission 2025-07-10 21:45:45 +08:00
MDLZCOOL
9de928d6af Modify kconfig for better template choose 2025-07-10 20:19:16 +08:00
sakumisu
5a94ed80cb feat(port/dwc2): add user fifo config api
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-07 20:28:14 +08:00
sakumisu
22e150a8e6 refactor(port/dwc2): support custom config for each dwc2 usb port
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-05 16:39:54 +08:00
sakumisu
8e0ff856fe update(class/mtp): support obj remove & add event
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-03 20:54:30 +08:00
FanhuaCloud
739db92ef0 fix:(port/ch58x/usb_ch58x_dc_usbfs.c) fix out endpoint cannot receive bug 2025-07-03 16:15:08 +08:00
sakumisu
53e42e6ceb fix(platform/rtthread/usbh_serial): remove unused variable
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-02 20:17:20 +08:00
sakumisu
832e4c45fb fix(class/hub): change urb interval unit to us
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-01 21:21:59 +08:00
sakumisu
52ea7e8dcf fix(demo): fix webusb desc len
Signed-off-by: sakumisu <1203593632@qq.com>
2025-07-01 09:51:56 +08:00
sakumisu
5a3b87e08c feat(demo): add mavlink with cdc acm
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-26 18:28:46 +08:00
sakumisu
6f1228c029 fix(platform/rtthread): change ssize_t to rt_ssize_t
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-25 15:10:44 +08:00
sakumisu
e96e5fd9ca feat(platform/rtthread): support cdc acm chardev
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-25 14:07:06 +08:00
sakumisu
9d4faca7db fix(vendor/serial/usbh_ftdi): fix missing break
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-24 18:21:09 +08:00
sakumisu
c22615ea6f feat(platform/rtthread): support adb shell and serial framework
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-24 18:20:38 +08:00
sakumisu
749cd8531f docs: update rst
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-24 18:05:08 +08:00
67 changed files with 4228 additions and 907 deletions

134
Kconfig
View File

@@ -52,6 +52,8 @@ if CHERRYUSB
bool "musb_sunxi"
config CHERRYUSB_DEVICE_MUSB_BK
bool "musb_bk"
config CHERRYUSB_DEVICE_MUSB_SIFLI
bool "musb_sifli"
config CHERRYUSB_DEVICE_MUSB_CUSTOM
bool "musb_custom"
config CHERRYUSB_DEVICE_CHIPIDEA_MCX
@@ -123,55 +125,109 @@ if CHERRYUSB
prompt "Enable usb mtp device, it is commercial charge"
default n
config CHERRYUSB_DEVICE_DFU
bool
prompt "Enable usb dfu device"
default n
config CHERRYUSB_DEVICE_ADB
bool
prompt "Enable usb adb device"
default n
config CHERRYUSB_DEVICE_DFU
bool
prompt "Enable usb dfu device"
default n
config USBDEV_REQUEST_BUFFER_LEN
int
prompt "Set device control transfer max buffer size"
default 512
config USBDEV_MSC_MAX_BUFSIZE
int
prompt "Set usb msc device max buffer size"
default 512
help
Set the maximum buffer size for usb msc device, it is used to transfer data.
you can change it to a larger value if you need larger speed but must be a power of blocksize.
config USBDEV_RNDIS_USING_LWIP
bool
prompt "Enable usb rndis device with lwip for lan"
default n
config USBDEV_CDC_ECM_USING_LWIP
bool
prompt "Enable usb cdc ecm device with lwip for lan"
default n
choice
prompt "Select usb device template"
prompt "Select usb device template, please select class driver first"
default CHERRYUSB_DEVICE_TEMPLATE_NONE
config CHERRYUSB_DEVICE_TEMPLATE_NONE
bool "none (Implement it yourself)"
bool
prompt "none (Implement it yourself)"
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
bool "cdc_acm"
bool
prompt "cdc_acm"
depends on CHERRYUSB_DEVICE_CDC_ACM
config CHERRYUSB_DEVICE_TEMPLATE_MSC
bool "msc"
bool
prompt "msc_ram"
depends on CHERRYUSB_DEVICE_MSC
config CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
bool "hid_keyboard"
bool
prompt "hid_keyboard"
depends on CHERRYUSB_DEVICE_HID
config CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE
bool "hid_mouse"
bool
prompt "hid_mouse"
depends on CHERRYUSB_DEVICE_HID
config CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM
bool "hid_custom"
bool
prompt "hid_custom"
depends on CHERRYUSB_DEVICE_HID
config CHERRYUSB_DEVICE_TEMPLATE_VIDEO
bool "video"
bool
prompt "video"
depends on CHERRYUSB_DEVICE_VIDEO
config CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER
bool "audio_v1_mic_speaker_multichan"
bool
prompt "audio_v1_mic_speaker_multichan"
depends on CHERRYUSB_DEVICE_AUDIO
config CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER
bool "audio_v2_mic_speaker_multichan"
bool
prompt "audio_v2_mic_speaker_multichan"
depends on CHERRYUSB_DEVICE_AUDIO
config CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS
bool "cdc_rndis"
bool
prompt "cdc_rndis"
depends on CHERRYUSB_DEVICE_CDC_RNDIS
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM
bool "cdc_ecm"
bool
prompt "cdc_ecm"
depends on CHERRYUSB_DEVICE_CDC_ECM
config CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM
bool "cdc_ncm"
bool
prompt "cdc_ncm"
depends on CHERRYUSB_DEVICE_CDC_NCM
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool "cdc_acm_msc"
bool
prompt "cdc_acm_msc"
depends on CHERRYUSB_DEVICE_CDC_ACM && CHERRYUSB_DEVICE_MSC
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID
bool "cdc_acm_msc_hid"
bool
prompt "cdc_acm_msc_hid"
depends on CHERRYUSB_DEVICE_CDC_ACM && CHERRYUSB_DEVICE_MSC && CHERRYUSB_DEVICE_HID
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1
bool "winusbv1"
bool
prompt "winusbv1"
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC
bool "winusbv2_cdc"
bool
prompt "winusbv2_cdc"
depends on CHERRYUSB_DEVICE_CDC_ACM
config CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID
bool "winusbv2_hid"
bool
prompt "winusbv2_hid"
depends on CHERRYUSB_DEVICE_HID
endchoice
endif
menuconfig CHERRYUSB_HOST
@@ -216,6 +272,8 @@ if CHERRYUSB
bool "musb_sunxi"
config CHERRYUSB_HOST_MUSB_BK
bool "musb_bk"
config CHERRYUSB_HOST_MUSB_SIFLI
bool "musb_sifli"
config CHERRYUSB_HOST_MUSB_CUSTOM
bool "musb_custom"
config CHERRYUSB_HOST_PUSB2
@@ -334,12 +392,27 @@ if CHERRYUSB
config USBHOST_PLATFORM_RTL8152
bool
config CHERRYUSB_HOST_TEMPLATE
bool
prompt "Use usb host template"
default n
config USBHOST_PSC_PRIO
int
prompt "Set hubport change thread priority, 0 is the max priority"
default 0
if CHERRYUSB_HOST_TEMPLATE
config USBHOST_PSC_STACKSIZE
int
prompt "Set hubport change thread stacksize"
default 4096
config USBHOST_REQUEST_BUFFER_LEN
int
prompt "Set host control transfer max buffer size"
default 512
config USBHOST_CONTROL_TRANSFER_TIMEOUT
int
prompt "Set host control transfer timeout, unit is ms"
default 500
menu "Select USB host template, please select class driver first"
config TEST_USBH_CDC_ACM
int
prompt "demo for test cdc acm"
@@ -355,7 +428,6 @@ if CHERRYUSB
prompt "demo for test msc"
default 0
depends on CHERRYUSB_HOST_MSC
endif
endmenu
endif
endif

View File

@@ -52,6 +52,8 @@ if RT_USING_CHERRYUSB
bool "musb_sunxi"
config RT_CHERRYUSB_DEVICE_MUSB_BK
bool "musb_bk"
config RT_CHERRYUSB_DEVICE_MUSB_SIFLI
bool "musb_sifli"
config RT_CHERRYUSB_DEVICE_MUSB_CUSTOM
bool "musb_custom"
config RT_CHERRYUSB_DEVICE_CHIPIDEA_MCX
@@ -125,50 +127,125 @@ if RT_USING_CHERRYUSB
prompt "Enable usb mtp device, it is commercial charge"
default n
config RT_CHERRYUSB_DEVICE_ADB
bool
prompt "Enable usb adb device"
default n
config RT_CHERRYUSB_DEVICE_DFU
bool
prompt "Enable usb dfu device"
default n
config RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV
bool
prompt "Enable chardev for cdc acm device"
default n
config CONFIG_USBDEV_REQUEST_BUFFER_LEN
int
prompt "Set device control transfer max buffer size"
default 512
config CONFIG_USBDEV_MSC_MAX_BUFSIZE
int
prompt "Set usb msc device max buffer size"
default 512
help
Set the maximum buffer size for usb msc device, it is used to transfer data.
you can change it to a larger value if you need larger speed but must be a power of blocksize.
config CONFIG_USBDEV_RNDIS_USING_LWIP
bool
prompt "Enable usb rndis device with lwip for lan"
default n
config CONFIG_USBDEV_CDC_ECM_USING_LWIP
bool
prompt "Enable usb cdc ecm device with lwip for lan"
default n
choice
prompt "Select usb device template"
prompt "Select usb device template, please select class driver first"
default RT_CHERRYUSB_DEVICE_TEMPLATE_NONE
config RT_CHERRYUSB_DEVICE_TEMPLATE_NONE
bool "none (Implement it yourself)"
bool
prompt "none (Implement it yourself)"
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
bool "cdc_acm"
bool
prompt "cdc_acm"
depends on RT_CHERRYUSB_DEVICE_CDC_ACM
config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC
bool "msc_ram"
bool
prompt "msc_ram"
depends on RT_CHERRYUSB_DEVICE_MSC
config RT_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
bool "msc_blkdev"
bool
prompt "msc_blkdev"
depends on RT_CHERRYUSB_DEVICE_MSC
config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
bool "hid_keyboard"
bool
prompt "hid_keyboard"
depends on RT_CHERRYUSB_DEVICE_HID
config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE
bool "hid_mouse"
bool
prompt "hid_mouse"
depends on RT_CHERRYUSB_DEVICE_HID
config RT_CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM
bool "hid_custom"
bool
prompt "hid_custom"
depends on RT_CHERRYUSB_DEVICE_HID
config RT_CHERRYUSB_DEVICE_TEMPLATE_VIDEO
bool "video"
bool
prompt "video"
depends on RT_CHERRYUSB_DEVICE_VIDEO
config RT_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER
bool "audio_v1_mic_speaker_multichan"
bool
prompt "audio_v1_mic_speaker_multichan"
depends on RT_CHERRYUSB_DEVICE_AUDIO
config RT_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER
bool "audio_v2_mic_speaker_multichan"
bool
prompt "audio_v2_mic_speaker_multichan"
depends on RT_CHERRYUSB_DEVICE_AUDIO
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS
bool "cdc_rndis"
bool
prompt "cdc_rndis"
depends on RT_CHERRYUSB_DEVICE_CDC_RNDIS
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM
bool "cdc_ecm"
bool
prompt "cdc_ecm"
depends on RT_CHERRYUSB_DEVICE_CDC_ECM
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM
bool "cdc_ncm"
bool
prompt "cdc_ncm"
depends on RT_CHERRYUSB_DEVICE_CDC_NCM
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool "cdc_acm_msc"
bool
prompt "cdc_acm_msc"
depends on RT_CHERRYUSB_DEVICE_CDC_ACM && RT_CHERRYUSB_DEVICE_MSC
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID
bool "cdc_acm_msc_hid"
bool
prompt "cdc_acm_msc_hid"
depends on RT_CHERRYUSB_DEVICE_CDC_ACM && RT_CHERRYUSB_DEVICE_MSC && RT_CHERRYUSB_DEVICE_HID
config RT_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1
bool "winusbv1"
bool
prompt "winusbv1"
config RT_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC
bool "winusbv2_cdc"
bool
prompt "winusbv2_cdc"
depends on RT_CHERRYUSB_DEVICE_CDC_ACM
config RT_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID
bool "winusbv2_hid"
bool
prompt "winusbv2_hid"
depends on RT_CHERRYUSB_DEVICE_HID
config RT_CHERRYUSB_DEVICE_TEMPLATE_ADB
bool
prompt "adb"
depends on RT_CHERRYUSB_DEVICE_ADB
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV
bool
prompt "cdc_acm_chardev"
depends on RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV
endchoice
config CONFIG_USBDEV_MSC_BLOCK_DEV_NAME
@@ -220,6 +297,8 @@ if RT_USING_CHERRYUSB
bool "musb_sunxi"
config RT_CHERRYUSB_HOST_MUSB_BK
bool "musb_bk"
config RT_CHERRYUSB_HOST_MUSB_SIFLI
bool "musb_sifli"
config RT_CHERRYUSB_HOST_MUSB_CUSTOM
bool "musb_custom"
config RT_CHERRYUSB_HOST_PUSB2
@@ -332,6 +411,26 @@ if RT_USING_CHERRYUSB
config CONFIG_USBHOST_PLATFORM_RTL8152
bool
config CONFIG_USBHOST_PSC_PRIO
int
prompt "Set hubport change thread priority, 0 is the max priority"
default 0
config CONFIG_USBHOST_PSC_STACKSIZE
int
prompt "Set hubport change thread stacksize"
default 4096
config CONFIG_USBHOST_REQUEST_BUFFER_LEN
int
prompt "Set host control transfer max buffer size"
default 512
config CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
int
prompt "Set host control transfer timeout, unit is ms"
default 500
config RT_LWIP_PBUF_POOL_BUFSIZE
int "The size of each pbuf in the pbuf pool"
range 1500 2000
@@ -342,23 +441,22 @@ if RT_USING_CHERRYUSB
depends on RT_CHERRYUSB_HOST_MSC
default "/"
config RT_CHERRYUSB_HOST_TEMPLATE
bool
prompt "Use usb host template"
default n
if RT_CHERRYUSB_HOST_TEMPLATE
config TEST_USBH_CDC_ACM
menu "Select USB host template, please select class driver first"
config CONFIG_TEST_USBH_CDC_ACM
int
prompt "demo for test cdc acm"
prompt "demo for test cdc acm, cannot enable this demo, we have used serial framework instead"
default 0
depends on CHERRYUSB_HOST_CDC_ACM
config TEST_USBH_HID
depends on RT_CHERRYUSB_HOST_CDC_ACM
config CONFIG_TEST_USBH_HID
int
prompt "demo for test hid"
default 0
depends on CHERRYUSB_HOST_HID
endif
depends on RT_CHERRYUSB_HOST_HID
config CONFIG_TEST_USBH_MSC
int
prompt "demo for test msc, cannot enable this demo, we have used dfs instead"
default 0
depends on RT_CHERRYUSB_HOST_MSC
endmenu
endif
endif

View File

@@ -53,6 +53,8 @@ if PKG_USING_CHERRYUSB
bool "musb_sunxi"
config PKG_CHERRYUSB_DEVICE_MUSB_BK
bool "musb_bk"
config PKG_CHERRYUSB_DEVICE_MUSB_SIFLI
bool "musb_sifli"
config PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM
bool "musb_custom"
config PKG_CHERRYUSB_DEVICE_CHIPIDEA_MCX
@@ -124,50 +126,125 @@ if PKG_USING_CHERRYUSB
prompt "Enable usb mtp device, it is commercial charge"
default n
config PKG_CHERRYUSB_DEVICE_ADB
bool
prompt "Enable usb adb device"
default n
config PKG_CHERRYUSB_DEVICE_DFU
bool
prompt "Enable usb dfu device"
default n
config PKG_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV
bool
prompt "Enable chardev for cdc acm device"
default n
config CONFIG_USBDEV_REQUEST_BUFFER_LEN
int
prompt "Set device control transfer max buffer size"
default 512
config CONFIG_USBDEV_MSC_MAX_BUFSIZE
int
prompt "Set usb msc device max buffer size"
default 512
help
Set the maximum buffer size for usb msc device, it is used to transfer data.
you can change it to a larger value if you need larger speed but must be a power of blocksize.
config CONFIG_USBDEV_RNDIS_USING_LWIP
bool
prompt "Enable usb rndis device with lwip for lan"
default n
config CONFIG_USBDEV_CDC_ECM_USING_LWIP
bool
prompt "Enable usb cdc ecm device with lwip for lan"
default n
choice
prompt "Select usb device template"
prompt "Select usb device template, please select class driver first"
default PKG_CHERRYUSB_DEVICE_TEMPLATE_NONE
config PKG_CHERRYUSB_DEVICE_TEMPLATE_NONE
bool "none (Implement it yourself)"
bool
prompt "none (Implement it yourself)"
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM
bool "cdc_acm"
bool
prompt "cdc_acm"
depends on PKG_CHERRYUSB_DEVICE_CDC_ACM
config PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC
bool "msc_ram"
bool
prompt "msc_ram"
depends on PKG_CHERRYUSB_DEVICE_MSC
config PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV
bool "msc_blkdev"
bool
prompt "msc_blkdev"
depends on PKG_CHERRYUSB_DEVICE_MSC
config PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD
bool "hid_keyboard"
bool
prompt "hid_keyboard"
depends on PKG_CHERRYUSB_DEVICE_HID
config PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE
bool "hid_mouse"
bool
prompt "hid_mouse"
depends on PKG_CHERRYUSB_DEVICE_HID
config PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_CUSTOM
bool "hid_custom"
bool
prompt "hid_custom"
depends on PKG_CHERRYUSB_DEVICE_HID
config PKG_CHERRYUSB_DEVICE_TEMPLATE_VIDEO
bool "video"
bool
prompt "video"
depends on PKG_CHERRYUSB_DEVICE_VIDEO
config PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V1_MIC_SPEAKER
bool "audio_v1_mic_speaker_multichan"
bool
prompt "audio_v1_mic_speaker_multichan"
depends on PKG_CHERRYUSB_DEVICE_AUDIO
config PKG_CHERRYUSB_DEVICE_TEMPLATE_AUDIO_V2_MIC_SPEAKER
bool "audio_v2_mic_speaker_multichan"
bool
prompt "audio_v2_mic_speaker_multichan"
depends on PKG_CHERRYUSB_DEVICE_AUDIO
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_RNDIS
bool "cdc_rndis"
bool
prompt "cdc_rndis"
depends on PKG_CHERRYUSB_DEVICE_CDC_RNDIS
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ECM
bool "cdc_ecm"
bool
prompt "cdc_ecm"
depends on PKG_CHERRYUSB_DEVICE_CDC_ECM
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM
bool "cdc_ncm"
bool
prompt "cdc_ncm"
depends on PKG_CHERRYUSB_DEVICE_CDC_NCM
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool "cdc_acm_msc"
bool
prompt "cdc_acm_msc"
depends on PKG_CHERRYUSB_DEVICE_CDC_ACM && PKG_CHERRYUSB_DEVICE_MSC
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID
bool "cdc_acm_msc_hid"
bool
prompt "cdc_acm_msc_hid"
depends on PKG_CHERRYUSB_DEVICE_CDC_ACM && PKG_CHERRYUSB_DEVICE_MSC && PKG_CHERRYUSB_DEVICE_HID
config PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV1
bool "winusbv1"
bool
prompt "winusbv1"
config PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_CDC
bool "winusbv2_cdc"
bool
prompt "winusbv2_cdc"
depends on PKG_CHERRYUSB_DEVICE_CDC_ACM
config PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID
bool "winusbv2_hid"
bool
prompt "winusbv2_hid"
depends on PKG_CHERRYUSB_DEVICE_HID
config PKG_CHERRYUSB_DEVICE_TEMPLATE_ADB
bool
prompt "adb"
depends on PKG_CHERRYUSB_DEVICE_ADB
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV
bool
prompt "cdc_acm_chardev"
depends on PKG_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV
endchoice
config CONFIG_USBDEV_MSC_BLOCK_DEV_NAME
@@ -219,6 +296,8 @@ if PKG_USING_CHERRYUSB
bool "musb_sunxi"
config PKG_CHERRYUSB_HOST_MUSB_BK
bool "musb_bk"
config PKG_CHERRYUSB_HOST_MUSB_SIFLI
bool "musb_sifli"
config PKG_CHERRYUSB_HOST_MUSB_CUSTOM
bool "musb_custom"
config PKG_CHERRYUSB_HOST_PUSB2
@@ -331,6 +410,26 @@ if PKG_USING_CHERRYUSB
config CONFIG_USBHOST_PLATFORM_RTL8152
bool
config CONFIG_USBHOST_PSC_PRIO
int
prompt "Set hubport change thread priority, 0 is the max priority"
default 0
config CONFIG_USBHOST_PSC_STACKSIZE
int
prompt "Set hubport change thread stacksize"
default 4096
config CONFIG_USBHOST_REQUEST_BUFFER_LEN
int
prompt "Set host control transfer max buffer size"
default 512
config CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
int
prompt "Set host control transfer timeout, unit is ms"
default 500
config RT_LWIP_PBUF_POOL_BUFSIZE
int "The size of each pbuf in the pbuf pool"
range 1500 2000
@@ -341,23 +440,23 @@ if PKG_USING_CHERRYUSB
depends on RT_CHERRYUSB_HOST_MSC
default "/"
config PKG_CHERRYUSB_HOST_TEMPLATE
bool
prompt "Use usb host template"
default n
if PKG_CHERRYUSB_HOST_TEMPLATE
config TEST_USBH_CDC_ACM
menu "Select USB host template, please select class driver first"
config CONFIG_TEST_USBH_CDC_ACM
int
prompt "demo for test cdc acm"
prompt "demo for test cdc acm, cannot enable this demo, we have used serial framework instead"
default 0
depends on PKG_CHERRYUSB_HOST_CDC_ACM
config TEST_USBH_HID
config CONFIG_TEST_USBH_HID
int
prompt "demo for test hid"
default 0
depends on PKG_CHERRYUSB_HOST_HID
endif
config CONFIG_TEST_USBH_MSC
int
prompt "demo for test msc, cannot enable this demo, we have used dfs instead"
default 0
depends on PKG_CHERRYUSB_HOST_MSC
endmenu
endif
config PKG_CHERRYUSB_PATH
@@ -372,18 +471,14 @@ if PKG_USING_CHERRYUSB
config PKG_USING_CHERRYUSB_LATEST_VERSION
bool "latest"
config PKG_USING_CHERRYUSB_V010501
bool "v1.5.1"
config PKG_USING_CHERRYUSB_V010500
bool "v1.5.0"
config PKG_USING_CHERRYUSB_V010403
bool "v1.4.3"
config PKG_USING_CHERRYUSB_V010402
bool "v1.4.2"
config PKG_USING_CHERRYUSB_V010400
bool "v1.4.0"
config PKG_USING_CHERRYUSB_V010301
bool "v1.3.1"
config PKG_USING_CHERRYUSB_V010300
bool "v1.3.0"
config PKG_USING_CHERRYUSB_V010200
bool "v1.2.0"
config PKG_USING_CHERRYUSB_V001002
@@ -393,12 +488,10 @@ if PKG_USING_CHERRYUSB
config PKG_CHERRYUSB_VER
string
default "latest" if PKG_USING_CHERRYUSB_LATEST_VERSION
default "v1.5.1" if PKG_USING_CHERRYUSB_V010501
default "v1.5.0" if PKG_USING_CHERRYUSB_V010500
default "v1.4.3" if PKG_USING_CHERRYUSB_V010403
default "v1.4.2" if PKG_USING_CHERRYUSB_V010402
default "v1.4.0" if PKG_USING_CHERRYUSB_V010400
default "v1.3.1" if PKG_USING_CHERRYUSB_V010301
default "v1.3.0" if PKG_USING_CHERRYUSB_V010300
default "v1.2.0" if PKG_USING_CHERRYUSB_V010200
default "v0.10.2" if PKG_USING_CHERRYUSB_V001002
endif

View File

@@ -70,6 +70,9 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_BK']):
src += Glob('port/musb/usb_dc_musb.c')
src += Glob('port/musb/usb_glue_bk.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SIFLI']):
src += Glob('port/musb/usb_dc_musb.c')
src += Glob('port/musb/usb_glue_sifli.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_CUSTOM']):
src += Glob('port/musb/usb_dc_musb.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CHIPIDEA_MCX']):
@@ -127,13 +130,17 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('class/cdc/usbd_cdc_ncm.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DFU']):
src += Glob('class/dfu/usbd_dfu.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_ADB']):
src += Glob('class/adb/usbd_adb.c')
src += Glob('platform/rtthread/usbd_adb_shell.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV']):
src += Glob('platform/rtthread/usbd_serial.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']):
src += Glob('demo/cdc_acm_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC']) or GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV']):
src += Glob('demo/msc_ram_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_MSC_BLKDEV']):
src += Glob('platform/rtthread/usbd_msc_blkdev.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_MOUSE']):
src += Glob('demo/hid_mouse_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_HID_KEYBOARD']):
@@ -162,6 +169,10 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('demo/winusb2.0_cdc_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WINUSBV2_HID']):
src += Glob('demo/winusb2.0_hid_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_ADB']):
src += Glob('demo/adb/usbd_adb_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV']):
src += Glob('demo/cdc_acm_rttchardev_template.c')
# USB HOST
if GetDepend(['PKG_CHERRYUSB_HOST']):
@@ -222,6 +233,9 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_BK']):
src += Glob('port/musb/usb_hc_musb.c')
src += Glob('port/musb/usb_glue_bk.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SIFLI']):
src += Glob('port/musb/usb_hc_musb.c')
src += Glob('port/musb/usb_glue_sifli.c')
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']):
src += Glob('port/musb/usb_hc_musb.c')
if GetDepend(['PKG_CHERRYUSB_HOST_KINETIS_MCX']):
@@ -281,10 +295,16 @@ if GetDepend(['PKG_CHERRYUSB_HOST']):
if GetDepend(['PKG_CHERRYUSB_HOST_PL2303']):
src += Glob('class/vendor/serial/usbh_pl2303.c')
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
CPPDEFINES+=['TEST_USBH_MSC=0']
if GetDepend(['CONFIG_TEST_USBH_HID']):
src += Glob('demo/usb_host.c')
if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ACM']) \
or GetDepend(['PKG_CHERRYUSB_HOST_FTDI']) \
or GetDepend(['PKG_CHERRYUSB_HOST_CH34X']) \
or GetDepend(['PKG_CHERRYUSB_HOST_CP210X']) \
or GetDepend(['PKG_CHERRYUSB_HOST_PL2303']):
src += Glob('platform/rtthread/usbh_serial.c')
if GetDepend('RT_USING_DFS') and GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
src += Glob('platform/rtthread/usbh_dfs.c')

View File

@@ -1,5 +1,5 @@
VERSION_MAJOR = 1
VERSION_MINOR = 5
PATCHLEVEL = 0
PATCHLEVEL = 1
VERSION_TWEAK = 0
EXTRAVERSION = 0

View File

@@ -120,6 +120,9 @@ if(CONFIG_CHERRYUSB_DEVICE)
elseif(CONFIG_CHERRYUSB_DEVICE_MUSB_BK)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
elseif(CONFIG_CHERRYUSB_DEVICE_MUSB_SIFLI)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_sifli.c)
elseif(CONFIG_CHERRYUSB_DEVICE_MUSB_CUSTOM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c)
elseif(CONFIG_CHERRYUSB_DEVICE_CHIPIDEA_MCX)
@@ -316,6 +319,9 @@ if(CONFIG_CHERRYUSB_HOST)
elseif(CONFIG_CHERRYUSB_HOST_MUSB_BK)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
elseif(CONFIG_CHERRYUSB_HOST_MUSB_SIFLI)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_sifli.c)
elseif(CONFIG_CHERRYUSB_HOST_MUSB_CUSTOM)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_hc_musb.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_glue_bk.c)
@@ -329,7 +335,7 @@ if(CONFIG_CHERRYUSB_HOST)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_hc_rp2040.c)
endif()
if(CHERRYUSB_HOST_TEMPLATE)
if(CONFIG_TEST_USBH_CDC_ACM OR CONFIG_TEST_USBH_HID OR CONFIG_TEST_USBH_MSC)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/demo/usb_host.c)
endif()
endif()

View File

@@ -47,9 +47,6 @@
#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512
#endif
/* Setup packet log for debug */
// #define CONFIG_USBDEV_SETUP_LOG_PRINT
/* Send ep0 in data from user buffer instead of copying into ep0 reqdata
* Please note that user buffer must be aligned with CONFIG_USB_ALIGN_SIZE
*/
@@ -262,28 +259,20 @@
// #define CONFIG_USBDEV_SOF_ENABLE
/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode, the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS. */
/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode,
* the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS.
*
* in xxx32 chips, only pb14/pb15 can support hs mode, pa11/pa12 is not supported(only a few supports, but we ignore them).
*/
// #define CONFIG_USB_HS
/* ---------------- FSDEV Configuration ---------------- */
//#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference
/* ---------------- DWC2 Configuration ---------------- */
/* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for
* status information) + (2 * number of OUT endpoints) + 1 for Global NAK
*/
// #define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
/* IN Endpoints Max packet Size / 4 */
// #define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX1_FIFO_SIZE (1024 / 4)
// #define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
// #define CONFIG_USB_DWC2_TX4_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX5_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX6_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
// #define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
/* enable dwc2 buffer dma mode for device
* in xxx32 chips, only pb14/pb15 can support dma mode, pa11/pa12 is not supported(only a few supports, but we ignore them)
*/
// #define CONFIG_USB_DWC2_DMA_ENABLE
/* ---------------- MUSB Configuration ---------------- */
@@ -320,17 +309,6 @@
/* ---------------- XHCI Configuration ---------------- */
#define CONFIG_USB_XHCI_HCCR_OFFSET (0x0)
/* ---------------- DWC2 Configuration ---------------- */
/* largest non-periodic USB packet used / 4 */
// #define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (512 / 4)
/* largest periodic USB packet used / 4 */
// #define CONFIG_USB_DWC2_PTX_FIFO_SIZE (1024 / 4)
/*
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
*/
// #define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
/* ---------------- MUSB Configuration ---------------- */
// #define CONFIG_USB_MUSB_SUNXI

View File

@@ -416,7 +416,7 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed), hub_int_timeout, hub, 0);
hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed) / 1000, hub_int_timeout, hub, 0);
if (hub->int_timer == NULL) {
USB_LOG_ERR("No memory to alloc int_timer\r\n");
return -USB_ERR_NOMEM;

View File

@@ -675,9 +675,8 @@ struct mtp_object {
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x1c, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x06 /* bLength */
WBVAL(0x1c), /* wMaxPacketSize */ \
0x06 /* bInterval */
// clang-format on
#endif

View File

@@ -36,6 +36,9 @@ struct usbd_interface *usbd_mtp_init_intf(struct usbd_interface *intf,
const uint8_t in_ep,
const uint8_t int_ep);
int usbd_mtp_notify_object_add(const char *path);
int usbd_mtp_notify_object_remove(const char *path);
const char *usbd_mtp_fs_root_path(void);
const char *usbd_mtp_fs_description(void);

View File

@@ -350,6 +350,7 @@ static int usbh_ftdi_connect(struct usbh_hubport *hport, uint8_t intf)
switch (version) {
case 0x400:
ftdi_class->chip_type = FT232B;
break;
case 0x500:
ftdi_class->chip_type = FT2232C;
break;

View File

@@ -15,7 +15,7 @@
#undef CHERRYUSB_VERSION_STR
#endif
#define CHERRYUSB_VERSION 0x010500
#define CHERRYUSB_VERSION_STR "v1.5.0"
#define CHERRYUSB_VERSION 0x010501
#define CHERRYUSB_VERSION_STR "v1.5.1"
#endif

View File

@@ -83,8 +83,8 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
uint8_t intf_altsetting[16];
uint8_t intf_offset;
struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_EP_NUM];
struct usbd_tx_rx_msg rx_msg[CONFIG_USBDEV_EP_NUM];
struct usbd_tx_rx_msg tx_msg[16];
struct usbd_tx_rx_msg rx_msg[16];
void (*event_handler)(uint8_t busid, uint8_t event);
} g_usbd_core[CONFIG_USBDEV_MAX_BUS];
@@ -95,15 +95,25 @@ static void usbd_class_event_notify_handler(uint8_t busid, uint8_t event, void *
static void usbd_print_setup(struct usb_setup_packet *setup)
{
USB_LOG_INFO("Setup: "
"bmRequestType 0x%02x, bRequest 0x%02x, wValue 0x%04x, wIndex 0x%04x, wLength 0x%04x\r\n",
setup->bmRequestType,
setup->bRequest,
setup->wValue,
setup->wIndex,
setup->wLength);
USB_LOG_ERR("Setup: "
"bmRequestType 0x%02x, bRequest 0x%02x, wValue 0x%04x, wIndex 0x%04x, wLength 0x%04x\r\n",
setup->bmRequestType,
setup->bRequest,
setup->wValue,
setup->wIndex,
setup->wLength);
}
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_LOG)
static const char *usb_ep0_state_string[] = {
"setup",
"indata",
"outdata",
"instatus",
"outstatus"
};
#endif
static bool is_device_configured(uint8_t busid)
{
return (g_usbd_core[busid].configuration != 0);
@@ -524,8 +534,6 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
if_desc = (void *)p;
}
USB_LOG_DBG("Current iface %u alt setting %u",
cur_iface, cur_alt_setting);
break;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
@@ -1171,9 +1179,14 @@ static void __usbd_event_ep0_setup_complete_handler(uint8_t busid, struct usb_se
{
uint8_t *buf;
#ifdef CONFIG_USBDEV_SETUP_LOG_PRINT
usbd_print_setup(setup);
#endif
USB_LOG_DBG("[%s] 0x%02x 0x%02x 0x%04x 0x%04x 0x%04x\r\n",
usb_ep0_state_string[usbd_get_ep0_next_state(busid)],
setup->bmRequestType,
setup->bRequest,
setup->wValue,
setup->wIndex,
setup->wLength);
if (setup->wLength > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
if ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT) {
USB_LOG_ERR("Request buffer too small\r\n");
@@ -1240,7 +1253,6 @@ static void __usbd_event_ep0_setup_complete_handler(uint8_t busid, struct usb_se
*/
if ((setup->wLength > g_usbd_core[busid].ep0_data_buf_len) && (!(g_usbd_core[busid].ep0_data_buf_len % USB_CTRL_EP_MPS))) {
g_usbd_core[busid].zlp_flag = true;
USB_LOG_DBG("EP0 Set zlp\r\n");
}
}
@@ -1266,7 +1278,10 @@ static void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32
g_usbd_core[busid].ep0_data_buf += nbytes;
g_usbd_core[busid].ep0_data_buf_residue -= nbytes;
USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", (unsigned int)nbytes, (unsigned int)g_usbd_core[busid].ep0_data_buf_residue);
USB_LOG_DBG("[%s] in %d bytes, %d remained\r\n",
usb_ep0_state_string[usbd_get_ep0_next_state(busid)],
(unsigned int)nbytes,
(unsigned int)g_usbd_core[busid].ep0_data_buf_residue);
if (g_usbd_core[busid].ep0_data_buf_residue != 0) {
/* Start sending the remain data */
@@ -1311,12 +1326,15 @@ static void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint3
(void)ep;
(void)setup;
USB_LOG_DBG("[%s] out %d bytes, %d remained\r\n",
usb_ep0_state_string[usbd_get_ep0_next_state(busid)],
(unsigned int)nbytes,
(unsigned int)g_usbd_core[busid].ep0_data_buf_residue);
if (nbytes > 0) {
g_usbd_core[busid].ep0_data_buf += nbytes;
g_usbd_core[busid].ep0_data_buf_residue -= nbytes;
USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", (unsigned int)nbytes, (unsigned int)g_usbd_core[busid].ep0_data_buf_residue);
if (g_usbd_core[busid].ep0_data_buf_residue == 0) {
#ifdef CONFIG_USBDEV_EP0_THREAD
usb_osal_mq_send(g_usbd_core[busid].usbd_ep0_mq, USB_EP0_STATE_OUT);
@@ -1338,9 +1356,8 @@ static void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint3
usbd_ep_start_read(busid, USB_CONTROL_OUT_EP0, g_usbd_core[busid].ep0_data_buf, g_usbd_core[busid].ep0_data_buf_residue);
}
} else {
g_usbd_core[busid].ep0_next_state = USBD_EP0_STATE_SETUP;
/* Read out status completely, do nothing */
USB_LOG_DBG("EP0 recv out status\r\n");
g_usbd_core[busid].ep0_next_state = USBD_EP0_STATE_SETUP;
}
}

View File

@@ -47,7 +47,7 @@ extern "C" {
#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
#endif
#define USBH_GET_URB_INTERVAL(interval, speed) (speed < USB_SPEED_HIGH ? interval : (1 << (interval - 1)))
#define USBH_GET_URB_INTERVAL(interval, speed) (speed < USB_SPEED_HIGH ? (interval * 1000) : ((1 << (interval - 1)) * 125))
#define USBH_EP_INIT(ep, ep_desc) \
do { \

View File

@@ -164,7 +164,7 @@ static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
return string_descriptors[index];
}
const struct usb_descriptor msc_bootuf2_descriptor = {
const struct usb_descriptor adb_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
@@ -274,9 +274,16 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
static struct usbd_interface intf0;
#ifdef RT_USING_MSH
extern void usbd_adb_shell_init(uint8_t in_ep, uint8_t out_ep);
#else
extern int shell_init(bool need_login);
#endif
void cherryadb_init(uint8_t busid, uint32_t reg_base)
{
#ifdef RT_USING_MSH
usbd_adb_shell_init(WINUSB_IN_EP, WINUSB_OUT_EP);
#else
/* default password is : 12345678 */
/* shell_init() must be called in-task */
if (0 != shell_init(false)) {
@@ -286,7 +293,7 @@ void cherryadb_init(uint8_t busid, uint32_t reg_base)
;
}
}
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &adb_descriptor);
#else

View File

@@ -8,10 +8,6 @@
#include "usbd_cdc_acm.h"
#include "usbd_hid.h"
#if CONFIG_USBDEV_EP_NUM < 7
#error endpoint number is too small for this demo, please try other chips
#endif
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02

View File

@@ -0,0 +1,337 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_acm.h"
#include "chry_ringbuffer.h"
#include <mavlink.h>
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02
#define CDC_INT_EP 0x83
#define USBD_VID 0xFFFF
#define USBD_PID 0xFFFF
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
static const uint8_t cdc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x26, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
' ', 0x00, /* wcChar9 */
'C', 0x00, /* wcChar10 */
'D', 0x00, /* wcChar11 */
'C', 0x00, /* wcChar12 */
' ', 0x00, /* wcChar13 */
'D', 0x00, /* wcChar14 */
'E', 0x00, /* wcChar15 */
'M', 0x00, /* wcChar16 */
'O', 0x00, /* wcChar17 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x16, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
chry_ringbuffer_t usb_rx_rb;
uint8_t usb_rx_buffer[2048];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t temp_rx_buffer[512];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t usb_tx_buffer[MAVLINK_MAX_PACKET_LEN];
volatile bool ep_tx_busy_flag = false;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
ep_tx_busy_flag = false;
/* setup first out ep read transfer */
usbd_ep_start_read(busid, CDC_OUT_EP, temp_rx_buffer, usbd_get_ep_mps(busid, CDC_OUT_EP));
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
chry_ringbuffer_write(&usb_rx_rb, temp_rx_buffer, nbytes);
usbd_ep_start_read(busid, CDC_OUT_EP, temp_rx_buffer, usbd_get_ep_mps(busid, CDC_OUT_EP));
}
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);
} else {
ep_tx_busy_flag = false;
}
}
/*!< endpoint call back */
struct usbd_endpoint cdc_out_ep = {
.ep_addr = CDC_OUT_EP,
.ep_cb = usbd_cdc_acm_bulk_out
};
struct usbd_endpoint cdc_in_ep = {
.ep_addr = CDC_IN_EP,
.ep_cb = usbd_cdc_acm_bulk_in
};
static struct usbd_interface intf0;
static struct usbd_interface intf1;
void cdc_acm_mavlink_init(uint8_t busid, uintptr_t reg_base)
{
chry_ringbuffer_init(&usb_rx_rb, usb_rx_buffer, sizeof(usb_rx_buffer));
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_descriptor);
#else
usbd_desc_register(busid, cdc_descriptor);
#endif
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf0));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &intf1));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void cdc_acm_mavlink_write(uint8_t *data, uint32_t len)
{
if (!usb_device_is_configured(0)) {
return;
}
ep_tx_busy_flag = true;
usbd_ep_start_write(0, CDC_IN_EP, data, len);
while (ep_tx_busy_flag) {
}
}
void send_heartbeat(void)
{
mavlink_message_t message;
const uint8_t system_id = 42;
const uint8_t base_mode = 0;
const uint8_t custom_mode = 0;
mavlink_msg_heartbeat_pack_chan(
system_id,
MAV_COMP_ID_PERIPHERAL,
MAVLINK_COMM_0,
&message,
MAV_TYPE_GENERIC,
MAV_AUTOPILOT_GENERIC,
base_mode,
custom_mode,
MAV_STATE_STANDBY);
const int len = mavlink_msg_to_send_buffer(usb_tx_buffer, &message);
cdc_acm_mavlink_write(usb_tx_buffer, len);
}
void handle_heartbeat(const mavlink_message_t *message)
{
mavlink_heartbeat_t heartbeat;
mavlink_msg_heartbeat_decode(message, &heartbeat);
USB_LOG_RAW("Got heartbeat from ");
switch (heartbeat.autopilot) {
case MAV_AUTOPILOT_GENERIC:
USB_LOG_RAW("generic");
break;
case MAV_AUTOPILOT_ARDUPILOTMEGA:
USB_LOG_RAW("ArduPilot");
break;
case MAV_AUTOPILOT_PX4:
USB_LOG_RAW("PX4");
break;
default:
USB_LOG_RAW("other");
break;
}
USB_LOG_RAW(" autopilot\n");
send_heartbeat();
}
void mavlink_polling(void)
{
uint8_t ch;
bool ret;
mavlink_message_t message;
mavlink_status_t status;
ret = chry_ringbuffer_read_byte(&usb_rx_rb, &ch);
if (ret) {
if (mavlink_parse_char(MAVLINK_COMM_0, ch, &message, &status) == 1) {
USB_LOG_INFO(
"Received message %d from %d/%d\n",
message.msgid, message.sysid, message.compid);
switch (message.msgid) {
case MAVLINK_MSG_ID_HEARTBEAT:
handle_heartbeat(&message);
break;
}
}
}
}

View File

@@ -7,10 +7,6 @@
#include "usbd_cdc_acm.h"
#include "usbd_msc.h"
#if CONFIG_USBDEV_EP_NUM < 6
#error endpoint number is too small for this demo, please try other chips
#endif
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02

View File

@@ -6,10 +6,6 @@
#include "usbd_core.h"
#include "usbd_cdc_acm.h"
#if CONFIG_USBDEV_EP_NUM < 8
#error endpoint number is too small for this demo, please try other chips
#endif
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x01

View File

@@ -0,0 +1,208 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_cdc_acm.h"
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02
#define CDC_INT_EP 0x83
#define USBD_VID 0xFFFF
#define USBD_PID 0xFFFF
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
#ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512
#else
#define CDC_MAX_MPS 64
#endif
#ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02)
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB CDC DEMO", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index > 3) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor cdc_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
#else
/*!< global descriptor */
static const uint8_t cdc_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02),
///////////////////////////////////////
/// string0 descriptor
///////////////////////////////////////
USB_LANGID_INIT(USBD_LANGID_STRING),
///////////////////////////////////////
/// string1 descriptor
///////////////////////////////////////
0x14, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
///////////////////////////////////////
/// string2 descriptor
///////////////////////////////////////
0x26, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'C', 0x00, /* wcChar0 */
'h', 0x00, /* wcChar1 */
'e', 0x00, /* wcChar2 */
'r', 0x00, /* wcChar3 */
'r', 0x00, /* wcChar4 */
'y', 0x00, /* wcChar5 */
'U', 0x00, /* wcChar6 */
'S', 0x00, /* wcChar7 */
'B', 0x00, /* wcChar8 */
' ', 0x00, /* wcChar9 */
'C', 0x00, /* wcChar10 */
'D', 0x00, /* wcChar11 */
'C', 0x00, /* wcChar12 */
' ', 0x00, /* wcChar13 */
'D', 0x00, /* wcChar14 */
'E', 0x00, /* wcChar15 */
'M', 0x00, /* wcChar16 */
'O', 0x00, /* wcChar17 */
///////////////////////////////////////
/// string3 descriptor
///////////////////////////////////////
0x16, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
#ifdef CONFIG_USB_HS
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
#endif
0x00
};
#endif
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
extern void usbd_cdc_acm_serial_init(uint8_t busid, uint8_t in_ep, uint8_t out_ep);
void cdc_acm_chardev_init(uint8_t busid, uintptr_t reg_base)
{
#ifdef CONFIG_USBDEV_ADVANCE_DESC
usbd_desc_register(busid, &cdc_descriptor);
#else
usbd_desc_register(busid, cdc_descriptor);
#endif
usbd_cdc_acm_serial_init(busid, CDC_IN_EP, CDC_OUT_EP);
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -10,17 +10,17 @@
#include "usbh_video.h"
#include "usbh_audio.h"
#ifndef TEST_USBH_CDC_ACM
#define TEST_USBH_CDC_ACM 1
#ifndef CONFIG_TEST_USBH_CDC_ACM
#define CONFIG_TEST_USBH_CDC_ACM 1
#endif
#ifndef TEST_USBH_CDC_SPEED
#define TEST_USBH_CDC_SPEED 0
#endif
#ifndef TEST_USBH_HID
#define TEST_USBH_HID 1
#ifndef CONFIG_TEST_USBH_HID
#define CONFIG_TEST_USBH_HID 1
#endif
#ifndef TEST_USBH_MSC
#define TEST_USBH_MSC 1
#ifndef CONFIG_TEST_USBH_MSC
#define CONFIG_TEST_USBH_MSC 1
#endif
#ifndef TEST_USBH_MSC_FATFS
#define TEST_USBH_MSC_FATFS 0
@@ -28,18 +28,18 @@
#ifndef TEST_USBH_MSC_FATFS_SPEED
#define TEST_USBH_MSC_FATFS_SPEED 0
#endif
#ifndef TEST_USBH_AUDIO
#define TEST_USBH_AUDIO 0
#ifndef CONFIG_TEST_USBH_AUDIO
#define CONFIG_TEST_USBH_AUDIO 0
#endif
#ifndef TEST_USBH_VIDEO
#define TEST_USBH_VIDEO 0
#ifndef CONFIG_TEST_USBH_VIDEO
#define CONFIG_TEST_USBH_VIDEO 0
#endif
#if defined(TEST_USBH_CDC_ECM) || defined(TEST_USBH_CDC_RNDIS) || defined(TEST_USBH_ASIX) || defined(TEST_USBH_RTL8152)
#error we have move those class implements into platform/none/usbh_lwip.c, and you should call tcpip_init(NULL, NULL) in your app
#endif
#if TEST_USBH_CDC_ACM
#if CONFIG_TEST_USBH_CDC_ACM
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_buffer[4096];
#if TEST_USBH_CDC_SPEED
@@ -115,7 +115,7 @@ delete:
}
#endif
#if TEST_USBH_HID
#if CONFIG_TEST_USBH_HID
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t hid_buffer[128];
void usbh_hid_callback(void *arg, int nbytes)
@@ -157,7 +157,7 @@ delete:
}
#endif
#if TEST_USBH_MSC
#if CONFIG_TEST_USBH_MSC
#if TEST_USBH_MSC_FATFS
#include "ff.h"
@@ -326,7 +326,7 @@ delete:
}
#endif
#if TEST_USBH_CDC_ACM
#if CONFIG_TEST_USBH_CDC_ACM
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, cdc_acm_class);
@@ -337,7 +337,7 @@ void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
}
#endif
#if TEST_USBH_HID
#if CONFIG_TEST_USBH_HID
void usbh_hid_run(struct usbh_hid *hid_class)
{
usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, hid_class);
@@ -348,7 +348,7 @@ void usbh_hid_stop(struct usbh_hid *hid_class)
}
#endif
#if TEST_USBH_MSC
#if CONFIG_TEST_USBH_MSC
void usbh_msc_run(struct usbh_msc *msc_class)
{
usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
@@ -359,11 +359,11 @@ void usbh_msc_stop(struct usbh_msc *msc_class)
}
#endif
#if TEST_USBH_AUDIO
#if CONFIG_TEST_USBH_AUDIO
#error "commercial charge"
#endif
#if TEST_USBH_VIDEO
#if CONFIG_TEST_USBH_VIDEO
#error "commercial charge"
#endif

View File

@@ -135,7 +135,7 @@ uint8_t USBD_BinaryObjectStoreDescriptor[USBD_BOS_WTOTALLENGTH] = {
struct usb_webusb_descriptor webusb_url_desc = {
.vendor_code = USBD_WEBUSB_VENDOR_CODE,
.string = USBD_WebUSBURLDescriptor,
.string_len = USBD_WINUSB_DESC_SET_LEN
.string_len = URL_DESCRIPTOR_LENGTH
};
struct usb_msosv2_descriptor msosv2_desc = {

View File

@@ -6,10 +6,6 @@
#include "usbd_core.h"
#include "usbd_cdc_acm.h"
#if CONFIG_USBDEV_EP_NUM < 6
#error endpoint number is too small for this demo, please try other chips
#endif
#define WINUSB_IN_EP 0x81
#define WINUSB_OUT_EP 0x02

View File

@@ -6,10 +6,6 @@
#include "usbd_core.h"
#include "usbd_hid.h"
#if CONFIG_USBDEV_EP_NUM < 4
#error endpoint number is too small for this demo, please try other chips
#endif
#define WINUSB_IN_EP 0x81
#define WINUSB_OUT_EP 0x02

View File

@@ -7,6 +7,10 @@
- 有多少个接口就调用多少次 `usbd_add_interface`,参数填相关 `xxx_init_intf`, 如果没有支持的,手动创建一个 intf 填入
- 有多少个端点就调用多少次 `usbd_add_endpoint`,当中断完成时,会调用到注册的端点回调中。
参考下面这张图:
.. figure:: img/api_device1.png
CORE
-----------------

View File

@@ -15,12 +15,11 @@ CLASS 驱动信息结构体
.. code-block:: C
struct usbh_class_info {
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
uint8_t class; /* Base device class code */
uint8_t subclass; /* Sub-class, depends on base class. Eg. */
uint8_t protocol; /* Protocol, depends on base class. Eg. */
uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
uint16_t pid; /* Product ID (for vendor/product specific devices) */
uint8_t match_flags; /* Used for product specific matches; range is inclusive */
uint8_t bInterfaceClass; /* Base device class code */
uint8_t bInterfaceSubClass; /* Sub-class, depends on base class. Eg. */
uint8_t bInterfaceProtocol; /* Protocol, depends on base class. Eg. */
const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */
const struct usbh_class_driver *class_driver;
};

View File

@@ -186,33 +186,36 @@ usbh_submit_urb
.. code-block:: C
struct usbh_urb {
void *hcpriv;
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *ep;
uint8_t data_toggle;
struct usb_setup_packet *setup;
uint8_t *transfer_buffer;
uint32_t transfer_buffer_length;
int transfer_flags;
uint32_t actual_length;
uint32_t timeout;
int errorcode;
uint32_t num_of_iso_packets;
uint32_t start_frame;
usbh_complete_callback_t complete;
void *arg;
#if defined(__ICCARM__) || defined(__ICCRISCV__) || defined(__ICCRX__)
struct usbh_iso_frame_packet *iso_packet;
#else
struct usbh_iso_frame_packet iso_packet[0];
#endif
};
struct usbh_urb {
usb_slist_t list;
void *hcpriv;
struct usbh_hubport *hport;
struct usb_endpoint_descriptor *ep;
uint8_t data_toggle;
uint8_t interval;
struct usb_setup_packet *setup;
uint8_t *transfer_buffer;
uint32_t transfer_buffer_length;
int transfer_flags;
uint32_t actual_length;
uint32_t timeout;
int errorcode;
uint32_t num_of_iso_packets;
uint32_t start_frame;
usbh_complete_callback_t complete;
void *arg;
#if defined(__ICCARM__) || defined(__ICCRISCV__) || defined(__ICCRX__)
struct usbh_iso_frame_packet *iso_packet;
#else
struct usbh_iso_frame_packet iso_packet[0];
#endif
};
- **hcpriv** 主机控制器驱动私有成员
- **hport** 当前 urb 使用的 hport
- **ep** 当前 urb 使用的 ep
- **data_toggle** 当前 data toggle
- **interval** urb 传输间隔,单位 us如果 interval 大于 1000us则需要使用软件定时器来维护
- **setup** setup 请求缓冲区端点0使用
- **transfer_buffer** 传输的数据缓冲区
- **transfer_buffer_length** 传输长度

View File

@@ -6,8 +6,8 @@ project = 'CherryUSB'
copyright = '2022 ~ 2025, sakumisu'
author = 'sakumisu'
release = '1.5.0'
version = '1.5.0'
release = '1.5.1'
version = '1.5.1'
# -- General configuration

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 KiB

View File

@@ -0,0 +1,28 @@
usbd_adb
===============
本节主要介绍如何使用 adb device。支持 **cherrysh** 和 rt-thread **msh**,只需要在 main 中添加以下初始化即可。
.. code-block:: C
cherryadb_init(0, xxxxx);
如果使用 rt-thread还需要在 menuconfig 中使能 adb device。
.. figure:: img/rtt_adb_shell1.png
进入 adb
--------------
- 使用 **cherrysh** 时枚举完成以后自动进入 adb 模式
- 使用 **msh** 需要在 **msh** 中输入 ``adb_enter`` 进入 adb 模式
退出 adb
--------------
- 使用 **cherrysh** 时输入 ``exit`` 退出 adb 模式
- 使用 **msh** 需要在 **msh** 中输入 ``adb_exit`` 退出 adb 模式
.. figure:: img/cherryadb.png
.. figure:: img/rtt_adb_shell2.png

View File

@@ -48,4 +48,8 @@ usbh_hid
.. code-block:: C
hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed), hub_int_timeout, hub, 0);
hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed) / 1000, hub_int_timeout, hub, 0);
.. note::
这里的 `USBH_GET_URB_INTERVAL` 是一个宏定义,用于根据 binterval 计算 URB 的传输间隔时间, 单位是 us而定时器最低是 ms ,因此需要除以 1000。对于小于等于 1ms 的不需要使用定时器。

View File

@@ -18,7 +18,7 @@ usbh_msc
- 不使用 fatfs则直接使用 usbh_msc_scsi_read10 或者 usbh_msc_scsi_write10 函数进行读写操作。
- 如果使用 fatfs则需要在 usbh_msc_thread 中调用 fatfs 的接口进行读写操作。msc读写适配fatfs 参考 `platform/none/usbh_fatfs.c`
- 如果使用 fatfs则需要在 usbh_msc_thread 中调用 fatfs 的接口进行读写操作。msc读写适配fatfs 参考 `platform/fatfs/usbh_fatfs.c`
.. code-block:: C

View File

@@ -104,3 +104,5 @@ TCPIP_THREAD_STACKSIZE 推荐大于 1K防止栈溢出。
#if TCPIP_THREAD_STACKSIZE < 1024
#error TCPIP_THREAD_STACKSIZE must be >= 1024
#endif
- 具体移植文章可以参考 https://club.rt-thread.org/ask/article/5cf3e9e0b2d95800.html

View File

@@ -1,2 +1,4 @@
usbh_serial
===============
当前仅支持 rt-thread device 框架,包括 cdc acm, ftdi, cp210x, ch34x, pl2303, 具体使用方式参考 rt-thread device api 即可。

View File

@@ -107,6 +107,7 @@ CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统的
demo/usbd_video
demo/usbd_winusb
demo/usbd_webusb
demo/usbd_adb
demo/usbh_serial
demo/usbh_hid
demo/usbh_msc

View File

@@ -15,7 +15,7 @@ Q & A
- 是否能进 USB 中断
- 芯片是否带有 cache功能是否做了 no cache 处理,截图
- 硬件是否正常,是否使用杜邦线连接,如果正常,请说明正常原因
- 打开 CONFIG_USBDEV_SETUP_LOG_PRINT并提供 log
- 配置 **#define CONFIG_USB_DBG_LEVEL USB_DBG_LOG** 并提供 log仅限商业 IP, 其余 IP 禁止开启 log否则无法枚举
- 是否流片并销售
其余问题提问模板

View File

@@ -177,6 +177,8 @@ USB Device 移植要点
.. figure:: img/stm32_13.png
- 如果芯片带 cachecache 修改参考 :ref:`usb_cache` 章节
- 调用 template 的内容初始化,并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBDEV_MAX_BUS`
.. figure:: img/stm32_15.png
@@ -212,13 +214,10 @@ USB Host 移植要点
- 拷贝 **xxx_msp.c** 中的 `HAL_HCD_MspInit` 函数中的内容到 `usb_hc_low_level_init` 函数中,屏蔽 st 生成的 usb 初始化
- 在中断函数中调用 `USBH_IRQHandler`,并传入 `busid`
- 链接脚本修改参考 :ref:`usbh_link_script` 章节
- 如果芯片带 cachecache 修改参考 :ref:`usb_cache` 章节
- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
- 启动线程
.. figure:: img/stm32_18.png
.. figure:: img/stm32_19.png
- 如果使用 **msc**,并且带文件系统,需要自行添加文件系统文件了,对应的 porting 编写参考 **fatfs_usbh.c** 文件。
.. figure:: img/stm32_21.png

View File

@@ -28,35 +28,19 @@
#define CONFIG_USB_PRINTF(...) rt_kprintf(__VA_ARGS__)
* USB IP 相关的 config 需要用户自己根据芯片实际情况修改
* 退出以后不急着编译,需要在代码中实现 `usb_dc_low_level_init` 函数
* 在代码中实现 `usb_dc_low_level_init` 函数
* 在 USB 中断函数中调用 `USBD_IRQHandler`,并传入 `busid`
* 调用 `usbd_initialize` 并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBDEV_MAX_BUS`
* 以上内容我们推荐放在 **board.c** 中,如下代码:
.. code-block:: C
void OTG_HS_IRQHandler(void)
{
extern void USBD_IRQHandler(uint8_t busid);
USBD_IRQHandler(0);
}
int usbd_init(void)
{
xxx_template_init(0, USB_OTG_HS_PERIPH_BASE);
return 0;
}
INIT_APP_EXPORT(usbd_init);
* 使用 `scons --target=mdk5` 或者 `scons` 进行编译如果是mdk需要使用 AC6 编译器
* 如果芯片带 cachecache 修改参考 :ref:`usb_cache` 章节
主机配置
--------------------------
* 选择 Enable usb host mode 并敲回车进入
* 选择 USB host ip不清楚自己芯片是哪个 ip 的可以参考 **port** 目录下对应的 readme
* 选择 Enable usb host mode 并敲回车进入
* 选择 USB host ip不清楚自己芯片是哪个 ip 的可以参考 **port** 目录下对应的 readme
* 根据需要勾选 class 驱动
* 选择是否开启模板 demo请注意, msc 禁止使能,因为默认对接到 dfs。
* 选择是否开启模板 demo推荐不用
.. figure:: img/env2.png
@@ -71,77 +55,8 @@
* USB IP 相关的 config 需要用户自己根据芯片实际情况修改
* 在代码中实现 `usb_hc_low_level_init` 函数
* 在 USB 中断函数中调用 `USBH_IRQHandler`,并传入 `busid`
* 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
* 以上内容我们推荐放在 **board.c** 中,如下代码:
.. code-block:: C
void OTG_HS_IRQHandler(void)
{
extern void USBH_IRQHandler(uint8_t busid);
USBH_IRQHandler(0);
}
int usbh_init(void)
{
usbh_initialize(0, USB_OTG_HS_PERIPH_BASE);
return 0;
}
INIT_APP_EXPORT(usbh_init);
* 使用 `scons --target=mdk5` 或者 `scons` 进行编译如果是mdk需要使用 AC6 编译器
* 如果使用的是 GCC ,需要在链接脚本(需要放在 flash 位置)中添加如下代码:
.. code-block:: C
/* section information for usbh class */
. = ALIGN(4);
__usbh_class_info_start__ = .;
KEEP(*(.usbh_class_info))
__usbh_class_info_end__ = .;
举例如下:
.. code-block:: C
/* The program code and other data into "FLASH" Rom type memory */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
__usbh_class_info_start__ = .;
KEEP(*(.usbh_class_info))
__usbh_class_info_end__ = .;
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} > FLASH
借助 STM32CubeMX 生成 USB 初始化
----------------------------------
使用 STM32CubeMX 主要是用来生成 usb 时钟、引脚、中断的配置。我们需要点击如图所示文件,并配置好 USB 的时钟、中断,点击 `Generate Code`
.. figure:: img/stm32cubemx0.png
.. figure:: img/stm32cubemx1.png
.. figure:: img/stm32cubemx2.png
.. figure:: img/stm32cubemx_clk.png
-`main.c` 中的 `SystemClock_Config` 替换掉 `board.c` 中的配置
.. figure:: img/stm32_init2.png
.. note :: 下面步骤从 V1.5.0 开始不再需要,**fsdev/usb_glue_st.c**, **dwc2/usb_glue_st.c** 文件中已经实现
-`stm32xxxx_hal_msp.c` 中的 `HAL_PCD_MspInit` 或者是 `HAL_HCD_MspInit` 中的内容复制到 `usb_dc_low_level_init``usb_hc_low_level_init` 函数中,举例如下:
.. figure:: img/stm32_init.png
* 链接脚本修改参考 :ref:`usbh_link_script` 章节
* 如果芯片带 cachecache 修改参考 :ref:`usb_cache` 章节

View File

@@ -12,6 +12,7 @@ USB Device 移植要点
- 描述符的注册、class的注册、接口的注册、端点中断的注册。不会的参考 demo 下的 template
- 调用 `usbd_initialize` 并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBDEV_MAX_BUS`
- 在中断函数中调用 `USBD_IRQHandler`,并传入 `busid`, 如果你的 SDK 中中断入口已经存在 `USBD_IRQHandler` ,请更改 USB 协议栈中的名称
- 如果芯片带 cachecache 修改参考 :ref:`usb_cache` 章节
- 编译使用。各个 class 如何使用,参考 demo 下的 template
USB Host 移植要点
@@ -22,7 +23,20 @@ USB Host 移植要点
- 实现 `usb_hc_low_level_init` 函数(该函数主要负责 USB 时钟、引脚、中断的初始化)。该函数可以放在你想要放的任何参与编译的 c 文件中。如何进行 USB 的时钟、引脚、中断等初始化,请自行根据你使用的芯片原厂提供的源码中进行添加。
- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base` `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
- 在中断函数中调用 `USBH_IRQHandler`,并传入 `busid`, 如果你的 SDK 中中断入口已经存在 `USBH_IRQHandler` ,请更改 USB 协议栈中的名称
- 如果使用的是 GCC ,需要在链接脚本中添加如下代码(需要放在 flash 位置):
- 链接脚本修改参考 :ref:`usbh_link_script` 章节
- 如果芯片带 cachecache 修改参考 :ref:`usb_cache` 章节
- 编译使用。基础的 cdc + hid + msc 参考 `usb_host.c` 文件,其余参考 **platform** 目录下适配
.. _usbh_link_script:
主机链接脚本修改
-----------------------
在使用主机时,如果没有修改链接脚本,会报 `__usbh_class_info_start__` 和 `__usbh_class_info_end__` 未定义的错误。因为主机协议栈需要在链接脚本中添加一个 section 来存储 class 信息。
- 如果使用的是 KEIL 无需修改
- 如果使用的是 GCC ,需要在链接脚本中添加如下代码(需要放在 flash 位置,建议放最后):
.. code-block:: C
@@ -68,15 +82,17 @@ GCC 举例如下:
place in AXI_SRAM { block cherryusb_usbh_class_info };
keep { section .usbh_class_info};
- 编译使用。各个 class 如何使用,参考 demo 下的 `usb_host.c` 文件
带 cache 功能的芯片使用注意
.. _usb_cache:
cache 配置修改
-------------------------------
协议栈以及 port 中不会对 cache 区域的 ram 进行 clean 或者 invalid所以需要使用一块非 cache 区域的 ram 来维护。 `USB_NOCACHE_RAM_SECTION` 宏表示将变量指定到非 cache ram上
因此,用户需要在对应的链接脚本中添加 no cache ram 的 section。默认 `USB_NOCACHE_RAM_SECTION` 定义为 `__attribute__((section(".noncacheable")))`。
对于带 cache 的芯片,协议栈以及 port 中不会对 cache 区域的 ram 进行 clean 或者 invalid所以需要使用一块非 cache 区域的 ram 来维护。
`USB_NOCACHE_RAM_SECTION` 宏表示将变量指定到非 cache ram上默认 `USB_NOCACHE_RAM_SECTION` 定义为 `__attribute__((section(".noncacheable")))`。
因此,用户需要在对应的链接脚本中添加 no cache ram 的 section并且 section 段包含 `.noncacheable`
.. note:: 需要注意,光指定 section 是不够的,还需要配置该 section 中的 ram 是真的 nocache一般需要配置 mpu 属性arm 的参考 stm32h7 demo
.. note:: 需要注意,光修改链接脚本中的 nocache section 是不够的,还需要配置该 section 中的 ram 是真的 nocache一般需要配置 mpu 属性arm 的参考 stm32h7 demo
GCC:

View File

@@ -20,7 +20,7 @@
- 主机 UVC & UAC 类 MUSB IP 中 ISO 驱动和 UAC/UVC 框架, MUSB 需要为 mentor 公司制定的标准 IP
- 从机 MTP 类驱动, 支持多文件和多文件夹
- 从机 MTP 类驱动, 支持多文件和多文件夹,支持 MCU 端增删文件并与 PC 同步
.. figure:: img/mtpdev.png

View File

@@ -125,4 +125,13 @@ v1.5.0
- cmakesconskconfig 更新
- 使用 USB_ASSERT_MSG 对部分代码检查,全面性 warning 修复
- N32H4/MM32F5 device 支持
- 默认使能 CONFIG_USBDEV_ADVANCE_DESC
- 默认使能 CONFIG_USBDEV_ADVANCE_DESC
v1.5.1
----------------------
- 支持 rt-thread 下使用 adb shellhost serial/device cdc_acm 对接 rtdevice 框架
- **dwc2 增加多个 usbport 不同参数的配置功能比如一个全速一个高速fifo配置和phy配置不同**
- **ehci 在控制传输中如果没有 nodata 阶段会导致 data qtd 未释放,导致内存泄漏**
- **dwc2 读取 setup 使用 usbd_get_next_ep0_state 去判断,避免 setup 和 ep0 out 使用在 USB_OTG_DOEPINT_XFRC 状态下冲突**
- sifli usb device 初步支持

View File

@@ -1,4 +1,4 @@
version: "1.5.0"
version: "1.5.1"
description: CherryUSB is a tiny and portable USB Stack (device & host) for embedded system with USB IP
tags:
- usb
@@ -18,7 +18,7 @@ repository: https://github.com/cherry-embedded/CherryUSB.git
documentation: https://cherryusb.readthedocs.io/
issues: https://github.com/cherry-embedded/CherryUSB/issues
dependencies:
idf: ">=5.0"
idf: ">=4.4.1"
targets:
- esp32s2
- esp32s3

View File

@@ -246,92 +246,12 @@
#define CONFIG_USBHOST_BLUETOOTH_RX_SIZE 2048
#endif
/* ================ USB Device Port Configuration ================*/
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define ESP_USBD_BASE 0x60080000
#define CONFIG_USBDEV_MAX_BUS 1
// esp32s2/s3 has 7 endpoints in device mode (include ep0)
#define CONFIG_USBDEV_EP_NUM 7
/* ---------------- DWC2 Configuration ---------------- */
//esp32s2/s3 can support up to 5 IN endpoints(include ep0) at the same time
#define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (320 / 4)
#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX6_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
#define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
#define CONFIG_USB_DWC2_DMA_ENABLE
#elif CONFIG_IDF_TARGET_ESP32P4
#define ESP_USBD_BASE 0x50000000UL
#define CONFIG_USBDEV_MAX_BUS 1
#define CONFIG_USBDEV_EP_NUM 7 // 16
/* ---------------- DWC2 Configuration ---------------- */
//esp32s2/s3 can support up to 5 IN endpoints(include ep0) at the same time
#define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (512 / 4)
#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (512 / 4)
#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (512 / 4)
#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (512 / 4)
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX6_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
#define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
#define CONFIG_USB_DWC2_DMA_ENABLE
#define CONFIG_USB_HS
#else
#error "Unsupported SoC"
#endif
/* ================ USB Host Port Configuration ==================*/
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define ESP_USBH_BASE 0x60080000
#define CONFIG_USBHOST_MAX_BUS 1
// esp32s2/s3 has 8 endpoints in host mode (include ep0)
#define CONFIG_USBHOST_PIPE_NUM 8
/* ---------------- DWC2 Configuration ---------------- */
/* largest non-periodic USB packet used / 4 */
#define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (240 / 4)
/* largest periodic USB packet used / 4 */
#define CONFIG_USB_DWC2_PTX_FIFO_SIZE (240 / 4)
/*
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
*/
#define CONFIG_USB_DWC2_RX_FIFO_SIZE ((200 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
#elif CONFIG_IDF_TARGET_ESP32P4
#define ESP_USBH_BASE 0x50000000UL
#define CONFIG_USBHOST_MAX_BUS 1
#define CONFIG_USBHOST_PIPE_NUM 16
/* ---------------- DWC2 Configuration ---------------- */
/* largest non-periodic USB packet used / 4 */
#define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (512 / 4)
/* largest periodic USB packet used / 4 */
#define CONFIG_USB_DWC2_PTX_FIFO_SIZE (512 / 4)
/*
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
*/
#define CONFIG_USB_DWC2_RX_FIFO_SIZE ((896 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
#define CONFIG_USBDEV_MAX_BUS 2
#define CONFIG_USBHOST_MAX_BUS 2
#define CONFIG_USB_HS
#else
#error "Unsupported SoC"

View File

@@ -18,7 +18,8 @@ lwip support with usb host net class(cdc_ecm/cdc_ncm/cdc_rndis/asix/rtl8152/bl61
- DFS support with usb host msc.
- lwip support with usb host net class(cdc_ecm/cdc_ncm/cdc_rndis/asix/rtl8152/bl616_wifi).
- msh support with lsusb
- device char support with host cdc_acm/ftdi/ch34x/cp210x/pl2303
- shell support with adb
## Nuttx

View File

@@ -13,7 +13,7 @@ FATFS s_sd_disk;
FIL s_file;
BYTE work[FF_MAX_SS];
const TCHAR driver_num_buf[4] = { '0', ':', '/', '\0' };
const TCHAR driver_num_buf[3] = { '0', ':', '\0' };
const char *show_error_string(FRESULT fresult);

View File

@@ -1,3 +1,8 @@
/*
* Copyright (c) 2022 ~ 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "rtthread.h"
#include "usb_config.h"

View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "usbd_core.h"
#include "usbd_adb.h"
#ifndef CONFIG_USBDEV_SHELL_RX_BUFSIZE
#define CONFIG_USBDEV_SHELL_RX_BUFSIZE (2048)
#endif
struct usbd_adb_shell {
struct rt_device parent;
usb_osal_sem_t tx_done;
struct rt_ringbuffer rx_rb;
rt_uint8_t rx_rb_buffer[CONFIG_USBDEV_SHELL_RX_BUFSIZE];
} g_usbd_adb_shell;
void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len)
{
rt_ringbuffer_put(&g_usbd_adb_shell.rx_rb, data, len);
if (g_usbd_adb_shell.parent.rx_indicate) {
g_usbd_adb_shell.parent.rx_indicate(&g_usbd_adb_shell.parent, len);
}
}
void usbd_adb_notify_write_done(void)
{
if (g_usbd_adb_shell.tx_done) {
usb_osal_sem_give(g_usbd_adb_shell.tx_done);
}
}
static rt_err_t usbd_adb_shell_open(struct rt_device *dev, rt_uint16_t oflag)
{
while (!usb_device_is_configured(0)) {
rt_thread_mdelay(10);
}
return RT_EOK;
}
static rt_err_t usbd_adb_shell_close(struct rt_device *dev)
{
if (g_usbd_adb_shell.tx_done) {
usb_osal_sem_give(g_usbd_adb_shell.tx_done);
}
return RT_EOK;
}
static rt_ssize_t usbd_adb_shell_read(struct rt_device *dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
{
return rt_ringbuffer_get(&g_usbd_adb_shell.rx_rb, (rt_uint8_t *)buffer, size);
}
static rt_ssize_t usbd_adb_shell_write(struct rt_device *dev,
rt_off_t pos,
const void *buffer,
rt_size_t size)
{
int ret = 0;
RT_ASSERT(dev != RT_NULL);
if (!usb_device_is_configured(0)) {
return size;
}
if (usbd_adb_can_write() && size) {
usb_osal_sem_reset(g_usbd_adb_shell.tx_done);
usbd_abd_write(ADB_SHELL_LOALID, buffer, size);
usb_osal_sem_take(g_usbd_adb_shell.tx_done, 0xffffffff);
}
return size;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops usbd_adb_shell_ops = {
NULL,
usbd_adb_shell_open,
usbd_adb_shell_close,
usbd_adb_shell_read,
usbd_adb_shell_write,
NULL
};
#endif
void usbd_adb_shell_init(uint8_t in_ep, uint8_t out_ep)
{
rt_err_t ret;
struct rt_device *device;
device = &(g_usbd_adb_shell.parent);
device->type = RT_Device_Class_Char;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
#ifdef RT_USING_DEVICE_OPS
device->ops = &usbd_adb_shell_ops;
#else
device->init = NULL;
device->open = usbd_adb_shell_open;
device->close = usbd_adb_shell_close;
device->read = usbd_adb_shell_read;
device->write = usbd_adb_shell_write;
device->control = NULL;
#endif
device->user_data = NULL;
/* register a character device */
ret = rt_device_register(device, "adb-sh", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
#ifdef RT_USING_POSIX_DEVIO
/* set fops */
device->fops = NULL;
#endif
g_usbd_adb_shell.tx_done = usb_osal_sem_create(0);
rt_ringbuffer_init(&g_usbd_adb_shell.rx_rb, g_usbd_adb_shell.rx_rb_buffer, sizeof(g_usbd_adb_shell.rx_rb_buffer));
}
static int adb_enter(int argc, char **argv)
{
(void)argc;
(void)argv;
finsh_set_device("adb-sh");
rt_console_set_device("adb-sh");
return 0;
}
MSH_CMD_EXPORT(adb_enter, adb_enter);
static int adb_exit(int argc, char **argv)
{
(void)argc;
(void)argv;
usbd_adb_close(ADB_SHELL_LOALID);
finsh_set_device(RT_CONSOLE_DEVICE_NAME);
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
return 0;
}
MSH_CMD_EXPORT(adb_exit, adb_exit);

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "usbd_core.h"
#include "usbd_cdc_acm.h"
#define DEV_FORMAT_CDC_ACM "usb-acm%d"
#ifndef CONFIG_USBDEV_MAX_CDC_ACM_CLASS
#define CONFIG_USBDEV_MAX_CDC_ACM_CLASS (4)
#endif
#ifndef CONFIG_USBDEV_SERIAL_RX_BUFSIZE
#define CONFIG_USBDEV_SERIAL_RX_BUFSIZE (2048)
#endif
struct usbd_serial {
struct rt_device parent;
uint8_t busid;
uint8_t in_ep;
uint8_t out_ep;
struct usbd_interface intf_ctrl;
struct usbd_interface intf_data;
usb_osal_sem_t tx_done;
uint8_t minor;
char name[32];
struct rt_ringbuffer rx_rb;
rt_uint8_t rx_rb_buffer[CONFIG_USBDEV_SERIAL_RX_BUFSIZE];
};
static uint32_t g_devinuse = 0;
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_usbd_serial_cdc_acm_rx_buf[CONFIG_USBDEV_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(512, CONFIG_USB_ALIGN_SIZE)];
static struct usbd_serial g_usbd_serial_cdc_acm[CONFIG_USBDEV_MAX_CDC_ACM_CLASS];
static struct usbd_serial *usbd_serial_alloc(void)
{
uint8_t devno;
struct usbd_serial *serial;
for (devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) {
if ((g_devinuse & (1U << devno)) == 0) {
g_devinuse |= (1U << devno);
serial = &g_usbd_serial_cdc_acm[devno];
memset(serial, 0, sizeof(struct usbd_serial));
serial->minor = devno;
snprintf(serial->name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_CDC_ACM, serial->minor);
return serial;
}
}
return NULL;
}
static void usbd_serial_free(struct usbd_serial *serial)
{
uint8_t devno = serial->minor;
if (devno < 32) {
g_devinuse &= ~(1U << devno);
}
memset(serial, 0, sizeof(struct usbd_serial));
}
static rt_err_t usbd_serial_open(struct rt_device *dev, rt_uint16_t oflag)
{
struct usbd_serial *serial;
RT_ASSERT(dev != RT_NULL);
serial = (struct usbd_serial *)dev;
if (!usb_device_is_configured(serial->busid)) {
USB_LOG_ERR("USB device is not configured\n");
return -RT_EPERM;
}
usbd_ep_start_read(serial->busid, serial->out_ep,
g_usbd_serial_cdc_acm_rx_buf[serial->minor],
usbd_get_ep_mps(serial->busid, serial->out_ep));
return RT_EOK;
}
static rt_ssize_t usbd_serial_read(struct rt_device *dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
{
struct usbd_serial *serial;
RT_ASSERT(dev != RT_NULL);
serial = (struct usbd_serial *)dev;
if (!usb_device_is_configured(serial->busid)) {
return -RT_EPERM;
}
return rt_ringbuffer_get(&serial->rx_rb, (rt_uint8_t *)buffer, size);
}
static rt_ssize_t usbd_serial_write(struct rt_device *dev,
rt_off_t pos,
const void *buffer,
rt_size_t size)
{
struct usbd_serial *serial;
int ret = 0;
rt_uint8_t *align_buf;
RT_ASSERT(dev != RT_NULL);
serial = (struct usbd_serial *)dev;
if (!usb_device_is_configured(serial->busid)) {
return -RT_EPERM;
}
align_buf = (rt_uint8_t *)buffer;
#ifdef RT_USING_CACHE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = rt_malloc_align(size, CONFIG_USB_ALIGN_SIZE);
if (!align_buf) {
USB_LOG_ERR("serial get align buf failed\n");
return 0;
}
usb_memcpy(align_buf, buffer, size);
}
#endif
usb_osal_sem_reset(serial->tx_done);
usbd_ep_start_write(serial->busid, serial->in_ep, align_buf, size);
ret = usb_osal_sem_take(serial->tx_done, 3000);
if (ret < 0) {
USB_LOG_ERR("serial write timeout\n");
ret = -RT_ETIMEOUT;
} else {
ret = size;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
rt_free_align(align_buf);
}
#endif
return ret;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops usbd_serial_ops = {
NULL,
usbd_serial_open,
NULL,
usbd_serial_read,
usbd_serial_write,
NULL
};
#endif
rt_err_t usbd_serial_register(struct usbd_serial *serial,
void *data)
{
rt_err_t ret;
struct rt_device *device;
RT_ASSERT(serial != RT_NULL);
device = &(serial->parent);
device->type = RT_Device_Class_Char;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
#ifdef RT_USING_DEVICE_OPS
device->ops = &usbd_serial_ops;
#else
device->init = NULL;
device->open = usbd_serial_open;
device->close = NULL;
device->read = usbd_serial_read;
device->write = usbd_serial_write;
device->control = NULL;
#endif
device->user_data = data;
/* register a character device */
ret = rt_device_register(device, serial->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
#ifdef RT_USING_POSIX_DEVIO
/* set fops */
device->fops = NULL;
#endif
rt_ringbuffer_init(&serial->rx_rb, serial->rx_rb_buffer, sizeof(serial->rx_rb_buffer));
return ret;
}
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
struct usbd_serial *serial;
for (uint8_t devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) {
serial = &g_usbd_serial_cdc_acm[devno];
if (serial->out_ep == ep) {
rt_ringbuffer_put(&serial->rx_rb, g_usbd_serial_cdc_acm_rx_buf[serial->minor], nbytes);
break;
}
}
}
void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
struct usbd_serial *serial;
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
/* send zlp */
usbd_ep_start_write(busid, ep, NULL, 0);
} else {
for (uint8_t devno = 0; devno < CONFIG_USBDEV_MAX_CDC_ACM_CLASS; devno++) {
serial = &g_usbd_serial_cdc_acm[devno];
if ((serial->in_ep == ep) && serial->tx_done) {
usb_osal_sem_give(serial->tx_done);
break;
}
}
}
}
void usbd_cdc_acm_serial_init(uint8_t busid, uint8_t in_ep, uint8_t out_ep)
{
struct usbd_serial *serial;
struct usbd_endpoint cdc_out_ep = {
.ep_addr = out_ep,
.ep_cb = usbd_cdc_acm_bulk_out
};
struct usbd_endpoint cdc_in_ep = {
.ep_addr = in_ep,
.ep_cb = usbd_cdc_acm_bulk_in
};
serial = usbd_serial_alloc();
if (serial == NULL) {
USB_LOG_ERR("No more serial device available\n");
return;
}
serial->busid = busid;
serial->in_ep = in_ep;
serial->out_ep = out_ep;
serial->tx_done = usb_osal_sem_create(0);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &serial->intf_ctrl));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &serial->intf_data));
usbd_add_endpoint(busid, &cdc_out_ep);
usbd_add_endpoint(busid, &cdc_in_ep);
if (usbd_serial_register(serial, NULL) != RT_EOK) {
USB_LOG_ERR("Failed to register serial device\n");
usbd_serial_free(serial);
return;
}
USB_LOG_INFO("USB CDC ACM Serial Device %s initialized\n", serial->name);
}

View File

@@ -30,15 +30,15 @@ static rt_err_t rt_udisk_init(rt_device_t dev)
return RT_EOK;
}
static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size)
static rt_ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size)
{
struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
int ret;
rt_uint8_t *align_buf;
align_buf = (rt_uint8_t *)buffer;
#ifdef RT_USING_CACHE
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
if (!align_buf) {
@@ -53,7 +53,7 @@ static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
rt_kprintf("usb mass_storage read failed\n");
return 0;
}
#ifdef RT_USING_CACHE
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
usb_memcpy(buffer, align_buf, size * msc_class->blocksize);
rt_free_align(align_buf);
@@ -62,15 +62,15 @@ static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
return size;
}
static ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
rt_size_t size)
static rt_ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
rt_size_t size)
{
struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
int ret;
rt_uint8_t *align_buf;
align_buf = (rt_uint8_t *)buffer;
#ifdef RT_USING_CACHE
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
if (!align_buf) {
@@ -86,7 +86,7 @@ static ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
rt_kprintf("usb mass_storage write failed\n");
return 0;
}
#ifdef RT_USING_CACHE
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
rt_free_align(align_buf);
}

View File

@@ -0,0 +1,914 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "usbh_core.h"
#include "usbh_cdc_acm.h"
#include "usbh_ftdi.h"
#include "usbh_cp210x.h"
#include "usbh_ch34x.h"
#include "usbh_pl2303.h"
#define DEV_FORMAT_VENDOR "ttyUSB%d"
#define DEV_FORMAT_CDC_ACM "ttyACM%d"
#define USBH_RX_MAX_SIZE 2048
#ifndef CONFIG_USBHOST_MAX_VENDOR_SERIAL_CLASS
#define CONFIG_USBHOST_MAX_VENDOR_SERIAL_CLASS (4)
#endif
#ifndef CONFIG_USBHOST_SERIAL_RX_BUFSIZE
#define CONFIG_USBHOST_SERIAL_RX_BUFSIZE (USBH_RX_MAX_SIZE * 2)
#endif
enum usbh_serial_type {
USBH_SERIAL_TYPE_CDC_ACM = 0,
USBH_SERIAL_TYPE_FTDI,
USBH_SERIAL_TYPE_CP210X,
USBH_SERIAL_TYPE_CH34X,
USBH_SERIAL_TYPE_PL2303,
};
struct usbh_serial {
struct rt_device parent;
enum usbh_serial_type type;
uint8_t minor;
char name[CONFIG_USBHOST_DEV_NAMELEN];
struct rt_ringbuffer rx_rb;
rt_uint8_t rx_rb_buffer[CONFIG_USBHOST_SERIAL_RX_BUFSIZE];
};
static uint32_t g_devinuse_vendor = 0;
static uint32_t g_devinuse_cdc_acm = 0;
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_usbh_serial_vendor_rx_buf[CONFIG_USBHOST_MAX_VENDOR_SERIAL_CLASS][USB_ALIGN_UP(USBH_RX_MAX_SIZE, CONFIG_USB_ALIGN_SIZE)];
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_usbh_serial_cdc_acm_rx_buf[CONFIG_USBHOST_MAX_CDC_ACM_CLASS][USB_ALIGN_UP(USBH_RX_MAX_SIZE, CONFIG_USB_ALIGN_SIZE)];
static struct usbh_serial *usbh_serial_alloc(uint8_t type)
{
uint8_t devno;
struct usbh_serial *serial;
for (devno = 0; devno < CONFIG_USBHOST_MAX_VENDOR_SERIAL_CLASS; devno++) {
if ((g_devinuse_vendor & (1U << devno)) == 0) {
g_devinuse_vendor |= (1U << devno);
serial = rt_malloc(sizeof(struct usbh_serial));
memset(serial, 0, sizeof(struct usbh_serial));
serial->type = type;
serial->minor = devno;
snprintf(serial->name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_VENDOR, serial->minor);
return serial;
}
}
return NULL;
}
static void usbh_serial_free(struct usbh_serial *serial)
{
uint8_t devno = serial->minor;
if (devno < 32) {
g_devinuse_vendor &= ~(1U << devno);
}
memset(serial, 0, sizeof(struct usbh_serial));
rt_free(serial);
}
static struct usbh_serial *usbh_serial_cdc_acm_alloc(uint8_t type)
{
uint8_t devno;
struct usbh_serial *serial;
for (devno = 0; devno < CONFIG_USBHOST_MAX_CDC_ACM_CLASS; devno++) {
if ((g_devinuse_cdc_acm & (1U << devno)) == 0) {
g_devinuse_cdc_acm |= (1U << devno);
serial = rt_malloc(sizeof(struct usbh_serial));
memset(serial, 0, sizeof(struct usbh_serial));
serial->type = type;
serial->minor = devno;
snprintf(serial->name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT_CDC_ACM, serial->minor);
return serial;
}
}
return NULL;
}
static void usbh_serial_cdc_acm_free(struct usbh_serial *serial)
{
uint8_t devno = serial->minor;
if (devno < 32) {
g_devinuse_cdc_acm &= ~(1U << devno);
}
memset(serial, 0, sizeof(struct usbh_serial));
rt_free(serial);
}
static rt_err_t usbh_serial_open(struct rt_device *dev, rt_uint16_t oflag)
{
struct usbh_serial *serial;
RT_ASSERT(dev != RT_NULL);
serial = (struct usbh_serial *)dev;
switch (serial->type) {
case USBH_SERIAL_TYPE_CDC_ACM:
break;
case USBH_SERIAL_TYPE_FTDI:
break;
case USBH_SERIAL_TYPE_CP210X:
break;
case USBH_SERIAL_TYPE_CH34X:
break;
case USBH_SERIAL_TYPE_PL2303:
break;
default:
break;
}
return RT_EOK;
}
static rt_err_t usbh_serial_close(struct rt_device *dev)
{
struct usbh_serial *serial;
RT_ASSERT(dev != RT_NULL);
serial = (struct usbh_serial *)dev;
switch (serial->type) {
case USBH_SERIAL_TYPE_CDC_ACM:
break;
case USBH_SERIAL_TYPE_FTDI:
break;
case USBH_SERIAL_TYPE_CP210X:
break;
case USBH_SERIAL_TYPE_CH34X:
break;
case USBH_SERIAL_TYPE_PL2303:
break;
default:
break;
}
return RT_EOK;
}
static rt_ssize_t usbh_serial_read(struct rt_device *dev,
rt_off_t pos,
void *buffer,
rt_size_t size)
{
struct usbh_serial *serial;
RT_ASSERT(dev != RT_NULL);
serial = (struct usbh_serial *)dev;
return rt_ringbuffer_get(&serial->rx_rb, (rt_uint8_t *)buffer, size);
}
static rt_ssize_t usbh_serial_write(struct rt_device *dev,
rt_off_t pos,
const void *buffer,
rt_size_t size)
{
struct usbh_serial *serial;
int ret = 0;
rt_uint8_t *align_buf;
RT_ASSERT(dev != RT_NULL);
serial = (struct usbh_serial *)dev;
align_buf = (rt_uint8_t *)buffer;
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = rt_malloc_align(size, CONFIG_USB_ALIGN_SIZE);
if (!align_buf) {
USB_LOG_ERR("serial get align buf failed\n");
return 0;
}
usb_memcpy(align_buf, buffer, size);
}
#endif
switch (serial->type) {
#if defined(PKG_CHERRYUSB_HOST_CDC_ACM) || defined(RT_CHERRYUSB_HOST_CDC_ACM)
case USBH_SERIAL_TYPE_CDC_ACM:
ret = usbh_cdc_acm_bulk_out_transfer((struct usbh_cdc_acm *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER);
if (ret < 0) {
USB_LOG_ERR("usbh_cdc_acm_bulk_out_transfer failed: %d\n", ret);
#ifdef CONFIG_USB_DCACHE_ENABLE
rt_free_align(align_buf);
#endif
return 0;
}
break;
#endif
#if defined(PKG_CHERRYUSB_HOST_FTDI) || defined(RT_CHERRYUSB_HOST_FTDI)
case USBH_SERIAL_TYPE_FTDI:
ret = usbh_ftdi_bulk_out_transfer((struct usbh_ftdi *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER);
if (ret < 0) {
USB_LOG_ERR("usbh_ftdi_bulk_out_transfer failed: %d\n", ret);
#ifdef CONFIG_USB_DCACHE_ENABLE
rt_free_align(align_buf);
#endif
return 0;
}
break;
#endif
#if defined(PKG_CHERRYUSB_HOST_CH34X) || defined(RT_CHERRYUSB_HOST_CH34X)
case USBH_SERIAL_TYPE_CH34X:
ret = usbh_ch34x_bulk_out_transfer((struct usbh_ch34x *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER);
if (ret < 0) {
USB_LOG_ERR("usbh_ch34x_bulk_out_transfer failed: %d\n", ret);
#ifdef CONFIG_USB_DCACHE_ENABLE
rt_free_align(align_buf);
#endif
return 0;
}
break;
#endif
#if defined(PKG_CHERRYUSB_HOST_PL2303) || defined(RT_CHERRYUSB_HOST_PL2303)
case USBH_SERIAL_TYPE_PL2303:
ret = usbh_pl2303_bulk_out_transfer((struct usbh_pl2303 *)dev->user_data, (uint8_t *)align_buf, size, RT_WAITING_FOREVER);
if (ret < 0) {
USB_LOG_ERR("usbh_pl2303_bulk_out_transfer failed: %d\n", ret);
#ifdef CONFIG_USB_DCACHE_ENABLE
rt_free_align(align_buf);
#endif
return 0;
}
break;
#endif
default:
break;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
rt_free_align(align_buf);
}
#endif
return ret;
}
static rt_err_t usbh_serial_control(struct rt_device *dev,
int cmd,
void *args)
{
struct usbh_serial *serial;
struct serial_configure *config;
struct cdc_line_coding line_coding;
int ret = -RT_EINVAL;
RT_ASSERT(dev != RT_NULL);
serial = (struct usbh_serial *)dev;
switch (serial->type) {
#if defined(PKG_CHERRYUSB_HOST_CDC_ACM) || defined(RT_CHERRYUSB_HOST_CDC_ACM)
case USBH_SERIAL_TYPE_CDC_ACM:
if (cmd == RT_DEVICE_CTRL_CONFIG) {
struct usbh_cdc_acm *cdc_acm_class;
cdc_acm_class = (struct usbh_cdc_acm *)dev->user_data;
config = (struct serial_configure *)args;
line_coding.dwDTERate = config->baud_rate;
line_coding.bDataBits = config->data_bits;
line_coding.bCharFormat = 0; // STOP_BITS_1
line_coding.bParityType = config->parity;
usbh_cdc_acm_set_line_coding(cdc_acm_class, &line_coding);
}
ret = RT_EOK;
break;
#endif
#if defined(PKG_CHERRYUSB_HOST_FTDI) || defined(RT_CHERRYUSB_HOST_FTDI)
case USBH_SERIAL_TYPE_FTDI:
if (cmd == RT_DEVICE_CTRL_CONFIG) {
struct usbh_ftdi *ftdi_class;
ftdi_class = (struct usbh_ftdi *)dev->user_data;
config = (struct serial_configure *)args;
line_coding.dwDTERate = config->baud_rate;
line_coding.bDataBits = config->data_bits;
line_coding.bCharFormat = 0; // STOP_BITS_1
line_coding.bParityType = config->parity;
usbh_ftdi_set_line_coding(ftdi_class, &line_coding);
}
ret = RT_EOK;
break;
#endif
#if defined(PKG_CHERRYUSB_HOST_CP210X) || defined(RT_CHERRYUSB_HOST_CP210X)
case USBH_SERIAL_TYPE_CP210X:
if (cmd == RT_DEVICE_CTRL_CONFIG) {
struct usbh_cp210x *cp210x_class;
cp210x_class = (struct usbh_cp210x *)dev->user_data;
config = (struct serial_configure *)args;
line_coding.dwDTERate = config->baud_rate;
line_coding.bDataBits = config->data_bits;
line_coding.bCharFormat = 0; // STOP_BITS_1
line_coding.bParityType = config->parity;
usbh_cp210x_set_line_coding(cp210x_class, &line_coding);
}
ret = RT_EOK;
break;
#endif
#if defined(PKG_CHERRYUSB_HOST_CH34X) || defined(RT_CHERRYUSB_HOST_CH34X)
case USBH_SERIAL_TYPE_CH34X:
if (cmd == RT_DEVICE_CTRL_CONFIG) {
struct usbh_ch34x *ch34x_class;
ch34x_class = (struct usbh_ch34x *)dev->user_data;
config = (struct serial_configure *)args;
line_coding.dwDTERate = config->baud_rate;
line_coding.bDataBits = config->data_bits;
line_coding.bCharFormat = 0; // STOP_BITS_1
line_coding.bParityType = config->parity;
usbh_ch34x_set_line_coding(ch34x_class, &line_coding);
}
ret = RT_EOK;
break;
#endif
#if defined(PKG_CHERRYUSB_HOST_PL2303) || defined(RT_CHERRYUSB_HOST_PL2303)
case USBH_SERIAL_TYPE_PL2303:
if (cmd == RT_DEVICE_CTRL_CONFIG) {
struct usbh_pl2303 *pl2303_class;
pl2303_class = (struct usbh_pl2303 *)dev->user_data;
config = (struct serial_configure *)args;
line_coding.dwDTERate = config->baud_rate;
line_coding.bDataBits = config->data_bits;
line_coding.bCharFormat = 0; // STOP_BITS_1
line_coding.bParityType = config->parity;
usbh_pl2303_set_line_coding(pl2303_class, &line_coding);
}
ret = RT_EOK;
break;
#endif
default:
break;
}
return ret;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops usbh_serial_ops = {
NULL,
usbh_serial_open,
usbh_serial_close,
usbh_serial_read,
usbh_serial_write,
usbh_serial_control
};
#endif
#ifdef RT_USING_POSIX_DEVIO
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <dfs_file.h>
#ifdef RT_USING_POSIX_TERMIOS
#include <termios.h>
#endif
static rt_err_t usbh_serial_fops_rx_ind(rt_device_t dev, rt_size_t size)
{
rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN);
return RT_EOK;
}
/* fops for serial */
static int usbh_serial_fops_open(struct dfs_file *fd)
{
rt_err_t ret = 0;
rt_uint16_t flags = 0;
rt_device_t device;
device = (rt_device_t)fd->vnode->data;
RT_ASSERT(device != RT_NULL);
switch (fd->flags & O_ACCMODE)
{
case O_RDONLY:
USB_LOG_DBG("fops open: O_RDONLY!");
flags = RT_DEVICE_FLAG_RDONLY;
break;
case O_WRONLY:
USB_LOG_DBG("fops open: O_WRONLY!");
flags = RT_DEVICE_FLAG_WRONLY;
break;
case O_RDWR:
USB_LOG_DBG("fops open: O_RDWR!");
flags = RT_DEVICE_FLAG_RDWR;
break;
default:
USB_LOG_ERR("fops open: unknown mode - %d!", fd->flags & O_ACCMODE);
break;
}
if ((fd->flags & O_ACCMODE) != O_WRONLY)
rt_device_set_rx_indicate(device, usbh_serial_fops_rx_ind);
ret = rt_device_open(device, flags);
if (ret == RT_EOK) return 0;
return ret;
}
static int usbh_serial_fops_close(struct dfs_file *fd)
{
rt_device_t device;
device = (rt_device_t)fd->vnode->data;
rt_device_set_rx_indicate(device, RT_NULL);
rt_device_close(device);
return 0;
}
static int usbh_serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
{
rt_device_t device;
int flags = (int)(rt_base_t)args;
int mask = O_NONBLOCK | O_APPEND;
device = (rt_device_t)fd->vnode->data;
switch (cmd)
{
case FIONREAD:
break;
case FIONWRITE:
break;
case F_SETFL:
flags &= mask;
fd->flags &= ~mask;
fd->flags |= flags;
break;
}
return rt_device_control(device, cmd, args);
}
static int usbh_serial_fops_read(struct dfs_file *fd, void *buf, size_t count)
{
int size = 0;
rt_device_t device;
device = (rt_device_t)fd->vnode->data;
do
{
size = rt_device_read(device, -1, buf, count);
if (size <= 0)
{
if (fd->flags & O_NONBLOCK)
{
size = -EAGAIN;
break;
}
rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER);
}
}while (size <= 0);
return size;
}
static int usbh_serial_fops_write(struct dfs_file *fd, const void *buf, size_t count)
{
rt_device_t device;
device = (rt_device_t)fd->vnode->data;
return rt_device_write(device, -1, buf, count);
}
static int usbh_serial_fops_poll(struct dfs_file *fd, struct rt_pollreq *req)
{
int mask = 0;
int flags = 0;
rt_device_t device;
struct usbh_serial *serial;
device = (rt_device_t)fd->vnode->data;
RT_ASSERT(device != RT_NULL);
serial = (struct usbh_serial *)device;
/* only support POLLIN */
flags = fd->flags & O_ACCMODE;
if (flags == O_RDONLY || flags == O_RDWR)
{
rt_base_t level;
rt_poll_add(&(device->wait_queue), req);
level = rt_hw_interrupt_disable();
if (rt_ringbuffer_data_len(&serial->rx_rb))
mask |= POLLIN;
rt_hw_interrupt_enable(level);
}
// mask|=POLLOUT;
return mask;
}
const static struct dfs_file_ops usbh_serial_fops =
{
usbh_serial_fops_open,
usbh_serial_fops_close,
usbh_serial_fops_ioctl,
usbh_serial_fops_read,
usbh_serial_fops_write,
RT_NULL, /* flush */
RT_NULL, /* lseek */
RT_NULL, /* getdents */
usbh_serial_fops_poll,
};
#endif /* RT_USING_POSIX_DEVIO */
rt_err_t usbh_serial_register(struct usbh_serial *serial,
void *data)
{
rt_err_t ret;
struct rt_device *device;
RT_ASSERT(serial != RT_NULL);
device = &(serial->parent);
device->type = RT_Device_Class_Char;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
#ifdef RT_USING_DEVICE_OPS
device->ops = &usbh_serial_ops;
#else
device->init = NULL;
device->open = usbh_serial_open;
device->close = usbh_serial_close;
device->read = usbh_serial_read;
device->write = usbh_serial_write;
device->control = usbh_serial_control;
#endif
device->user_data = data;
/* register a character device */
ret = rt_device_register(device, serial->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
#ifdef RT_USING_POSIX_DEVIO
/* set fops */
device->fops = &usbh_serial_fops;
#endif
rt_ringbuffer_init(&serial->rx_rb, serial->rx_rb_buffer, sizeof(serial->rx_rb_buffer));
return ret;
}
void usbh_serial_unregister(struct usbh_serial *serial)
{
RT_ASSERT(serial != NULL);
rt_device_unregister(&serial->parent);
if (serial->type == USBH_SERIAL_TYPE_CDC_ACM) {
usbh_serial_cdc_acm_free(serial);
} else {
usbh_serial_free(serial);
}
}
#if defined(PKG_CHERRYUSB_HOST_CDC_ACM) || defined(RT_CHERRYUSB_HOST_CDC_ACM)
void usbh_cdc_acm_callback(void *arg, int nbytes)
{
struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg;
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &cdc_acm_class->bulkin_urb;
if (nbytes > 0) {
serial = (struct usbh_serial *)cdc_acm_class->user_data;
rt_ringbuffer_put(&serial->rx_rb, g_usbh_serial_cdc_acm_rx_buf[serial->minor], nbytes);
if (serial->parent.rx_indicate) {
serial->parent.rx_indicate(&serial->parent, nbytes);
}
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, g_usbh_serial_cdc_acm_rx_buf[serial->minor], sizeof(g_usbh_serial_cdc_acm_rx_buf[serial->minor]), 0, usbh_cdc_acm_callback, cdc_acm_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
}
}
}
void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &cdc_acm_class->bulkin_urb;
serial = usbh_serial_cdc_acm_alloc(USBH_SERIAL_TYPE_CDC_ACM);
cdc_acm_class->user_data = serial;
usbh_serial_register(serial, cdc_acm_class);
struct cdc_line_coding linecoding;
linecoding.dwDTERate = 115200;
linecoding.bDataBits = 8;
linecoding.bParityType = 0;
linecoding.bCharFormat = 0;
usbh_cdc_acm_set_line_coding(cdc_acm_class, &linecoding);
usbh_bulk_urb_fill(urb, cdc_acm_class->hport, cdc_acm_class->bulkin, g_usbh_serial_cdc_acm_rx_buf[serial->minor], sizeof(g_usbh_serial_cdc_acm_rx_buf[serial->minor]), 0, usbh_cdc_acm_callback, cdc_acm_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
usbh_serial_unregister(serial);
return;
}
}
void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
{
struct usbh_serial *serial;
serial = (struct usbh_serial *)cdc_acm_class->user_data;
usbh_serial_unregister(serial);
}
#endif
#if defined(PKG_CHERRYUSB_HOST_FTDI) || defined(RT_CHERRYUSB_HOST_FTDI)
void usbh_ftdi_callback(void *arg, int nbytes)
{
struct usbh_ftdi *ftdi_class = (struct usbh_ftdi *)arg;
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &ftdi_class->bulkin_urb;
if (nbytes >= 2) {
serial = (struct usbh_serial *)ftdi_class->user_data;
nbytes -= 2; // Skip the first two bytes (header)
rt_ringbuffer_put(&serial->rx_rb, &g_usbh_serial_vendor_rx_buf[serial->minor][2], nbytes);
if (serial->parent.rx_indicate && nbytes) {
serial->parent.rx_indicate(&serial->parent, nbytes);
}
usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_ftdi_callback, ftdi_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
}
}
}
void usbh_ftdi_run(struct usbh_ftdi *ftdi_class)
{
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &ftdi_class->bulkin_urb;
serial = usbh_serial_alloc(USBH_SERIAL_TYPE_FTDI);
ftdi_class->user_data = serial;
usbh_serial_register(serial, ftdi_class);
struct cdc_line_coding linecoding;
linecoding.dwDTERate = 115200;
linecoding.bDataBits = 8;
linecoding.bParityType = 0;
linecoding.bCharFormat = 0;
usbh_ftdi_set_line_coding(ftdi_class, &linecoding);
usbh_bulk_urb_fill(urb, ftdi_class->hport, ftdi_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_ftdi_callback, ftdi_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
usbh_serial_unregister(serial);
return;
}
}
void usbh_ftdi_stop(struct usbh_ftdi *ftdi_class)
{
struct usbh_serial *serial;
serial = (struct usbh_serial *)ftdi_class->user_data;
usbh_serial_unregister(serial);
}
#endif
#if defined(PKG_CHERRYUSB_HOST_CH34X) || defined(RT_CHERRYUSB_HOST_CH34X)
void usbh_ch34x_callback(void *arg, int nbytes)
{
struct usbh_ch34x *ch34x_class = (struct usbh_ch34x *)arg;
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &ch34x_class->bulkin_urb;
if (nbytes > 0) {
serial = (struct usbh_serial *)ch34x_class->user_data;
rt_ringbuffer_put(&serial->rx_rb, g_usbh_serial_vendor_rx_buf[serial->minor], nbytes);
if (serial->parent.rx_indicate) {
serial->parent.rx_indicate(&serial->parent, nbytes);
}
usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_ch34x_callback, ch34x_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
}
}
}
void usbh_ch34x_run(struct usbh_ch34x *ch34x_class)
{
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &ch34x_class->bulkin_urb;
serial = usbh_serial_alloc(USBH_SERIAL_TYPE_CH34X);
ch34x_class->user_data = serial;
usbh_serial_register(serial, ch34x_class);
struct cdc_line_coding linecoding;
linecoding.dwDTERate = 115200;
linecoding.bDataBits = 8;
linecoding.bParityType = 0;
linecoding.bCharFormat = 0;
usbh_ch34x_set_line_coding(ch34x_class, &linecoding);
usbh_bulk_urb_fill(urb, ch34x_class->hport, ch34x_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_ch34x_callback, ch34x_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
usbh_serial_unregister(serial);
return;
}
}
void usbh_ch34x_stop(struct usbh_ch34x *ch34x_class)
{
struct usbh_serial *serial;
serial = (struct usbh_serial *)ch34x_class->user_data;
usbh_serial_unregister(serial);
}
#endif
#if defined(PKG_CHERRYUSB_HOST_CP210X) || defined(RT_CHERRYUSB_HOST_CP210X)
void usbh_cp210x_callback(void *arg, int nbytes)
{
struct usbh_cp210x *cp210x_class = (struct usbh_cp210x *)arg;
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &cp210x_class->bulkin_urb;
if (nbytes > 0) {
serial = (struct usbh_serial *)cp210x_class->user_data;
rt_ringbuffer_put(&serial->rx_rb, g_usbh_serial_vendor_rx_buf[serial->minor], nbytes);
if (serial->parent.rx_indicate) {
serial->parent.rx_indicate(&serial->parent, nbytes);
}
usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_cp210x_callback, cp210x_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
}
}
}
void usbh_cp210x_run(struct usbh_cp210x *cp210x_class)
{
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &cp210x_class->bulkin_urb;
serial = usbh_serial_alloc(USBH_SERIAL_TYPE_CP210X);
cp210x_class->user_data = serial;
usbh_serial_register(serial, cp210x_class);
struct cdc_line_coding linecoding;
linecoding.dwDTERate = 115200;
linecoding.bDataBits = 8;
linecoding.bParityType = 0;
linecoding.bCharFormat = 0;
usbh_cp210x_set_line_coding(cp210x_class, &linecoding);
usbh_bulk_urb_fill(urb, cp210x_class->hport, cp210x_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_cp210x_callback, cp210x_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
usbh_serial_unregister(serial);
return;
}
}
void usbh_cp210x_stop(struct usbh_cp210x *cp210x_class)
{
struct usbh_serial *serial;
serial = (struct usbh_serial *)cp210x_class->user_data;
usbh_serial_unregister(serial);
}
#endif
#if defined(PKG_CHERRYUSB_HOST_PL2303) || defined(RT_CHERRYUSB_HOST_PL2303)
void usbh_pl2303_callback(void *arg, int nbytes)
{
struct usbh_pl2303 *pl2303_class = (struct usbh_pl2303 *)arg;
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &pl2303_class->bulkin_urb;
if (nbytes > 0) {
serial = (struct usbh_serial *)pl2303_class->user_data;
rt_ringbuffer_put(&serial->rx_rb, g_usbh_serial_vendor_rx_buf[serial->minor], nbytes);
if (serial->parent.rx_indicate) {
serial->parent.rx_indicate(&serial->parent, nbytes);
}
usbh_bulk_urb_fill(urb, pl2303_class->hport, pl2303_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_pl2303_callback, pl2303_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
}
}
}
void usbh_pl2303_run(struct usbh_pl2303 *pl2303_class)
{
struct usbh_serial *serial;
int ret;
struct usbh_urb *urb = &pl2303_class->bulkin_urb;
serial = usbh_serial_alloc(USBH_SERIAL_TYPE_PL2303);
pl2303_class->user_data = serial;
usbh_serial_register(serial, pl2303_class);
struct cdc_line_coding linecoding;
linecoding.dwDTERate = 115200;
linecoding.bDataBits = 8;
linecoding.bParityType = 0;
linecoding.bCharFormat = 0;
usbh_pl2303_set_line_coding(pl2303_class, &linecoding);
usbh_bulk_urb_fill(urb, pl2303_class->hport, pl2303_class->bulkin, g_usbh_serial_vendor_rx_buf[serial->minor], sizeof(g_usbh_serial_vendor_rx_buf[serial->minor]), 0, usbh_pl2303_callback, pl2303_class);
ret = usbh_submit_urb(urb);
if (ret < 0) {
USB_LOG_ERR("usbh_submit_urb failed: %d\n", ret);
usbh_serial_unregister(serial);
return;
}
}
void usbh_pl2303_stop(struct usbh_pl2303 *pl2303_class)
{
struct usbh_serial *serial;
serial = (struct usbh_serial *)pl2303_class->user_data;
usbh_serial_unregister(serial);
}
#endif

View File

@@ -543,11 +543,10 @@ void USBD_IRQHandler(uint8_t busid)
}
break;
case UIS_TOKEN_OUT:
EPn_SET_RX_NAK(epid);
if (epid == 0) {
/*!< ep0 out */
CH58x_USBFS_DEV->UEP0_CTRL ^= RB_UEP_R_TOG;
EPn_SET_RX_NAK(epid);
uint32_t read_count = EPn_GET_RX_LEN(0);
memcpy(usb_dc_cfg.ep_out[epid].xfer_buf, usb_dc_cfg.ep_out[epid].ep_ram_addr, read_count);
@@ -563,6 +562,7 @@ void USBD_IRQHandler(uint8_t busid)
if (epid == 4) {
CH58x_USBFS_DEV->UEP4_CTRL ^= RB_UEP_R_TOG;
}
EPn_SET_RX_NAK(epid);
uint32_t read_count = EPn_GET_RX_LEN(epid);
memcpy(usb_dc_cfg.ep_out[epid].xfer_buf, usb_dc_cfg.ep_out[epid].ep_ram_addr, read_count);
usb_dc_cfg.ep_out[epid].xfer_buf += read_count;
@@ -637,4 +637,4 @@ void USB_IRQHandler(void)
{
extern void USBD_IRQHandler(uint8_t busid);
USBD_IRQHandler(0);
}
}

View File

@@ -6,24 +6,25 @@ If you are using more than one port, all ip parameters must be the same(like fif
## STM32
**有且仅有 PB14/PB15 引脚支持 host 模式, 部分 F7/H7 可能 PA11/PA12 也支持**
- STM32F105xc、STM32F107xc
- STM32F205xx、STM32F207xx、STM32F215xx、STM32F217xx
- STM32F401xc、STM32F401xe、STM32F405xx、STM32F407xx、STM32F411xe、STM32F412cx、STM32F412rx、STM32F412vx、STM32F412zx、STM32F413xx、STM32F415xx、STM32F417xx、STM32F423xx、STM32F423xx、STM32F429xx、STM32F437xx、STM32F439xx、STM32F446xx、STM32F469xx、STM32F479xx
- STM32F7xx
- STM32H7xx
- STM32L4xx
- STM32MPxx
- STM32U5xx
## AT32
**有且仅有 AT32F405xx PB14/PB15引脚支持 host 模式**
- AT32F402xx、AT32F405xx、AT32F415xx、AT32F423xx、AT32F425xx、AT32F435xx、AT32F437xx
## GD32
CONFIG_USBDEV_EP_NUM 必须为4 或者 6并删除 usb_dc_dwc2.c 中 while(1){}
当 CONFIG_USBDEV_EP_NUM 为4 时fifo_num 不得大于 320 字
当 CONFIG_USBDEV_EP_NUM 为6 时fifo_num 不得大于 1280 字
**由于无法读取 DWC2 配置信息,并且有部分寄存器是非标准的,因此暂时无法支持 GD 系列**
- GD32F30X_CL
- GD32F405、GD32F407

View File

@@ -5,6 +5,7 @@
*/
#include "usbd_core.h"
#include "usb_dwc2_reg.h"
#include "usb_dwc2_param.h"
// clang-format off
#if defined ( __CC_ARM )
@@ -51,46 +52,6 @@
#endif
// clang-format on
#ifndef CONFIG_USB_DWC2_RXALL_FIFO_SIZE
#define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX0_FIFO_SIZE
#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX1_FIFO_SIZE
#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (1024 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX2_FIFO_SIZE
#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX3_FIFO_SIZE
#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX4_FIFO_SIZE
#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX5_FIFO_SIZE
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX6_FIFO_SIZE
#define CONFIG_USB_DWC2_TX6_FIFO_SIZE (0 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX7_FIFO_SIZE
#define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX8_FIFO_SIZE
#define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
#endif
#define USBD_BASE (g_usbdev_bus[busid].reg_base)
#define USB_OTG_GLB ((DWC2_GlobalTypeDef *)(USBD_BASE))
@@ -115,9 +76,11 @@ struct dwc2_ep_state {
/* Driver state */
USB_NOCACHE_RAM_SECTION struct dwc2_udc {
USB_MEM_ALIGNX struct usb_setup_packet setup;
USB_MEM_ALIGNX uint32_t GSNPSID;
struct dwc2_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
struct dwc2_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
USB_MEM_ALIGNX uint8_t pad; /* Pad to CONFIG_USB_ALIGN_SIZE bytes */
struct dwc2_hw_params hw_params;
struct dwc2_user_params user_params;
struct dwc2_ep_state in_ep[16]; /*!< IN endpoint parameters*/
struct dwc2_ep_state out_ep[16]; /*!< OUT endpoint parameters */
} g_dwc2_udc[CONFIG_USBDEV_MAX_BUS];
static inline int dwc2_reset(uint8_t busid)
@@ -135,7 +98,7 @@ static inline int dwc2_reset(uint8_t busid)
count = 0U;
USB_OTG_GLB->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
if (g_dwc2_udc[busid].GSNPSID < 0x4F54420AU) {
if (g_dwc2_udc[busid].hw_params.snpsid < 0x4F54420AU) {
do {
if (++count > 200000U) {
USB_LOG_ERR("DWC2 reset timeout\r\n");
@@ -160,22 +123,42 @@ static inline int dwc2_reset(uint8_t busid)
static inline int dwc2_core_init(uint8_t busid)
{
int ret;
#if defined(CONFIG_USB_HS)
/* Init The ULPI Interface */
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL);
uint32_t regval;
/* Select vbus source */
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
if (g_dwc2_udc[busid].user_params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
/* Select FS Embedded PHY */
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
} else {
regval = USB_OTG_GLB->GUSBCFG;
regval &= ~USB_OTG_GUSBCFG_PHYSEL;
/* disable external vbus source */
regval &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
/* disable ULPI FS/LS */
regval &= ~(USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_ULPICSM);
switch (g_dwc2_udc[busid].user_params.phy_type) {
case DWC2_PHY_TYPE_PARAM_ULPI:
regval |= USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
regval &= ~USB_OTG_GUSBCFG_PHYIF16;
regval &= ~USB_OTG_GUSBCFG_DDR_SEL;
if (g_dwc2_udc[busid].user_params.phy_utmi_width == 16) {
regval |= USB_OTG_GUSBCFG_PHYIF16;
}
break;
case DWC2_PHY_TYPE_PARAM_UTMI:
regval &= ~USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
regval &= ~USB_OTG_GUSBCFG_PHYIF16;
break;
default:
break;
}
USB_OTG_GLB->GUSBCFG = regval;
}
/* Reset after a PHY select */
ret = dwc2_reset(busid);
#else
/* Select FS Embedded PHY */
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
/* Reset after a PHY select */
ret = dwc2_reset(busid);
#endif
return ret;
}
@@ -285,8 +268,6 @@ static void dwc2_set_turnaroundtime(uint8_t busid, uint32_t hclk, uint8_t speed)
UsbTrd = USBD_DEFAULT_TRDT_VALUE;
}
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_TOCAL;
USB_OTG_GLB->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
USB_OTG_GLB->GUSBCFG |= (uint32_t)((UsbTrd << USB_OTG_GUSBCFG_TRDT_Pos) & USB_OTG_GUSBCFG_TRDT);
}
@@ -347,11 +328,11 @@ static void dwc2_ep0_start_read_setup(uint8_t busid, uint8_t *psetup)
USB_OTG_OUTEP(0U)->DOEPTSIZ |= (3U * 8U);
USB_OTG_OUTEP(0U)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT;
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
USB_OTG_OUTEP(0U)->DOEPDMA = (uint32_t)psetup;
/* EP enable */
USB_OTG_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_USBAEP;
#endif
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_OTG_OUTEP(0U)->DOEPDMA = (uint32_t)psetup;
/* EP enable */
USB_OTG_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_USBAEP;
}
}
void dwc2_ep_write(uint8_t busid, uint8_t ep_idx, uint8_t *src, uint16_t len)
@@ -504,41 +485,13 @@ static inline uint32_t dwc2_get_inep_intstatus(uint8_t busid, uint8_t epnum)
int usb_dc_init(uint8_t busid)
{
int ret;
uint8_t fsphy_type;
uint8_t hsphy_type;
uint8_t dma_support;
uint8_t endpoints;
uint32_t fifo_num;
memset(&g_dwc2_udc[busid], 0, sizeof(struct dwc2_udc));
usb_dc_low_level_init(busid);
/*
Full-Speed PHY Interface Type (FSPhyType)
2'b00: Full-speed interface not supported
2'b01: Dedicated full-speed interface
2'b10: FS pins shared with UTMI+ pins
2'b11: FS pins shared with ULPI pins
High-Speed PHY Interface Type (HSPhyType)
2'b00: High-Speed interface not supported
2'b01: UTMI+
2'b10: ULPI
2'b11: UTMI+ and ULPI
Architecture (OtgArch)
2'b00: Slave-Only
2'b01: External DMA
2'b10: Internal DMA
Others: Reserved
*/
fsphy_type = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 8)) >> 8);
hsphy_type = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 6)) >> 6);
dma_support = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 3)) >> 3);
endpoints = ((USB_OTG_GLB->GHWCFG2 & (0x0f << 10)) >> 10) + 1;
USB_LOG_INFO("========== dwc2 udc params ==========\r\n");
USB_LOG_INFO("========== dwc2 dcd params ==========\r\n");
USB_LOG_INFO("CID:%08x\r\n", (unsigned int)USB_OTG_GLB->CID);
USB_LOG_INFO("GSNPSID:%08x\r\n", (unsigned int)USB_OTG_GLB->GSNPSID);
USB_LOG_INFO("GHWCFG1:%08x\r\n", (unsigned int)USB_OTG_GLB->GHWCFG1);
@@ -546,26 +499,40 @@ int usb_dc_init(uint8_t busid)
USB_LOG_INFO("GHWCFG3:%08x\r\n", (unsigned int)USB_OTG_GLB->GHWCFG3);
USB_LOG_INFO("GHWCFG4:%08x\r\n", (unsigned int)USB_OTG_GLB->GHWCFG4);
USB_LOG_INFO("dwc2 fsphy type:%d, hsphy type:%d, dma support:%d\r\n", fsphy_type, hsphy_type, dma_support);
USB_LOG_INFO("dwc2 has %d endpoints and dfifo depth(32-bit words) is %d, default config: %d endpoints\r\n", endpoints, (USB_OTG_GLB->GHWCFG3 >> 16), CONFIG_USBDEV_EP_NUM);
USB_LOG_INFO("=================================\r\n");
dwc2_get_hwparams(USBD_BASE, &g_dwc2_udc[busid].hw_params);
dwc2_get_user_params(USBD_BASE, &g_dwc2_udc[busid].user_params);
USB_ASSERT_MSG(endpoints >= CONFIG_USBDEV_EP_NUM, "dwc2 has less endpoints than config, please check");
if (g_dwc2_udc[busid].user_params.phy_utmi_width == 0) {
g_dwc2_udc[busid].user_params.phy_utmi_width = 8;
}
if (g_dwc2_udc[busid].user_params.total_fifo_size == 0) {
g_dwc2_udc[busid].user_params.total_fifo_size = g_dwc2_udc[busid].hw_params.total_fifo_size;
}
g_dwc2_udc[busid].GSNPSID = USB_OTG_GLB->GSNPSID;
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
USB_LOG_INFO("dwc2 has %d endpoints and dfifo depth(32-bit words) is %d\r\n",
g_dwc2_udc[busid].hw_params.num_dev_ep + 1,
g_dwc2_udc[busid].user_params.total_fifo_size);
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
/* This is vendor register */
USB_OTG_GLB->GCCFG = usbd_get_dwc2_gccfg_conf(USBD_BASE);
USB_OTG_GLB->GCCFG = g_dwc2_udc[busid].user_params.device_gccfg;
ret = dwc2_core_init(busid);
/* Force Device Mode*/
dwc2_set_mode(busid, USB_OTG_MODE_DEVICE);
if (g_dwc2_udc[busid].user_params.b_session_valid_override) {
/* B-peripheral session valid override enable */
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
}
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_TOCAL;
for (uint8_t i = 0U; i < 15U; i++) {
USB_OTG_GLB->DIEPTXF[i] = 0U;
}
@@ -575,15 +542,17 @@ int usb_dc_init(uint8_t busid)
/* Device speed configuration */
USB_OTG_DEV->DCFG &= ~USB_OTG_DCFG_DSPD;
#if defined(CONFIG_USB_HS)
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH;
#else
if (hsphy_type == 0) {
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_FULL;
if (g_dwc2_udc[busid].user_params.phy_type != DWC2_PHY_TYPE_PARAM_FS) {
USB_ASSERT_MSG(g_dwc2_udc[busid].hw_params.hs_phy_type != 0, "This dwc2 version does not support hs, so stop working");
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH;
} else {
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH_IN_FULL;
if (g_dwc2_udc[busid].hw_params.hs_phy_type == 0) {
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_FULL;
} else {
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH_IN_FULL;
}
}
#endif
/* Clear all pending Device Interrupts */
USB_OTG_DEV->DIEPMSK = 0U;
@@ -600,58 +569,35 @@ int usb_dc_init(uint8_t busid)
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT |
USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM;
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
USB_ASSERT_MSG(((USB_OTG_GLB->GHWCFG2 & (0x3U << 3)) >> 3) == 2, "This dwc2 version does not support dma mode, so stop working");
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_ASSERT_MSG(g_dwc2_udc[busid].hw_params.arch == GHWCFG2_INT_DMA_ARCH, "This dwc2 version does not support dma mode, so stop working");
USB_OTG_DEV->DCFG &= ~USB_OTG_DCFG_DESCDMA;
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_HBSTLEN;
USB_OTG_GLB->GAHBCFG |= (USB_OTG_GAHBCFG_DMAEN | USB_OTG_GAHBCFG_HBSTLEN_4);
} else {
USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
}
USB_OTG_DEV->DCFG &= ~USB_OTG_DCFG_DESCDMA;
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_HBSTLEN;
USB_OTG_GLB->GAHBCFG |= (USB_OTG_GAHBCFG_DMAEN | USB_OTG_GAHBCFG_HBSTLEN_4);
#else
USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
#endif
#if CONFIG_DWC2_VBUS_SENSING
USB_OTG_GLB->GINTMSK |= (USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_SRQIM);
#endif
#ifdef CONFIG_USBDEV_SOF_ENABLE
USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_SOFM;
#endif
USB_OTG_GLB->GRXFSIZ = (CONFIG_USB_DWC2_RXALL_FIFO_SIZE);
USB_OTG_GLB->GRXFSIZ = g_dwc2_udc[busid].user_params.device_rx_fifo_size;
dwc2_set_txfifo(busid, 0, CONFIG_USB_DWC2_TX0_FIFO_SIZE);
dwc2_set_txfifo(busid, 1, CONFIG_USB_DWC2_TX1_FIFO_SIZE);
dwc2_set_txfifo(busid, 2, CONFIG_USB_DWC2_TX2_FIFO_SIZE);
dwc2_set_txfifo(busid, 3, CONFIG_USB_DWC2_TX3_FIFO_SIZE);
fifo_num = g_dwc2_udc[busid].user_params.device_rx_fifo_size;
for (uint8_t i = 0; i < (g_dwc2_udc[busid].hw_params.num_dev_ep + 1); i++) {
dwc2_set_txfifo(busid, i, g_dwc2_udc[busid].user_params.device_tx_fifo_size[i]);
fifo_num += g_dwc2_udc[busid].user_params.device_tx_fifo_size[i];
fifo_num = CONFIG_USB_DWC2_RXALL_FIFO_SIZE;
fifo_num += CONFIG_USB_DWC2_TX0_FIFO_SIZE;
fifo_num += CONFIG_USB_DWC2_TX1_FIFO_SIZE;
fifo_num += CONFIG_USB_DWC2_TX2_FIFO_SIZE;
fifo_num += CONFIG_USB_DWC2_TX3_FIFO_SIZE;
#if CONFIG_USBDEV_EP_NUM > 4
dwc2_set_txfifo(busid, 4, CONFIG_USB_DWC2_TX4_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX4_FIFO_SIZE;
#endif
#if CONFIG_USBDEV_EP_NUM > 5
dwc2_set_txfifo(busid, 5, CONFIG_USB_DWC2_TX5_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX5_FIFO_SIZE;
#endif
#if CONFIG_USBDEV_EP_NUM > 6
dwc2_set_txfifo(busid, 6, CONFIG_USB_DWC2_TX6_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX6_FIFO_SIZE;
#endif
#if CONFIG_USBDEV_EP_NUM > 7
dwc2_set_txfifo(busid, 7, CONFIG_USB_DWC2_TX7_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX7_FIFO_SIZE;
#endif
#if CONFIG_USBDEV_EP_NUM > 8
dwc2_set_txfifo(busid, 8, CONFIG_USB_DWC2_TX8_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX8_FIFO_SIZE;
#endif
USB_ASSERT_MSG(fifo_num <= g_dwc2_udc[busid].user_params.total_fifo_size, "Your fifo config is overflow, please check");
}
USB_ASSERT_MSG(fifo_num <= (USB_OTG_GLB->GHWCFG3 >> 16), "Your fifo config is overflow, please check");
/* xxx32 chips do not follow (USB_OTG_GLB->GHWCFG3 >> 16) if hsphy_type is zero, they use 1.25KB(320 DWORD) */
USB_ASSERT_MSG(!((hsphy_type == 0) && (fifo_num > 320)), "Your fifo config is larger than 320 , please check");
if (g_dwc2_udc[busid].user_params.phy_type != DWC2_PHY_TYPE_PARAM_FS) {
USB_ASSERT_MSG(g_dwc2_udc[busid].user_params.device_rx_fifo_size >= (5 + 8 + 512 / 4 + 1 + 2 * 8 + 1), "Your rx fifo size config is invalid, please check");
} else {
USB_ASSERT_MSG(g_dwc2_udc[busid].user_params.device_rx_fifo_size >= (5 + 8 + 64 / 4 + 1 + 2 * 8 + 1), "Your rx fifo size config is invalid, please check");
}
ret = dwc2_flush_txfifo(busid, 0x10U);
ret = dwc2_flush_rxfifo(busid);
@@ -725,7 +671,7 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
USB_ASSERT_MSG(ep_idx < CONFIG_USBDEV_EP_NUM, "Ep addr %02x overflow", ep->bEndpointAddress);
USB_ASSERT_MSG(ep_idx < (g_dwc2_udc[busid].hw_params.num_dev_ep + 1), "Ep addr %02x overflow", ep->bEndpointAddress);
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
g_dwc2_udc[busid].out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
@@ -829,11 +775,11 @@ int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
}
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
if (ep_idx == 0) {
if ((ep_idx == 0) && g_dwc2_udc[busid].user_params.device_dma_enable) {
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
}
#endif
return 0;
}
@@ -884,9 +830,9 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
USB_ASSERT_MSG(!((uint32_t)data % 0x04), "dwc2 data must be 4-byte aligned");
#ifdef CONFIG_USB_DCACHE_ENABLE
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
#endif
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
}
if (!data && data_len) {
return -1;
@@ -935,18 +881,18 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1U << 29));
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
usb_dcache_clean((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
USB_OTG_INEP(ep_idx)->DIEPDMA = (uint32_t)data;
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
usb_dcache_clean((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
USB_OTG_INEP(ep_idx)->DIEPDMA = (uint32_t)data;
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
#else
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
/* Enable the Tx FIFO Empty Interrupt for this EP */
if (data_len > 0U) {
USB_OTG_DEV->DIEPEMPMSK |= 1UL << (ep_idx & 0x0f);
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
} else {
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
/* Enable the Tx FIFO Empty Interrupt for this EP */
if (data_len > 0U) {
USB_OTG_DEV->DIEPEMPMSK |= 1UL << (ep_idx & 0x0f);
}
}
#endif
return 0;
}
@@ -957,9 +903,9 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
USB_ASSERT_MSG(!((uint32_t)data % 0x04), "dwc2 data must be 4-byte aligned");
#ifdef CONFIG_USB_DCACHE_ENABLE
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
#endif
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
}
if (!data && data_len) {
return -1;
@@ -996,9 +942,9 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & data_len);
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
USB_OTG_OUTEP(ep_idx)->DOEPDMA = (uint32_t)data;
#endif
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_OTG_OUTEP(ep_idx)->DOEPDMA = (uint32_t)data;
}
if (g_dwc2_udc[busid].out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
if ((USB_OTG_DEV->DSTS & (1U << 8)) == 0U) {
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
@@ -1025,29 +971,30 @@ void USBD_IRQHandler(uint8_t busid)
return;
}
#ifndef CONFIG_USB_DWC2_DMA_ENABLE
/* Handle RxQLevel Interrupt */
if (gint_status & USB_OTG_GINTSTS_RXFLVL) {
USB_MASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL);
if (!g_dwc2_udc[busid].user_params.device_dma_enable) {
/* Handle RxQLevel Interrupt */
if (gint_status & USB_OTG_GINTSTS_RXFLVL) {
USB_MASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL);
temp = USB_OTG_GLB->GRXSTSP;
ep_idx = temp & USB_OTG_GRXSTSP_EPNUM;
temp = USB_OTG_GLB->GRXSTSP;
ep_idx = temp & USB_OTG_GRXSTSP_EPNUM;
if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_DATA_UPDT) {
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
if (read_count != 0) {
dwc2_ep_read(busid, g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, read_count);
g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf += read_count;
if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_DATA_UPDT) {
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
if (read_count != 0) {
dwc2_ep_read(busid, g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, read_count);
g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf += read_count;
}
} else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_SETUP_UPDT) {
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
dwc2_ep_read(busid, (uint8_t *)&g_dwc2_udc[busid].setup, read_count);
} else {
/* ... */
}
} else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_SETUP_UPDT) {
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
dwc2_ep_read(busid, (uint8_t *)&g_dwc2_udc[busid].setup, read_count);
} else {
/* ... */
USB_UNMASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL);
}
USB_UNMASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL);
}
#endif
if (gint_status & USB_OTG_GINTSTS_OEPINT) {
ep_idx = 0;
ep_intr = dwc2_get_outeps_intstatus(busid);
@@ -1057,14 +1004,25 @@ void USBD_IRQHandler(uint8_t busid)
if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC) {
if (ep_idx == 0) {
if (usbd_get_ep0_next_state(busid) == USBD_EP0_STATE_SETUP) {
goto process_setup; // goto ep0 setup, xfer_len is not used
}
if (g_dwc2_udc[busid].out_ep[ep_idx].xfer_len == 0) {
/* If ep0 xfer_len is 0, it means that we are in outstatus phase */
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = 0;
} else {
/* If ep0 xfer_len is not 0, it means that we are in outdata phase */
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
}
g_dwc2_udc[busid].out_ep[ep_idx].xfer_len = 0;
usb_dcache_invalidate((uintptr_t)g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, USB_ALIGN_UP(g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len, CONFIG_USB_ALIGN_SIZE));
usbd_event_ep_out_complete_handler(busid, 0x00, g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len);
if (usbd_get_ep0_next_state(busid) == USBD_EP0_STATE_SETUP) {
/* Out status, start reading setup */
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
} else {
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
g_dwc2_udc[busid].out_ep[ep_idx].xfer_len = 0;
usb_dcache_invalidate((uintptr_t)g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, USB_ALIGN_UP(g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len, CONFIG_USB_ALIGN_SIZE));
usbd_event_ep_out_complete_handler(busid, 0x00, g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len);
}
} else {
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
@@ -1073,7 +1031,9 @@ void USBD_IRQHandler(uint8_t busid)
usbd_event_ep_out_complete_handler(busid, ep_idx, g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len);
}
}
// clang-format off
process_setup:
// clang-format on
if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) {
usb_dcache_invalidate((uintptr_t)&g_dwc2_udc[busid].setup, USB_ALIGN_UP(8, CONFIG_USB_ALIGN_SIZE));
usbd_event_ep0_setup_complete_handler(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
@@ -1096,10 +1056,7 @@ void USBD_IRQHandler(uint8_t busid)
g_dwc2_udc[busid].in_ep[ep_idx].xfer_len = 0;
usbd_event_ep_in_complete_handler(busid, 0x80, g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len);
if (g_dwc2_udc[busid].setup.wLength && ((g_dwc2_udc[busid].setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
/* In status, start reading setup */
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
} else if (g_dwc2_udc[busid].setup.wLength == 0) {
if (usbd_get_ep0_next_state(busid) == USBD_EP0_STATE_SETUP) {
/* In status, start reading setup */
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
}
@@ -1109,8 +1066,10 @@ void USBD_IRQHandler(uint8_t busid)
usbd_event_ep_in_complete_handler(busid, ep_idx | 0x80, g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len);
}
}
if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) {
dwc2_tx_fifo_empty_procecss(busid, ep_idx);
if (!g_dwc2_udc[busid].user_params.device_dma_enable) {
if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) {
dwc2_tx_fifo_empty_procecss(busid, ep_idx);
}
}
}
ep_intr >>= 1U;
@@ -1124,7 +1083,7 @@ void USBD_IRQHandler(uint8_t busid)
dwc2_flush_txfifo(busid, 0x10U);
dwc2_flush_rxfifo(busid);
for (uint8_t i = 0U; i < CONFIG_USBDEV_EP_NUM; i++) {
for (uint8_t i = 0U; i < (g_dwc2_udc[busid].hw_params.num_dev_ep + 1); i++) {
if (i == 0U) {
USB_OTG_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK;
USB_OTG_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK;
@@ -1153,7 +1112,8 @@ void USBD_IRQHandler(uint8_t busid)
USB_OTG_DEV->DIEPMSK = USB_OTG_DIEPMSK_XFRCM;
memset(&g_dwc2_udc[busid], 0, sizeof(struct dwc2_udc));
memset(g_dwc2_udc[busid].in_ep, 0, sizeof(struct dwc2_ep_state) * 16);
memset(g_dwc2_udc[busid].out_ep, 0, sizeof(struct dwc2_ep_state) * 16);
usbd_event_reset_handler(busid);
/* Start reading setup */
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);

367
port/dwc2/usb_dwc2_param.h Normal file
View File

@@ -0,0 +1,367 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __USB_DWC2_PARAM_H__
#define __USB_DWC2_PARAM_H__
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
#define HSOTG_REG(x) (x)
#define dwc2_readl(addr) \
(*(volatile uint32_t *)(addr))
#define GUID_OFFSET HSOTG_REG(0x003c)
#define GSNPSID_OFFSET HSOTG_REG(0x0040)
#define GSNPSID_ID_MASK 0xffff0000
#define GHWCFG1_OFFSET HSOTG_REG(0x0044)
#define GHWCFG2_OFFSET HSOTG_REG(0x0048)
#define GHWCFG2_OTG_ENABLE_IC_USB (1U << 31)
#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1f << 26)
#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT 26
#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24)
#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT 24
#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22)
#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT 22
#define GHWCFG2_MULTI_PROC_INT (1 << 20)
#define GHWCFG2_DYNAMIC_FIFO (1 << 19)
#define GHWCFG2_PERIO_EP_SUPPORTED (1 << 18)
#define GHWCFG2_NUM_HOST_CHAN_MASK (0xf << 14)
#define GHWCFG2_NUM_HOST_CHAN_SHIFT 14
#define GHWCFG2_NUM_DEV_EP_MASK (0xf << 10)
#define GHWCFG2_NUM_DEV_EP_SHIFT 10
#define GHWCFG2_FS_PHY_TYPE_MASK (0x3 << 8)
#define GHWCFG2_FS_PHY_TYPE_SHIFT 8
#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED 0
#define GHWCFG2_FS_PHY_TYPE_DEDICATED 1
#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI 2
#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI 3
#define GHWCFG2_HS_PHY_TYPE_MASK (0x3 << 6)
#define GHWCFG2_HS_PHY_TYPE_SHIFT 6
#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
#define GHWCFG2_HS_PHY_TYPE_UTMI 1
#define GHWCFG2_HS_PHY_TYPE_ULPI 2
#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
#define GHWCFG2_POINT2POINT (1 << 5)
#define GHWCFG2_ARCHITECTURE_MASK (0x3 << 3)
#define GHWCFG2_ARCHITECTURE_SHIFT 3
#define GHWCFG2_SLAVE_ONLY_ARCH 0
#define GHWCFG2_EXT_DMA_ARCH 1
#define GHWCFG2_INT_DMA_ARCH 2
#define GHWCFG2_OP_MODE_MASK (0x7 << 0)
#define GHWCFG2_OP_MODE_SHIFT 0
#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE 0
#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE 1
#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE 2
#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
#define GHWCFG2_OP_MODE_UNDEFINED 7
#define GHWCFG3_OFFSET HSOTG_REG(0x004c)
#define GHWCFG3_DFIFO_DEPTH_MASK (0xffff << 16)
#define GHWCFG3_DFIFO_DEPTH_SHIFT 16
#define GHWCFG3_OTG_LPM_EN (1 << 15)
#define GHWCFG3_BC_SUPPORT (1 << 14)
#define GHWCFG3_OTG_ENABLE_HSIC (1 << 13)
#define GHWCFG3_ADP_SUPP (1 << 12)
#define GHWCFG3_SYNCH_RESET_TYPE (1 << 11)
#define GHWCFG3_OPTIONAL_FEATURES (1 << 10)
#define GHWCFG3_VENDOR_CTRL_IF (1 << 9)
#define GHWCFG3_I2C (1 << 8)
#define GHWCFG3_OTG_FUNC (1 << 7)
#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4)
#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT 4
#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xf << 0)
#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT 0
#define GHWCFG4_OFFSET HSOTG_REG(0x0050)
#define GHWCFG4_DESC_DMA_DYN (1U << 31)
#define GHWCFG4_DESC_DMA (1 << 30)
#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
#define GHWCFG4_NUM_IN_EPS_SHIFT 26
#define GHWCFG4_DED_FIFO_EN (1 << 25)
#define GHWCFG4_DED_FIFO_SHIFT 25
#define GHWCFG4_SESSION_END_FILT_EN (1 << 24)
#define GHWCFG4_B_VALID_FILT_EN (1 << 23)
#define GHWCFG4_A_VALID_FILT_EN (1 << 22)
#define GHWCFG4_VBUS_VALID_FILT_EN (1 << 21)
#define GHWCFG4_IDDIG_FILT_EN (1 << 20)
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xf << 16)
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14)
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2
#define GHWCFG4_ACG_SUPPORTED (1 << 12)
#define GHWCFG4_IPG_ISOC_SUPPORTED (1 << 11)
#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED (1 << 10)
#define GHWCFG4_XHIBER (1 << 7)
#define GHWCFG4_HIBER (1 << 6)
#define GHWCFG4_MIN_AHB_FREQ (1 << 5)
#define GHWCFG4_POWER_OPTIMIZ (1 << 4)
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xf << 0)
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT 0
/**
* struct dwc2_hw_params - Autodetected parameters.
*
* These parameters are the various parameters read from hardware
* registers during initialization. They typically contain the best
* supported or maximum value that can be configured in the
* corresponding dwc2_core_params value.
*
* The values that are not in dwc2_core_params are documented below.
*
* @snpsid: Value from SNPSID register
* @dev_ep_dirs: Direction of device endpoints (GHWCFG1)
*
* @op_mode: Mode of Operation
* 0 - HNP- and SRP-Capable OTG (Host & Device)
* 1 - SRP-Capable OTG (Host & Device)
* 2 - Non-HNP and Non-SRP Capable OTG (Host & Device)
* 3 - SRP-Capable Device
* 4 - Non-OTG Device
* 5 - SRP-Capable Host
* 6 - Non-OTG Host
* @arch: Architecture
* 0 - Slave only
* 1 - External DMA
* 2 - Internal DMA
* @enable_dynamic_fifo: 0 - Use coreConsultant-specified FIFO size parameters
* 1 - Allow dynamic FIFO sizing (default, if available)
* @host_channels: The number of host channel registers to use
* 1 to 16
* @hs_phy_type: High-speed PHY interface type
* 0 - High-speed interface not supported
* 1 - UTMI+
* 2 - ULPI
* 3 - UTMI+ and ULPI
* @fs_phy_type: Full-speed PHY interface type
* 0 - Full speed interface not supported
* 1 - Dedicated full speed interface
* 2 - FS pins shared with UTMI+ pins
* 3 - FS pins shared with ULPI pins
* @num_dev_ep: Number of device endpoints available
* @nperio_tx_q_depth:
* Non-Periodic Request Queue Depth
* 2, 4 or 8
* @dev_token_q_depth: Device Mode IN Token Sequence Learning Queue
* Depth
* 0 to 30
* @host_perio_tx_q_depth:
* Host Mode Periodic Request Queue Depth
* 2, 4 or 8
*
* @max_transfer_size: The maximum transfer size supported, in bytes
* 2047 to 65,535
* Actual maximum value is autodetected and also
* the default.
* @max_packet_count: The maximum number of packets in a transfer
* 15 to 511
* Actual maximum value is autodetected and also
* the default.
* @i2c_enable: Specifies whether to use the I2Cinterface for a full
* speed PHY. This parameter is only applicable if phy_type
* is FS.
* 0 - No (default)
* 1 - Yes
* @total_fifo_size: Total internal RAM for FIFOs (bytes)
* @lpm_mode: For enabling Link Power Management in the controller
* 0 - Disable
* 1 - Enable
*
* @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs
* are enabled for non-periodic IN endpoints in device
* mode.
* @num_dev_in_eps: Number of device IN endpoints available
* @num_dev_perio_in_ep: Number of device periodic IN endpoints
* available
* @dma_desc_enable: When DMA mode is enabled, specifies whether to use
* address DMA mode or descriptor DMA mode for accessing
* the data FIFOs. The driver will automatically detect the
* value for this if none is specified.
* 0 - Address DMA
* 1 - Descriptor DMA (default, if available)
* @power_optimized: Are power optimizations enabled?
* @hibernation: Is hibernation enabled?
* @utmi_phy_data_width: UTMI+ PHY data width
* 0 - 8 bits
* 1 - 16 bits
* 2 - 8 or 16 bits
* @acg_enable: For enabling Active Clock Gating in the controller
* 0 - Disable
* 1 - Enable
* @ipg_isoc_en: This feature indicates that the controller supports
* the worst-case scenario of Rx followed by Rx
* Interpacket Gap (IPG) (32 bitTimes) as per the utmi
* specification for any token following ISOC OUT token.
* 0 - Don't support
* 1 - Support
* @service_interval_mode: For enabling service interval based scheduling in the
* controller.
* 0 - Disable
* 1 - Enable
*/
struct dwc2_hw_params {
uint32_t snpsid;
uint32_t dev_ep_dirs;
unsigned op_mode : 3;
unsigned arch : 2;
unsigned enable_dynamic_fifo : 1;
unsigned host_channels : 5;
unsigned hs_phy_type : 2;
unsigned fs_phy_type : 2;
unsigned num_dev_ep : 4;
unsigned nperio_tx_q_depth : 3;
unsigned host_perio_tx_q_depth : 3;
unsigned dev_token_q_depth : 5;
unsigned max_transfer_size : 26;
unsigned max_packet_count : 11;
unsigned i2c_enable : 1;
unsigned total_fifo_size : 16;
unsigned lpm_mode : 1;
unsigned en_multiple_tx_fifo : 1;
unsigned num_dev_in_eps : 4;
unsigned num_dev_perio_in_ep : 4;
unsigned dma_desc_enable : 1;
unsigned power_optimized : 1;
unsigned hibernation : 1;
unsigned utmi_phy_data_width : 2;
unsigned acg_enable : 1;
unsigned ipg_isoc_en : 1;
unsigned service_interval_mode : 1;
};
#define DWC2_PHY_TYPE_PARAM_FS 0
#define DWC2_PHY_TYPE_PARAM_UTMI 1
#define DWC2_PHY_TYPE_PARAM_ULPI 2
struct dwc2_user_params {
uint8_t phy_type;
uint8_t phy_utmi_width;
bool device_dma_enable;
bool device_dma_desc_enable;
/* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for
* status information) + (2 * number of OUT endpoints) + 1 for Global NAK
*/
uint16_t device_rx_fifo_size;
/* IN Endpoints Max packet Size / 4 */
uint16_t device_tx_fifo_size[MAX_EPS_CHANNELS];
bool host_dma_desc_enable;
/*
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
*/
uint16_t host_rx_fifo_size;
/* largest non-periodic USB packet used / 4 */
uint16_t host_nperio_tx_fifo_size;
/* largest periodic USB packet used / 4 */
uint16_t host_perio_tx_fifo_size;
uint32_t device_gccfg;
uint32_t host_gccfg;
bool b_session_valid_override;
uint32_t total_fifo_size;
};
struct usb_dwc2_user_fifo_config {
/* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for
* status information) + (2 * number of OUT endpoints) + 1 for Global NAK
*/
uint16_t device_rx_fifo_size;
/* IN Endpoints Max packet Size / 4 */
uint16_t device_tx_fifo_size[MAX_EPS_CHANNELS];
};
static inline void dwc2_get_hwparams(uint32_t reg_base, struct dwc2_hw_params *hw)
{
unsigned int width;
uint32_t snpsid, hwcfg1, hwcfg2, hwcfg3, hwcfg4;
snpsid = dwc2_readl(reg_base + GSNPSID_OFFSET);
hwcfg1 = dwc2_readl(reg_base + GHWCFG1_OFFSET);
hwcfg2 = dwc2_readl(reg_base + GHWCFG2_OFFSET);
hwcfg3 = dwc2_readl(reg_base + GHWCFG3_OFFSET);
hwcfg4 = dwc2_readl(reg_base + GHWCFG4_OFFSET);
/* snpsid */
hw->snpsid = snpsid;
/* hwcfg1 */
hw->dev_ep_dirs = hwcfg1;
/* hwcfg2 */
hw->op_mode = (hwcfg2 & GHWCFG2_OP_MODE_MASK) >>
GHWCFG2_OP_MODE_SHIFT;
hw->arch = (hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >>
GHWCFG2_ARCHITECTURE_SHIFT;
hw->enable_dynamic_fifo = !!(hwcfg2 & GHWCFG2_DYNAMIC_FIFO);
hw->host_channels = 1 + ((hwcfg2 & GHWCFG2_NUM_HOST_CHAN_MASK) >>
GHWCFG2_NUM_HOST_CHAN_SHIFT);
hw->hs_phy_type = (hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >>
GHWCFG2_HS_PHY_TYPE_SHIFT;
hw->fs_phy_type = (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >>
GHWCFG2_FS_PHY_TYPE_SHIFT;
hw->num_dev_ep = (hwcfg2 & GHWCFG2_NUM_DEV_EP_MASK) >>
GHWCFG2_NUM_DEV_EP_SHIFT;
hw->nperio_tx_q_depth =
(hwcfg2 & GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK) >>
GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT << 1;
hw->host_perio_tx_q_depth =
(hwcfg2 & GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK) >>
GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT << 1;
hw->dev_token_q_depth =
(hwcfg2 & GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK) >>
GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT;
/* hwcfg3 */
width = (hwcfg3 & GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT;
hw->max_transfer_size = (1 << (width + 11)) - 1;
width = (hwcfg3 & GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT;
hw->max_packet_count = (1 << (width + 4)) - 1;
hw->i2c_enable = !!(hwcfg3 & GHWCFG3_I2C);
hw->total_fifo_size = (hwcfg3 & GHWCFG3_DFIFO_DEPTH_MASK) >>
GHWCFG3_DFIFO_DEPTH_SHIFT;
hw->lpm_mode = !!(hwcfg3 & GHWCFG3_OTG_LPM_EN);
/* hwcfg4 */
hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN);
hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >>
GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT;
hw->num_dev_in_eps = (hwcfg4 & GHWCFG4_NUM_IN_EPS_MASK) >>
GHWCFG4_NUM_IN_EPS_SHIFT;
hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA);
hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ);
hw->hibernation = !!(hwcfg4 & GHWCFG4_HIBER);
hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >>
GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT;
hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED);
hw->ipg_isoc_en = !!(hwcfg4 & GHWCFG4_IPG_ISOC_SUPPORTED);
hw->service_interval_mode = !!(hwcfg4 &
GHWCFG4_SERVICE_INTERVAL_SUPPORTED);
}
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params);
void dwc2_get_user_fifo_config(uint32_t reg_base, struct usb_dwc2_user_fifo_config *config);
#endif

View File

@@ -209,12 +209,15 @@ typedef struct
#define USB_OTG_HCFG_FSLSPCS_Pos (0U)
#define USB_OTG_HCFG_FSLSPCS_Msk (0x3UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000003 */
#define USB_OTG_HCFG_FSLSPCS USB_OTG_HCFG_FSLSPCS_Msk /*!< FS/LS PHY clock select */
#define USB_OTG_HCFG_FSLSPCS_0 (0x1UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000001 */
#define USB_OTG_HCFG_FSLSPCS_1 (0x2UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000002 */
#define USB_OTG_HCFG_FSLSPCLKSEL_30_60_MHZ (0x0UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000000 */
#define USB_OTG_HCFG_FSLSPCLKSEL_48_MHZ (0x1UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000001 */
#define USB_OTG_HCFG_FSLSPCLKSEL_6_MHZ (0x2UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000002 */
#define USB_OTG_HCFG_FSLSS_Pos (2U)
#define USB_OTG_HCFG_FSLSS_Msk (0x1UL << USB_OTG_HCFG_FSLSS_Pos) /*!< 0x00000004 */
#define USB_OTG_HCFG_FSLSS USB_OTG_HCFG_FSLSS_Msk /*!< FS- and LS-only support */
#define USB_OTG_HFIR_RELOAD_CTRL_Pos (16U)
#define USB_OTG_HFIR_RELOAD_CTRL_Msk (0x1UL << USB_OTG_HFIR_RELOAD_CTRL_Pos)
#define USB_OTG_HFIR_RELOAD_CTRL USB_OTG_HFIR_RELOAD_CTRL_Msk
/******************** Bit definition for USB_OTG_DCFG register ********************/
#define USB_OTG_DCFG_DSPD_Pos (0U)
@@ -385,12 +388,20 @@ typedef struct
#define USB_OTG_GUSBCFG_TOCAL_Pos (0U)
#define USB_OTG_GUSBCFG_TOCAL_Msk (0x7UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000007 */
#define USB_OTG_GUSBCFG_TOCAL USB_OTG_GUSBCFG_TOCAL_Msk /*!< FS timeout calibration */
#define USB_OTG_GUSBCFG_TOCAL_0 (0x1UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000001 */
#define USB_OTG_GUSBCFG_TOCAL_1 (0x2UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000002 */
#define USB_OTG_GUSBCFG_TOCAL_2 (0x4UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000004 */
#define USB_OTG_GUSBCFG_PHYIF_Pos (3U)
#define USB_OTG_GUSBCFG_PHYIF_Msk (0x1UL << USB_OTG_GUSBCFG_PHYIF_Pos)
#define USB_OTG_GUSBCFG_PHYIF USB_OTG_GUSBCFG_PHYIF_Msk
#define USB_OTG_GUSBCFG_PHYIF8 (0x0UL << USB_OTG_GUSBCFG_PHYIF_Pos)
#define USB_OTG_GUSBCFG_PHYIF16 (0x1UL << USB_OTG_GUSBCFG_PHYIF_Pos)
#define USB_OTG_GUSBCFG_ULPI_UTMI_SEL_Pos (4U)
#define USB_OTG_GUSBCFG_ULPI_UTMI_SEL_Msk (0x1UL << USB_OTG_GUSBCFG_ULPI_UTMI_SEL_Pos)
#define USB_OTG_GUSBCFG_ULPI_UTMI_SEL USB_OTG_GUSBCFG_ULPI_UTMI_SEL_Msk
#define USB_OTG_GUSBCFG_PHYSEL_Pos (6U)
#define USB_OTG_GUSBCFG_PHYSEL_Msk (0x1UL << USB_OTG_GUSBCFG_PHYSEL_Pos) /*!< 0x00000040 */
#define USB_OTG_GUSBCFG_PHYSEL USB_OTG_GUSBCFG_PHYSEL_Msk /*!< USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */
#define USB_OTG_GUSBCFG_DDR_SEL_Pos (7U)
#define USB_OTG_GUSBCFG_DDR_SEL_Msk (0x1UL << USB_OTG_GUSBCFG_DDR_SEL_Pos)
#define USB_OTG_GUSBCFG_DDR_SEL USB_OTG_GUSBCFG_DDR_SEL_Msk
#define USB_OTG_GUSBCFG_SRPCAP_Pos (8U)
#define USB_OTG_GUSBCFG_SRPCAP_Msk (0x1UL << USB_OTG_GUSBCFG_SRPCAP_Pos) /*!< 0x00000100 */
#define USB_OTG_GUSBCFG_SRPCAP USB_OTG_GUSBCFG_SRPCAP_Msk /*!< SRP-capable */
@@ -1720,7 +1731,5 @@ typedef struct
void usb_dc_low_level_init(uint8_t busid);
void usb_dc_low_level_deinit(uint8_t busid);
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base);
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base);
void usbd_dwc2_delay_ms(uint8_t ms);
#endif

View File

@@ -3,60 +3,106 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usb_config.h"
#include "stdint.h"
#include "usb_dwc2_reg.h"
#include "usbd_core.h"
#include "usbh_core.h"
#include "usb_dwc2_param.h"
extern unsigned int system_core_clock;
uint32_t SystemCoreClock;
/* you can find this config in function: usb_global_init, file:at32fxxx_usb.c, for example:
*
* usbx->gccfg_bit.pwrdown = TRUE;
* usbx->gccfg_bit.avalidsesen = TRUE;
* usbx->gccfg_bit.bvalidsesen = TRUE;
*
*/
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
#ifdef AT32F415xx
.device_gccfg = ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21)),
#else
.device_gccfg = ((1 << 16) | (1 << 21)),
#endif
.total_fifo_size = 320 // 1280 byte
};
#if __has_include("at32f402_405.h")
#include "at32f402_405.h"
const struct dwc2_user_params param_pb14_pb15 = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
.device_dma_enable = true,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (1008 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 628,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
.device_gccfg = ((1 << 16) | (1 << 21)),
.host_gccfg = ((1 << 16) | (1 << 21))
};
#endif
#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
{
SystemCoreClock = system_core_clock;
#ifdef CONFIG_USB_HS
return ((1 << 16) | (1 << 21));
#if __has_include("at32f402_405.h")
if (reg_base == OTGHS_BASE) {
memcpy(params, &param_pb14_pb15, sizeof(struct dwc2_user_params));
} else {
memcpy(params, &param_pa11_pa12, sizeof(struct dwc2_user_params));
}
#else
// AT32F415
#if defined(AT32F415RCT7) || defined(AT32F415RCT7_7) || defined(AT32F415CCT7) || \
defined(AT32F415CCU7) || defined(AT32F415KCU7_4) || defined(AT32F415RBT7) || \
defined(AT32F415RBT7_7) || defined(AT32F415CBT7) || defined(AT32F415CBU7) || \
defined(AT32F415KBU7_4) || defined(AT32F415R8T7) || defined(AT32F415R8T7_7) || \
defined(AT32F415C8T7) || defined(AT32F415K8U7_4)
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
#else
return ((1 << 16) | (1 << 21));
memcpy(params, &param_pa11_pa12, sizeof(struct dwc2_user_params));
#endif
#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++) {
params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
}
#endif
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
SystemCoreClock = system_core_clock;
#ifdef CONFIG_USB_HS
return ((1 << 16) | (1 << 21));
#else
// AT32F415
#if defined(AT32F415RCT7) || defined(AT32F415RCT7_7) || defined(AT32F415CCT7) || \
defined(AT32F415CCU7) || defined(AT32F415KCU7_4) || defined(AT32F415RBT7) || \
defined(AT32F415RBT7_7) || defined(AT32F415CBT7) || defined(AT32F415CBU7) || \
defined(AT32F415KBU7_4) || defined(AT32F415R8T7) || defined(AT32F415R8T7_7) || \
defined(AT32F415C8T7) || defined(AT32F415K8U7_4)
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
#else
return ((1 << 16) | (1 << 21));
#endif
#endif
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{

View File

@@ -12,6 +12,7 @@
#include "freertos/task.h"
#include "usbd_core.h"
#include "usbh_core.h"
#include "usb_dwc2_param.h"
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
@@ -30,6 +31,95 @@ uint32_t SystemCoreClock = (DEFAULT_CPU_FREQ_MHZ * 1000 * 1000);
static usb_phy_handle_t s_phy_handle = NULL;
static intr_handle_t s_interrupt_handle = NULL;
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
const struct dwc2_user_params param_fs = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = true,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (200 - 16 * 7),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 16, // 64 byte
[5] = 16, // 64 byte
[6] = 16, // 64 byte
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 80,
.host_nperio_tx_fifo_size = 60, // 240 byte
.host_perio_tx_fifo_size = 60, // 240 byte
};
#elif CONFIG_IDF_TARGET_ESP32P4
const struct dwc2_user_params param_fs = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = true,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (200 - 16 * 7),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 16, // 64 byte
[5] = 16, // 64 byte
[6] = 16, // 64 byte
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = (200 - 60 - 60),
.host_nperio_tx_fifo_size = 60, // 240 byte
.host_perio_tx_fifo_size = 60, // 240 byte
};
const struct dwc2_user_params param_hs = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
.device_dma_enable = true,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (896 - 16 - 128 - 128 - 128 - 128 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 128, // 512 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 16, // 64 byte
[6] = 16, // 64 byte
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = (896 - 128 - 128),
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 128, // 512 byte
};
#endif
static void usb_dc_interrupt_cb(void *arg_pv)
{
extern void USBD_IRQHandler(uint8_t busid);
@@ -75,11 +165,6 @@ void usb_dc_low_level_deinit(uint8_t busid)
}
}
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
return 0;
}
static void usb_hc_interrupt_cb(void *arg_pv)
{
extern void USBH_IRQHandler(uint8_t busid);
@@ -129,9 +214,28 @@ void usb_hc_low_level_deinit(struct usbh_bus *bus)
}
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
{
return 0;
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
memcpy(params, &param_fs, sizeof(struct dwc2_user_params));
#elif CONFIG_IDF_TARGET_ESP32P4
if (reg_base == 0x50000000UL) {
memcpy(params, &param_hs, sizeof(struct dwc2_user_params));
} else {
memcpy(params, &param_fs, sizeof(struct dwc2_user_params));
}
#endif
#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++)
{
params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
}
#endif
}
void usbd_dwc2_delay_ms(uint8_t ms)

View File

@@ -7,6 +7,10 @@
#include "stdint.h"
#include "usb_dwc2_reg.h"
#if 1
#error you need to modify some usb register values then use this chip
#endif
#if CONFIG_USBDEV_EP_NUM != 4 && CONFIG_USBDEV_EP_NUM != 6
#error "gd32 only has 4 endpoints for pa11/pa12 and 6 endpoints for pb14/pb15"
#endif

View File

@@ -5,22 +5,549 @@
*/
#include "usbd_core.h"
#include "usbh_core.h"
#include "usb_dwc2_param.h"
#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
#if __has_include("stm32f1xx_hal.h")
#include "stm32f1xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = { 0 }; // do not support
#if defined(HAL_HCD_MODULE_ENABLED)
#error "HAL_HCD_MODULE_ENABLED is not supported for STM32F1xx, please use HAL_PCD_MODULE_ENABLED"
#endif
#elif __has_include("stm32f2xx_hal.h")
#include "stm32f2xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = {
#ifdef CONFIG_USB_HS
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#else
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
#endif
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (1012 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 628,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
#ifdef CONFIG_USB_HS
.device_gccfg = 0,
.host_gccfg = 0,
#else
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS hs:0
.host_gccfg = ((1 << 16) | (1 << 21)) // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS hs:0
#endif
};
#elif __has_include("stm32f4xx_hal.h")
#include "stm32f4xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || \
defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || \
defined(STM32F423xx)
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.b_session_valid_override = true,
#else
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS
#endif
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = {
#ifdef CONFIG_USB_HS
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#else
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
#endif
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (1012 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 628,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
#ifdef CONFIG_USB_HS
.device_gccfg = 0,
.host_gccfg = 0,
#else
#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || \
defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || \
defined(STM32F423xx)
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.b_session_valid_override = true,
#else
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS hs:0
.host_gccfg = ((1 << 16) | (1 << 21)) // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS hs:0
#endif
#endif
};
#elif __has_include("stm32f7xx_hal.h")
#include "stm32f7xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.b_session_valid_override = true,
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = {
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#else
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
#endif
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (1006 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 622,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
.device_gccfg = (1 << 23), // USB_OTG_GCCFG_PHYHSEN
.host_gccfg = (1 << 23), // USB_OTG_GCCFG_PHYHSEN
#else
#ifdef CONFIG_USB_HS
.device_gccfg = 0,
.host_gccfg = 0,
#else
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
#endif
#endif
.b_session_valid_override = true
};
#elif __has_include("stm32h7xx_hal.h")
#include "stm32h7xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS, // DWC2_PHY_TYPE_PARAM_UTMI
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (952 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 568,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
.b_session_valid_override = true
};
const struct dwc2_user_params param_pb14_pb15 = {
#ifdef CONFIG_USB_HS
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#else
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
#endif
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (952 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 568,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
#ifdef CONFIG_USB_HS
.device_gccfg = 0,
.host_gccfg = 0,
#else
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
#endif
.b_session_valid_override = true
};
#elif __has_include("stm32h7rsxx_hal.h")
#include "stm32h7rsxx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.b_session_valid_override = true,
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (952 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 568,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
.device_gccfg = ((1 << 23) | (1 << 24)), // hs: USB_OTG_GCCFG_VBVALEXTOEN | USB_OTG_GCCFG_VBVALOVAL
.host_gccfg = (1 << 25) // hs: USB_OTG_GCCFG_PULLDOWNEN
};
#elif __has_include("stm32l4xx_hal.h")
#include "stm32l4xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = (1 << 16),
.b_session_valid_override = true,
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = { 0 }; // do not support
#if defined(HAL_HCD_MODULE_ENABLED)
#error "HAL_HCD_MODULE_ENABLED is not supported for STM32L4xx, please use HAL_PCD_MODULE_ENABLED"
#endif
#elif __has_include("stm32u5xx_hal.h")
#include "stm32u5xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = (1 << 16),
.b_session_valid_override = true,
.total_fifo_size = 320 // 1280 byte
};
#if defined(STM32U595xx) || defined(STM32U5A5xx) || defined(STM32U599xx) || defined(STM32U5A9xx) || \
defined(STM32U5F7xx) || defined(STM32U5G7xx) || defined(STM32U5F9xx) || defined(STM32U5G9xx)
const struct dwc2_user_params param_pb14_pb15 = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (952 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 568,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
.device_gccfg = ((1 << 23) | (1 << 24)), // hs: USB_OTG_GCCFG_VBVALEXTOEN | USB_OTG_GCCFG_VBVALOVAL
.host_gccfg = (1 << 25) // hs: USB_OTG_GCCFG_PULLDOWNEN
};
#else
const struct dwc2_user_params param_pb14_pb15 = { 0 }; // do not support
#endif
#endif
#endif // CONFIG_USB_DWC2_CUSTOM_PARAM
#if !defined(HAL_HCD_MODULE_ENABLED) && !defined(HAL_PCD_MODULE_ENABLED)
#error please define HAL_HCD_MODULE_ENABLED or HAL_PCD_MODULE_ENABLED in stm32xxx_hal_conf.h
@@ -36,74 +563,6 @@ static usb_dwc2_irq g_usb_dwc2_irq[2];
static uint8_t g_usb_dwc2_busid[2] = { 0, 0 };
static struct dwc2_instance g_dwc2_instance;
#ifdef HAL_PCD_MODULE_ENABLED
void usb_dc_low_level_init(uint8_t busid)
{
if (g_usbdev_bus[busid].reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = busid;
g_usb_dwc2_irq[1] = USBD_IRQHandler;
} else {
g_usb_dwc2_busid[0] = busid;
g_usb_dwc2_irq[0] = USBD_IRQHandler;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)g_usbdev_bus[busid].reg_base;
HAL_PCD_MspInit((PCD_HandleTypeDef *)&g_dwc2_instance);
}
void usb_dc_low_level_deinit(uint8_t busid)
{
if (g_usbdev_bus[busid].reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = 0;
g_usb_dwc2_irq[1] = NULL;
} else {
g_usb_dwc2_busid[0] = 0;
g_usb_dwc2_irq[0] = NULL;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)g_usbdev_bus[busid].reg_base;
HAL_PCD_MspDeInit((PCD_HandleTypeDef *)&g_dwc2_instance);
}
#endif
#ifdef HAL_HCD_MODULE_ENABLED
void usb_hc_low_level_init(struct usbh_bus *bus)
{
if (bus->hcd.reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = bus->hcd.hcd_id;
g_usb_dwc2_irq[1] = USBH_IRQHandler;
} else {
g_usb_dwc2_busid[0] = bus->hcd.hcd_id;
g_usb_dwc2_irq[0] = USBH_IRQHandler;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)bus->hcd.reg_base;
HAL_HCD_MspInit((HCD_HandleTypeDef *)&g_dwc2_instance);
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
if (bus->hcd.reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = 0;
g_usb_dwc2_irq[1] = NULL;
} else {
g_usb_dwc2_busid[0] = 0;
g_usb_dwc2_irq[0] = NULL;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)bus->hcd.reg_base;
HAL_HCD_MspDeInit((HCD_HandleTypeDef *)&g_dwc2_instance);
}
#endif
/* you can find this config in function: USB_DevInit, file:stm32xxx_ll_usb.c, for example:
*
* USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
* USBx->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS;
* USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN;
* USBx->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN;
*
*/
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
/**
* @brief Enables control of a High Speed USB PHY
@@ -163,62 +622,96 @@ static int usb_hsphy_init(uint32_t hse_value)
}
#endif
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
#ifdef HAL_PCD_MODULE_ENABLED
void usb_dc_low_level_init(uint8_t busid)
{
#if __has_include("stm32h7xx.h") || __has_include("stm32f7xx.h") || __has_include("stm32l4xx.h")
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(reg_base))
/* B-peripheral session valid override enable */
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
#endif
if (g_usbdev_bus[busid].reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = busid;
g_usb_dwc2_irq[1] = USBD_IRQHandler;
} else {
g_usb_dwc2_busid[0] = busid;
g_usb_dwc2_irq[0] = USBD_IRQHandler;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)g_usbdev_bus[busid].reg_base;
HAL_PCD_MspInit((PCD_HandleTypeDef *)&g_dwc2_instance);
#ifdef CONFIG_USB_HS
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
USB_OTG_GLB->GCCFG = (1 << 23);
usb_hsphy_init(25000000U);
return (1 << 23); /* Enable USB HS PHY USBx->GCCFG |= USB_OTG_GCCFG_PHYHSEN;*/
#elif __has_include("stm32h7rsxx.h")
return ((1 << 23) | (1 << 24));
#else
return 0;
#endif
#else
#if __has_include("stm32h7xx.h") || __has_include("stm32f7xx.h") || __has_include("stm32l4xx.h")
return (1 << 16);
#else
return ((1 << 16) | (1 << 21));
#endif
#endif
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
void usb_dc_low_level_deinit(uint8_t busid)
{
#if __has_include("stm32h7xx.h") || __has_include("stm32f7xx.h") || __has_include("stm32l4xx.h")
#define USB_OTG_GLB ((USB_OTG_GlobalTypeDef *)(reg_base))
/* B-peripheral session valid override enable */
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOVAL;
if (g_usbdev_bus[busid].reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = 0;
g_usb_dwc2_irq[1] = NULL;
} else {
g_usb_dwc2_busid[0] = 0;
g_usb_dwc2_irq[0] = NULL;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)g_usbdev_bus[busid].reg_base;
HAL_PCD_MspDeInit((PCD_HandleTypeDef *)&g_dwc2_instance);
}
#endif
#ifdef CONFIG_USB_HS
#ifdef HAL_HCD_MODULE_ENABLED
void usb_hc_low_level_init(struct usbh_bus *bus)
{
if (bus->hcd.reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = bus->hcd.hcd_id;
g_usb_dwc2_irq[1] = USBH_IRQHandler;
} else {
g_usb_dwc2_busid[0] = bus->hcd.hcd_id;
g_usb_dwc2_irq[0] = USBH_IRQHandler;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)bus->hcd.reg_base;
HAL_HCD_MspInit((HCD_HandleTypeDef *)&g_dwc2_instance);
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
USB_OTG_GLB->GCCFG = (1 << 23);
usb_hsphy_init(25000000U);
return (1 << 23); /* Enable USB HS PHY USBx->GCCFG |= USB_OTG_GCCFG_PHYHSEN;*/
#elif __has_include("stm32h7rsxx.h")
return (1 << 25);
#else
return 0;
#endif
#else
#if __has_include("stm32h7xx.h") || __has_include("stm32f7xx.h") || __has_include("stm32l4xx.h")
return (1 << 16);
#else
return ((1 << 16) | (1 << 21));
#endif
#endif
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
if (bus->hcd.reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = 0;
g_usb_dwc2_irq[1] = NULL;
} else {
g_usb_dwc2_busid[0] = 0;
g_usb_dwc2_irq[0] = NULL;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)bus->hcd.reg_base;
HAL_HCD_MspDeInit((HCD_HandleTypeDef *)&g_dwc2_instance);
}
#endif
#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
{
if (reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
memcpy(params, &param_pb14_pb15, sizeof(struct dwc2_user_params));
} else {
memcpy(params, &param_pa11_pa12, sizeof(struct dwc2_user_params));
}
#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++)
{
params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
}
#endif
}
#endif
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)

View File

@@ -6,28 +6,7 @@
#include "usbh_core.h"
#include "usbh_hub.h"
#include "usb_dwc2_reg.h"
#ifndef CONFIG_USBHOST_PIPE_NUM
#define CONFIG_USBHOST_PIPE_NUM 12
#endif
/* largest non-periodic USB packet used / 4 */
#ifndef CONFIG_USB_DWC2_NPTX_FIFO_SIZE
#define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (512 / 4)
#endif
/* largest periodic USB packet used / 4 */
#ifndef CONFIG_USB_DWC2_PTX_FIFO_SIZE
#define CONFIG_USB_DWC2_PTX_FIFO_SIZE (1024 / 4)
#endif
/*
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
*/
#ifndef CONFIG_USB_DWC2_RX_FIFO_SIZE
#define CONFIG_USB_DWC2_RX_FIFO_SIZE ((1012 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
#endif
#include "usb_dwc2_param.h"
#define USB_OTG_GLB ((DWC2_GlobalTypeDef *)(bus->hcd.reg_base))
#define USB_OTG_PCGCCTL *(__IO uint32_t *)((uint32_t)bus->hcd.reg_base + USB_OTG_PCGCCTL_BASE)
@@ -56,8 +35,9 @@ struct dwc2_hcd {
volatile bool port_csc;
volatile bool port_pec;
volatile bool port_occ;
uint32_t GSNPSID;
struct dwc2_chan chan_pool[CONFIG_USBHOST_PIPE_NUM];
struct dwc2_hw_params hw_params;
struct dwc2_user_params user_params;
struct dwc2_chan chan_pool[16];
} g_dwc2_hcd[CONFIG_USBHOST_MAX_BUS];
#define DWC2_EP0_STATE_SETUP 0
@@ -81,7 +61,7 @@ static inline int dwc2_reset(struct usbh_bus *bus)
count = 0U;
USB_OTG_GLB->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
if (g_dwc2_hcd[bus->hcd.hcd_id].GSNPSID < 0x4F54420AU) {
if (g_dwc2_hcd[bus->hcd.hcd_id].hw_params.snpsid < 0x4F54420AU) {
do {
if (++count > 200000U) {
USB_LOG_ERR("DWC2 reset timeout\r\n");
@@ -106,22 +86,43 @@ static inline int dwc2_reset(struct usbh_bus *bus)
static inline int dwc2_core_init(struct usbh_bus *bus)
{
int ret;
#if defined(CONFIG_USB_HS)
/* Init The ULPI Interface */
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL);
uint32_t regval;
/* Select vbus source */
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
/* Select FS Embedded PHY */
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
} else {
regval = USB_OTG_GLB->GUSBCFG;
regval &= ~USB_OTG_GUSBCFG_PHYSEL;
/* disable external vbus source */
regval &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
/* disable ULPI FS/LS */
regval &= ~(USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_ULPICSM);
switch (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_type) {
case DWC2_PHY_TYPE_PARAM_ULPI:
regval |= USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
regval &= ~USB_OTG_GUSBCFG_PHYIF16;
regval &= ~USB_OTG_GUSBCFG_DDR_SEL;
break;
case DWC2_PHY_TYPE_PARAM_UTMI:
regval &= ~USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
regval &= ~USB_OTG_GUSBCFG_PHYIF16;
if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_utmi_width == 16) {
regval |= USB_OTG_GUSBCFG_PHYIF16;
}
break;
default:
break;
}
USB_OTG_GLB->GUSBCFG = regval;
}
//USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_ULPIEVBUSD;
/* Reset after a PHY select */
ret = dwc2_reset(bus);
#else
/* Select FS Embedded PHY */
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
/* Reset after a PHY select */
ret = dwc2_reset(bus);
#endif
return ret;
}
@@ -390,13 +391,60 @@ static inline uint16_t dwc2_get_full_frame_num(struct usbh_bus *bus)
return ((frame & 0x3FFF) >> 3);
}
/**
* dwc2_calc_frame_interval() - Calculates the correct frame Interval value for
* the HFIR register according to PHY type and speed
*
* NOTE: The caller can modify the value of the HFIR register only after the
* Port Enable bit of the Host Port Control and Status register (HPRT.EnaPort)
* has been set
*/
uint32_t dwc2_calc_frame_interval(struct usbh_bus *bus)
{
uint32_t usbcfg;
uint32_t hprt0;
int clock = 60; /* default value */
usbcfg = USB_OTG_GLB->GUSBCFG;
hprt0 = USB_OTG_HPRT;
if (!(usbcfg & USB_OTG_GUSBCFG_PHYSEL) && (usbcfg & USB_OTG_GUSBCFG_ULPI_UTMI_SEL) &&
!(usbcfg & USB_OTG_GUSBCFG_PHYIF16))
clock = 60;
if ((usbcfg & USB_OTG_GUSBCFG_PHYSEL) && g_dwc2_hcd[bus->hcd.hcd_id].hw_params.fs_phy_type ==
GHWCFG2_FS_PHY_TYPE_SHARED_ULPI)
clock = 48;
if (!(usbcfg & USB_OTG_GUSBCFG_PHYLPCS) && !(usbcfg & USB_OTG_GUSBCFG_PHYSEL) &&
!(usbcfg & USB_OTG_GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & USB_OTG_GUSBCFG_PHYIF16))
clock = 30;
if (!(usbcfg & USB_OTG_GUSBCFG_PHYLPCS) && !(usbcfg & USB_OTG_GUSBCFG_PHYSEL) &&
!(usbcfg & USB_OTG_GUSBCFG_ULPI_UTMI_SEL) && !(usbcfg & USB_OTG_GUSBCFG_PHYIF16))
clock = 60;
if ((usbcfg & USB_OTG_GUSBCFG_PHYLPCS) && !(usbcfg & USB_OTG_GUSBCFG_PHYSEL) &&
!(usbcfg & USB_OTG_GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & USB_OTG_GUSBCFG_PHYIF16))
clock = 48;
if ((usbcfg & USB_OTG_GUSBCFG_PHYSEL) && !(usbcfg & USB_OTG_GUSBCFG_PHYIF16) &&
g_dwc2_hcd[bus->hcd.hcd_id].hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_SHARED_UTMI)
clock = 48;
if ((usbcfg & USB_OTG_GUSBCFG_PHYSEL) &&
g_dwc2_hcd[bus->hcd.hcd_id].hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED)
clock = 48;
if ((hprt0 & USB_OTG_HPRT_PSPD) >> USB_OTG_HPRT_PSPD_Pos == HPRT0_PRTSPD_HIGH_SPEED)
/* High speed case */
return 125 * clock - 1;
/* FS/LS case */
return 1000 * clock - 1;
}
static int dwc2_chan_alloc(struct usbh_bus *bus)
{
size_t flags;
int chidx;
flags = usb_osal_enter_critical_section();
for (chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
for (chidx = 0; chidx < g_dwc2_hcd[bus->hcd.hcd_id].hw_params.host_channels; chidx++) {
if (!g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].inuse) {
g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].inuse = true;
usb_osal_leave_critical_section(flags);
@@ -544,18 +592,11 @@ __WEAK void usb_hc_low_level_deinit(struct usbh_bus *bus)
int usb_hc_init(struct usbh_bus *bus)
{
int ret;
uint8_t channels;
memset(&g_dwc2_hcd[bus->hcd.hcd_id], 0, sizeof(struct dwc2_hcd));
for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].waitsem = usb_osal_sem_create(0);
}
usb_hc_low_level_init(bus);
channels = ((USB_OTG_GLB->GHWCFG2 & (0x0f << 14)) >> 14) + 1;
USB_LOG_INFO("========== dwc2 hcd params ==========\r\n");
USB_LOG_INFO("CID:%08x\r\n", (unsigned int)USB_OTG_GLB->CID);
USB_LOG_INFO("GSNPSID:%08x\r\n", (unsigned int)USB_OTG_GLB->GSNPSID);
@@ -564,34 +605,70 @@ int usb_hc_init(struct usbh_bus *bus)
USB_LOG_INFO("GHWCFG3:%08x\r\n", (unsigned int)USB_OTG_GLB->GHWCFG3);
USB_LOG_INFO("GHWCFG4:%08x\r\n", (unsigned int)USB_OTG_GLB->GHWCFG4);
USB_LOG_INFO("dwc2 has %d channels and dfifo depth(32-bit words) is %d\r\n", channels, (USB_OTG_GLB->GHWCFG3 >> 16));
dwc2_get_hwparams(bus->hcd.reg_base, &g_dwc2_hcd[bus->hcd.hcd_id].hw_params);
dwc2_get_user_params(bus->hcd.reg_base, &g_dwc2_hcd[bus->hcd.hcd_id].user_params);
USB_ASSERT_MSG(((USB_OTG_GLB->GHWCFG2 & (0x3U << 3)) >> 3) == 2, "This dwc2 version does not support dma mode, so stop working");
USB_ASSERT_MSG(channels >= CONFIG_USBHOST_PIPE_NUM, "dwc2 has less channels than config, please check");
USB_ASSERT_MSG((CONFIG_USB_DWC2_RX_FIFO_SIZE + CONFIG_USB_DWC2_NPTX_FIFO_SIZE + CONFIG_USB_DWC2_PTX_FIFO_SIZE) <= (USB_OTG_GLB->GHWCFG3 >> 16),
if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_utmi_width == 0) {
g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_utmi_width = 8;
}
if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.total_fifo_size == 0) {
g_dwc2_hcd[bus->hcd.hcd_id].user_params.total_fifo_size = g_dwc2_hcd[bus->hcd.hcd_id].hw_params.total_fifo_size;
}
for (uint8_t chidx = 0; chidx < g_dwc2_hcd[bus->hcd.hcd_id].hw_params.host_channels; chidx++) {
g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].waitsem = usb_osal_sem_create(0);
}
USB_LOG_INFO("dwc2 has %d channels and dfifo depth(32-bit words) is %d\r\n",
g_dwc2_hcd[bus->hcd.hcd_id].hw_params.host_channels,
g_dwc2_hcd[bus->hcd.hcd_id].user_params.total_fifo_size);
USB_ASSERT_MSG(g_dwc2_hcd[bus->hcd.hcd_id].hw_params.arch == GHWCFG2_INT_DMA_ARCH, "This dwc2 version does not support dma mode, so stop working");
USB_ASSERT_MSG((g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_rx_fifo_size +
g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_nperio_tx_fifo_size +
g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_perio_tx_fifo_size) <=
g_dwc2_hcd[bus->hcd.hcd_id].user_params.total_fifo_size,
"Your fifo config is overflow, please check");
g_dwc2_hcd[bus->hcd.hcd_id].GSNPSID = USB_OTG_GLB->GSNPSID;
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
/* This is vendor register */
USB_OTG_GLB->GCCFG = usbh_get_dwc2_gccfg_conf(bus->hcd.reg_base);
USB_OTG_GLB->GCCFG = g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_gccfg;
if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_type != DWC2_PHY_TYPE_PARAM_FS) {
USB_ASSERT_MSG(g_dwc2_hcd[bus->hcd.hcd_id].hw_params.hs_phy_type != 0, "This dwc2 version does not support hs, so stop working");
}
ret = dwc2_core_init(bus);
/* Force Host Mode*/
dwc2_set_mode(bus, USB_OTG_MODE_HOST);
usb_osal_msleep(50);
/* B-peripheral session valid override enable */
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOVAL;
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_TOCAL;
/* Restart the Phy Clock */
USB_OTG_PCGCCTL = 0U;
/* Set default Max speed support */
USB_OTG_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
USB_OTG_HOST->HCFG &= ~USB_OTG_HCFG_FSLSS;
USB_OTG_HOST->HCFG &= ~USB_OTG_HCFG_FSLSPCS;
if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
USB_OTG_HOST->HCFG |= USB_OTG_HCFG_FSLSPCLKSEL_48_MHZ;
} else {
USB_OTG_HOST->HCFG |= USB_OTG_HCFG_FSLSPCLKSEL_30_60_MHZ;
}
if (g_dwc2_hcd[bus->hcd.hcd_id].hw_params.snpsid > 0x4F54292AU) {
USB_OTG_HOST->HCFG |= USB_OTG_HFIR_RELOAD_CTRL;
}
/* Clear all pending HC Interrupts */
for (uint8_t i = 0U; i < CONFIG_USBHOST_PIPE_NUM; i++) {
for (uint8_t i = 0U; i < g_dwc2_hcd[bus->hcd.hcd_id].hw_params.host_channels; i++) {
USB_OTG_HC(i)->HCINT = 0xFFFFFFFFU;
USB_OTG_HC(i)->HCINTMSK = 0U;
}
@@ -603,9 +680,11 @@ int usb_hc_init(struct usbh_bus *bus)
USB_OTG_GLB->GINTSTS = 0xFFFFFFFFU;
/* set Rx FIFO size */
USB_OTG_GLB->GRXFSIZ = CONFIG_USB_DWC2_RX_FIFO_SIZE;
USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((CONFIG_USB_DWC2_NPTX_FIFO_SIZE << 16) & USB_OTG_NPTXFD) | CONFIG_USB_DWC2_RX_FIFO_SIZE);
USB_OTG_GLB->HPTXFSIZ = (uint32_t)(((CONFIG_USB_DWC2_PTX_FIFO_SIZE << 16) & USB_OTG_HPTXFSIZ_PTXFD) | (CONFIG_USB_DWC2_RX_FIFO_SIZE + CONFIG_USB_DWC2_NPTX_FIFO_SIZE));
USB_OTG_GLB->GRXFSIZ = g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_rx_fifo_size;
USB_OTG_GLB->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_nperio_tx_fifo_size << 16) & USB_OTG_NPTXFD) |
g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_rx_fifo_size);
USB_OTG_GLB->HPTXFSIZ = (uint32_t)(((g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_perio_tx_fifo_size << 16) & USB_OTG_HPTXFSIZ_PTXFD) |
(g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_rx_fifo_size + g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_nperio_tx_fifo_size));
ret = dwc2_flush_txfifo(bus, 0x10U);
ret = dwc2_flush_rxfifo(bus);
@@ -637,7 +716,7 @@ int usb_hc_deinit(struct usbh_bus *bus)
dwc2_flush_rxfifo(bus);
/* Flush out any leftover queued requests. */
for (uint32_t i = 0U; i <= 15U; i++) {
for (uint32_t i = 0U; i < g_dwc2_hcd[bus->hcd.hcd_id].hw_params.host_channels; i++) {
value = USB_OTG_HC(i)->HCCHAR;
value |= USB_OTG_HCCHAR_CHDIS;
value &= ~USB_OTG_HCCHAR_CHENA;
@@ -646,7 +725,7 @@ int usb_hc_deinit(struct usbh_bus *bus)
}
/* Halt all channels to put them into a known state. */
for (uint32_t i = 0U; i <= 15U; i++) {
for (uint32_t i = 0U; i < g_dwc2_hcd[bus->hcd.hcd_id].hw_params.host_channels; i++) {
value = USB_OTG_HC(i)->HCCHAR;
value |= USB_OTG_HCCHAR_CHDIS;
value |= USB_OTG_HCCHAR_CHENA;
@@ -670,7 +749,7 @@ int usb_hc_deinit(struct usbh_bus *bus)
dwc2_drivebus(bus, 0);
usb_osal_msleep(200);
for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
for (uint8_t chidx = 0; chidx < g_dwc2_hcd[bus->hcd.hcd_id].hw_params.host_channels; chidx++) {
usb_osal_sem_delete(g_dwc2_hcd[bus->hcd.hcd_id].chan_pool[chidx].waitsem);
}
@@ -858,18 +937,18 @@ int usbh_submit_urb(struct usbh_urb *urb)
if (urb->ep->bEndpointAddress & 0x80) {
/* Check if pipe rx fifo is overflow */
if (USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) > (CONFIG_USB_DWC2_RX_FIFO_SIZE * 4)) {
if (USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) > (g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_rx_fifo_size * 4)) {
return -USB_ERR_RANGE;
}
} else {
/* Check if intr and iso pipe tx fifo is overflow */
if (((USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS) ||
(USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT)) &&
USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) > (CONFIG_USB_DWC2_PTX_FIFO_SIZE * 4)) {
USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) > (g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_perio_tx_fifo_size * 4)) {
return -USB_ERR_RANGE;
} else {
/* Check if control and bulk pipe tx fifo is overflow */
if (USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) > (CONFIG_USB_DWC2_NPTX_FIFO_SIZE * 4)) {
if (USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize) > (g_dwc2_hcd[bus->hcd.hcd_id].user_params.host_nperio_tx_fifo_size * 4)) {
return -USB_ERR_RANGE;
}
}
@@ -1297,7 +1376,7 @@ static void dwc2_outchan_irq_handler(struct usbh_bus *bus, uint8_t ch_num)
static void dwc2_port_irq_handler(struct usbh_bus *bus)
{
__IO uint32_t hprt0, hprt0_dup;
__IO uint32_t hprt0, hprt0_dup, regval;
/* Handle Host Port Interrupts */
hprt0 = USB_OTG_HPRT;
@@ -1322,26 +1401,28 @@ static void dwc2_port_irq_handler(struct usbh_bus *bus)
g_dwc2_hcd[bus->hcd.hcd_id].port_pec = 1;
if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) {
#if defined(CONFIG_USB_HS)
#else
if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) {
USB_OTG_HOST->HFIR = 6000U;
if ((USB_OTG_HOST->HCFG & USB_OTG_HCFG_FSLSPCS) != USB_OTG_HCFG_FSLSPCS_1) {
uint32_t regval = USB_OTG_HOST->HCFG;
regval &= ~USB_OTG_HCFG_FSLSPCS;
regval |= USB_OTG_HCFG_FSLSPCS_1;
USB_OTG_HOST->HCFG = regval;
}
} else {
USB_OTG_HOST->HFIR = 48000U;
if ((USB_OTG_HOST->HCFG & USB_OTG_HCFG_FSLSPCS) != USB_OTG_HCFG_FSLSPCS_0) {
uint32_t regval = USB_OTG_HOST->HCFG;
regval &= ~USB_OTG_HCFG_FSLSPCS;
regval |= USB_OTG_HCFG_FSLSPCS_0;
USB_OTG_HOST->HCFG = regval;
regval = USB_OTG_HOST->HFIR;
regval &= ~USB_OTG_HFIR_FRIVL;
regval |= dwc2_calc_frame_interval(bus) & USB_OTG_HFIR_FRIVL;
USB_OTG_HOST->HFIR = regval;
if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) {
if ((USB_OTG_HOST->HCFG & USB_OTG_HCFG_FSLSPCS) != USB_OTG_HCFG_FSLSPCLKSEL_6_MHZ) {
regval = USB_OTG_HOST->HCFG;
regval &= ~USB_OTG_HCFG_FSLSPCS;
regval |= USB_OTG_HCFG_FSLSPCLKSEL_6_MHZ;
USB_OTG_HOST->HCFG = regval;
}
} else {
if ((USB_OTG_HOST->HCFG & USB_OTG_HCFG_FSLSPCS) != USB_OTG_HCFG_FSLSPCLKSEL_48_MHZ) {
regval = USB_OTG_HOST->HCFG;
regval &= ~USB_OTG_HCFG_FSLSPCS;
regval |= USB_OTG_HCFG_FSLSPCLKSEL_48_MHZ;
USB_OTG_HOST->HCFG = regval;
}
}
}
#endif
} else {
}
}
@@ -1380,7 +1461,7 @@ void USBH_IRQHandler(uint8_t busid)
}
if (gint_status & USB_OTG_GINTSTS_HCINT) {
chan_int = (USB_OTG_HOST->HAINT & USB_OTG_HOST->HAINTMSK) & 0xFFFFU;
for (uint8_t i = 0U; i < CONFIG_USBHOST_PIPE_NUM; i++) {
for (uint8_t i = 0U; i < g_dwc2_hcd[bus->hcd.hcd_id].hw_params.host_channels; i++) {
if ((chan_int & (1UL << (i & 0xFU))) != 0U) {
if ((USB_OTG_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR) {
dwc2_inchan_irq_handler(bus, i);

View File

@@ -336,10 +336,8 @@ static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_bus *bus, struct usb
}
qtd_setup = ehci_qtd_alloc(bus);
qtd_data = ehci_qtd_alloc(bus);
qtd_status = ehci_qtd_alloc(bus);
USB_ASSERT_MSG(qtd_setup && qtd_data && qtd_status, "ctrl qtd alloc failed");
USB_ASSERT_MSG(qtd_setup && qtd_status, "ctrl qtd alloc failed");
ehci_qh_fill(qh,
urb->hport->dev_addr,
@@ -363,6 +361,9 @@ static struct ehci_qh_hw *ehci_control_urb_init(struct usbh_bus *bus, struct usb
/* fill data qtd */
if (setup->wLength > 0) {
qtd_data = ehci_qtd_alloc(bus);
USB_ASSERT_MSG(qtd_data, "ctrl qtd alloc failed");
if ((setup->bmRequestType & 0x80) == 0x80) {
token = QTD_TOKEN_PID_IN;
} else {

View File

@@ -5,6 +5,10 @@
*/
#include "usbd_core.h"
#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_LOG)
#error "fsdev cannot enable USB_DBG_LOG"
#endif
#ifndef CONFIG_USBDEV_FSDEV_PMA_ACCESS
#error "please define CONFIG_USBDEV_FSDEV_PMA_ACCESS in usb_config.h"
#endif

View File

@@ -283,6 +283,13 @@ int usb_dc_init(uint8_t busid)
int usb_dc_deinit(uint8_t busid)
{
HWREGB(USB_BASE + MUSB_IE_OFFSET) = 0;
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = 0;
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) = 0;
HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~USB_POWER_SOFTCONN;
usb_dc_low_level_deinit();
return 0;
}
@@ -345,8 +352,10 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
g_musb_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_musb_udc.out_ep[ep_idx].ep_enable = true;
#ifndef CONFIG_USB_MUSB_SIFLI
USB_ASSERT_MSG((8 << HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET)) >= g_musb_udc.out_ep[ep_idx].ep_mps,
"Ep %02x fifo is overflow", ep->bEndpointAddress);
#endif
HWREGH(USB_BASE + MUSB_IND_RXMAP_OFFSET) = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
@@ -394,8 +403,10 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
g_musb_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_musb_udc.in_ep[ep_idx].ep_enable = true;
#ifndef CONFIG_USB_MUSB_SIFLI
USB_ASSERT_MSG((8 << HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET)) >= g_musb_udc.in_ep[ep_idx].ep_mps,
"Ep %02x fifo is overflow", ep->bEndpointAddress);
#endif
HWREGH(USB_BASE + MUSB_IND_TXMAP_OFFSET) = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);

162
port/musb/usb_glue_sifli.c Normal file
View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbh_core.h"
#include "usb_musb_reg.h"
#undef USB_POWER_SOFTCONN
#undef USB_DEVCTL_FSDEV
#undef USB_DEVCTL_LSDEV
#undef USB_DEVCTL_SESSION
#undef USB_POWER_HSENAB
#undef USB_POWER_HSMODE
#undef USB_POWER_RESET
#undef USB_POWER_RESUME
#ifndef CONFIG_USB_MUSB_SIFLI
#error must define CONFIG_USB_MUSB_SIFLI when use sunxi chips
#endif
#include "bf0_hal.h"
uint8_t usbd_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
{
*cfg = NULL; // No FIFO configuration for this implementation, readonly
return 0;
}
uint8_t usbh_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
{
*cfg = NULL; // No FIFO configuration for this implementation, readonly
return 0;
}
uint32_t usb_get_musb_ram_size(void)
{
return 0xFFFF; // No specific RAM size for this implementation
}
void usbd_musb_delay_ms(uint8_t ms)
{
/* implement later */
}
#ifdef PKG_CHERRYUSB_DEVICE
void usb_dc_low_level_init(uint8_t busid)
{
HAL_RCC_EnableModule(RCC_MOD_USBC);
#ifdef SOC_SF32LB58X
//hwp_usbc->utmicfg12 = hwp_usbc->utmicfg12 | 0x3; //set xo_clk_sel
hwp_usbc->ldo25 = hwp_usbc->ldo25 | 0xa; //set psw_en and ldo25_en
HAL_Delay(1);
hwp_usbc->swcntl3 = 0x1; //set utmi_en for USB2.0
hwp_usbc->usbcfg = hwp_usbc->usbcfg | 0x40; //enable usb PLL.
#elif defined(SOC_SF32LB56X) || defined(SOC_SF32LB52X)
hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN;
#elif defined(SOC_SF32LB55X)
hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN;
#endif
#ifndef SOC_SF32LB55X
hwp_usbc->usbcfg |= (USB_USBCFG_AVALID | USB_USBCFG_AVALID_DR);
hwp_usbc->dpbrxdisl = 0xFE;
hwp_usbc->dpbtxdisl = 0xFE;
#endif
NVIC_EnableIRQ(USBC_IRQn);
__HAL_SYSCFG_Enable_USB();
}
void usb_dc_low_level_deinit(uint8_t busid)
{
NVIC_DisableIRQ(USBC_IRQn);
#ifdef SOC_SF32LB58X
hwp_usbc->usbcfg &= ~0x40; // Disable usb PLL.
hwp_usbc->swcntl3 = 0x0;
hwp_usbc->ldo25 &= ~0xa; // Disable psw_en and ldo25_en
#elif defined(SOC_SF32LB56X) || defined(SOC_SF32LB52X)
hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN);
#elif defined(SOC_SF32LB55X)
hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN);
#endif
/* reset USB to make DP change to PULLDOWN state */
hwp_hpsys_rcc->RSTR2 |= HPSYS_RCC_RSTR2_USBC;
HAL_Delay_us(100);
hwp_hpsys_rcc->RSTR2 &= ~HPSYS_RCC_RSTR2_USBC;
HAL_RCC_DisableModule(RCC_MOD_USBC);
}
#endif
#ifdef PKG_CHERRYUSB_HOST
void usb_hc_low_level_init(struct usbh_bus *bus)
{
HAL_RCC_EnableModule(RCC_MOD_USBC);
#ifdef SOC_SF32LB58X
//hwp_usbc->utmicfg12 = hwp_usbc->utmicfg12 | 0x3; //set xo_clk_sel
hwp_usbc->ldo25 = hwp_usbc->ldo25 | 0xa; //set psw_en and ldo25_en
HAL_Delay(1);
hwp_usbc->swcntl3 = 0x1; //set utmi_en for USB2.0
hwp_usbc->usbcfg = hwp_usbc->usbcfg | 0x40; //enable usb PLL.
#elif defined(SOC_SF32LB56X) || defined(SOC_SF32LB52X)
hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN;
#elif defined(SOC_SF32LB55X)
hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN;
#endif
#ifndef SOC_SF32LB55X
hwp_usbc->usbcfg |= (USB_USBCFG_AVALID | USB_USBCFG_AVALID_DR);
hwp_usbc->dpbrxdisl = 0xFE;
hwp_usbc->dpbtxdisl = 0xFE;
#endif
__HAL_SYSCFG_Enable_USB();
hwp_usbc->usbcfg &= 0xEF;
hwp_usbc->dbgl = 0x80;
NVIC_EnableIRQ(USBC_IRQn);
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
NVIC_DisableIRQ(USBC_IRQn);
#ifdef SOC_SF32LB58X
hwp_usbc->usbcfg &= ~0x40; // Disable usb PLL.
hwp_usbc->swcntl3 = 0x0;
hwp_usbc->ldo25 &= ~0xa; // Disable psw_en and ldo25_en
#elif defined(SOC_SF32LB56X) || defined(SOC_SF32LB52X)
hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN);
#elif defined(SOC_SF32LB55X)
hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN);
#endif
/* reset USB to make DP change to PULLDOWN state */
hwp_hpsys_rcc->RSTR2 |= HPSYS_RCC_RSTR2_USBC;
HAL_Delay_us(100);
hwp_hpsys_rcc->RSTR2 &= ~HPSYS_RCC_RSTR2_USBC;
HAL_RCC_DisableModule(RCC_MOD_USBC);
}
void musb_reset_prev(void)
{
#if defined(SF32LB58X)
hwp_usbc->rsvd0 = 0xc; //58
#endif
}
void musb_reset_post(void)
{
#if defined(SF32LB58X)
hwp_usbc->rsvd0 = 0x0; //58
#endif
}
#endif
void USBC_IRQHandler(void)
{
#ifdef PKG_CHERRYUSB_DEVICE
USBD_IRQHandler(0);
#endif
#ifdef PKG_CHERRYUSB_HOST
USBH_IRQHandler(0);
#endif
}

View File

@@ -429,9 +429,18 @@ static int usbh_reset_port(struct usbh_bus *bus, const uint8_t port)
{
g_musb_hcd[bus->hcd.hcd_id].port_pe = 0;
HWREGB(USB_BASE + MUSB_POWER_OFFSET) |= USB_POWER_RESET;
#ifdef CONFIG_USB_MUSB_SIFLI
extern void musb_reset_prev(void);
musb_reset_prev();
#endif
usb_osal_msleep(20);
HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~(USB_POWER_RESET);
usb_osal_msleep(20);
#ifdef CONFIG_USB_MUSB_SIFLI
extern void musb_reset_post(void);
musb_reset_post();
#endif
g_musb_hcd[bus->hcd.hcd_id].port_pe = 1;
return 0;
}