summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2024-04-09 20:26:26 +0700
committerhathach <[email protected]>2024-04-09 22:04:43 +0700
commit2bce68a065aa873ffd738b5a90639b3b4b18d2c2 (patch)
treec1a2bfc42a3be56b4751969681005665dfaf90ad /src
parent75cf8e21a7e525eb24b7fd34fe5859cba331fcc2 (diff)
parent68a08e33d2a1a3b02a28c616bc825eb674700833 (diff)
Merge branch 'master' into dwc2-interrupts
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt87
-rw-r--r--src/class/audio/audio.h25
-rw-r--r--src/class/audio/audio_device.c680
-rw-r--r--src/class/audio/audio_device.h35
-rwxr-xr-xsrc/class/bth/bth_device.c13
-rwxr-xr-xsrc/class/bth/bth_device.h8
-rw-r--r--src/class/cdc/cdc.h34
-rw-r--r--src/class/cdc/cdc_device.c53
-rw-r--r--src/class/cdc/cdc_device.h1
-rw-r--r--src/class/cdc/cdc_host.c1459
-rw-r--r--src/class/cdc/cdc_host.h24
-rw-r--r--src/class/cdc/serial/ch34x.h84
-rw-r--r--src/class/cdc/serial/cp210x.h2
-rw-r--r--src/class/cdc/serial/ftdi_sio.h5
-rw-r--r--src/class/dfu/dfu_device.c20
-rw-r--r--src/class/dfu/dfu_device.h1
-rw-r--r--src/class/dfu/dfu_rt_device.c20
-rw-r--r--src/class/dfu/dfu_rt_device.h1
-rw-r--r--src/class/hid/hid.h13
-rw-r--r--src/class/hid/hid_device.c22
-rw-r--r--src/class/hid/hid_device.h60
-rw-r--r--src/class/hid/hid_host.c574
-rw-r--r--src/class/hid/hid_host.h33
-rw-r--r--src/class/midi/midi_device.c38
-rw-r--r--src/class/midi/midi_device.h1
-rw-r--r--src/class/msc/msc.h10
-rw-r--r--src/class/msc/msc_device.c57
-rw-r--r--src/class/msc/msc_device.h1
-rw-r--r--src/class/msc/msc_host.c306
-rw-r--r--src/class/msc/msc_host.h11
-rw-r--r--src/class/net/ecm_rndis_device.c19
-rw-r--r--src/class/net/ncm_device.c21
-rw-r--r--src/class/net/net_device.h1
-rw-r--r--src/class/usbtmc/usbtmc_device.c9
-rw-r--r--src/class/usbtmc/usbtmc_device.h3
-rw-r--r--src/class/vendor/vendor_device.c48
-rw-r--r--src/class/vendor/vendor_device.h1
-rw-r--r--src/class/video/video.h265
-rw-r--r--src/class/video/video_device.c462
-rw-r--r--src/class/video/video_device.h1
-rw-r--r--src/common/tusb_common.h47
-rw-r--r--src/common/tusb_compiler.h10
-rw-r--r--src/common/tusb_debug.h43
-rw-r--r--src/common/tusb_fifo.c3
-rw-r--r--src/common/tusb_fifo.h31
-rw-r--r--src/common/tusb_mcu.h108
-rw-r--r--src/common/tusb_private.h36
-rw-r--r--src/common/tusb_types.h167
-rw-r--r--src/common/tusb_verify.h56
-rw-r--r--src/device/dcd.h52
-rw-r--r--src/device/usbd.c953
-rw-r--r--src/device/usbd.h41
-rw-r--r--src/device/usbd_control.c133
-rw-r--r--src/device/usbd_pvt.h22
-rw-r--r--src/host/hcd.h58
-rw-r--r--src/host/hub.c66
-rw-r--r--src/host/hub.h13
-rw-r--r--src/host/usbh.c1467
-rw-r--r--src/host/usbh.h85
-rw-r--r--src/host/usbh_pvt.h (renamed from src/host/usbh_classdriver.h)27
-rw-r--r--src/osal/osal.h3
-rw-r--r--src/osal/osal_freertos.h120
-rw-r--r--src/osal/osal_mynewt.h61
-rw-r--r--src/osal/osal_none.h82
-rw-r--r--src/osal/osal_pico.h105
-rw-r--r--src/osal/osal_rtthread.h64
-rw-r--r--src/osal/osal_rtx4.h61
-rw-r--r--src/portable/analog/max3421/hcd_max3421.c1010
-rw-r--r--src/portable/bridgetek/ft9xx/dcd_ft9xx.c2
-rw-r--r--src/portable/chipidea/ci_fs/ci_fs_kinetis.h49
-rw-r--r--src/portable/chipidea/ci_fs/ci_fs_mcx.h (renamed from src/common/tusb_timeout.h)64
-rw-r--r--src/portable/chipidea/ci_fs/ci_fs_type.h118
-rw-r--r--src/portable/chipidea/ci_fs/dcd_ci_fs.c567
-rw-r--r--src/portable/chipidea/ci_hs/ci_hs_imxrt.h44
-rw-r--r--src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h15
-rw-r--r--src/portable/chipidea/ci_hs/ci_hs_mcx.h52
-rw-r--r--src/portable/chipidea/ci_hs/ci_hs_type.h14
-rw-r--r--src/portable/chipidea/ci_hs/dcd_ci_hs.c118
-rw-r--r--src/portable/chipidea/ci_hs/hcd_ci_hs.c47
-rw-r--r--src/portable/dialog/da146xx/dcd_da146xx.c2
-rw-r--r--src/portable/ehci/ehci.c955
-rw-r--r--src/portable/ehci/ehci.h177
-rw-r--r--src/portable/espressif/esp32sx/dcd_esp32sx.c12
-rw-r--r--src/portable/mentor/musb/dcd_musb.c34
-rw-r--r--src/portable/mentor/musb/hcd_musb.c24
-rw-r--r--src/portable/microchip/pic/dcd_pic.c2
-rw-r--r--src/portable/microchip/samx7x/dcd_samx7x.c2
-rw-r--r--src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c2
-rw-r--r--src/portable/nordic/nrf5x/dcd_nrf5x.c33
-rw-r--r--src/portable/nxp/khci/dcd_khci.c14
-rw-r--r--src/portable/nxp/khci/hcd_khci.c35
-rw-r--r--src/portable/nxp/lpc17_40/dcd_lpc17_40.c2
-rw-r--r--src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c270
-rw-r--r--src/portable/nxp/transdimension/common_transdimension.h136
-rw-r--r--src/portable/nxp/transdimension/dcd_transdimension.c672
-rw-r--r--src/portable/nxp/transdimension/hcd_transdimension.c119
-rw-r--r--src/portable/ohci/ohci.c57
-rw-r--r--src/portable/ohci/ohci.h24
-rw-r--r--src/portable/raspberrypi/pio_usb/hcd_pio_usb.c98
-rw-r--r--src/portable/raspberrypi/rp2040/dcd_rp2040.c358
-rw-r--r--src/portable/raspberrypi/rp2040/hcd_rp2040.c42
-rw-r--r--src/portable/raspberrypi/rp2040/rp2040_usb.c174
-rw-r--r--src/portable/renesas/rusb2/dcd_rusb2.c783
-rw-r--r--src/portable/renesas/rusb2/hcd_rusb2.c566
-rw-r--r--src/portable/renesas/rusb2/rusb2_common.c61
-rw-r--r--src/portable/renesas/rusb2/rusb2_ra.h71
-rw-r--r--src/portable/renesas/rusb2/rusb2_rx.h20
-rw-r--r--src/portable/renesas/rusb2/rusb2_type.h483
-rw-r--r--src/portable/sony/cxd56/dcd_cxd56.c30
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c329
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h (renamed from src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h)397
-rw-r--r--src/portable/st/synopsys/dcd_synopsys.c1240
-rw-r--r--src/portable/st/synopsys/synopsys_common.h1465
-rw-r--r--src/portable/st/typec/typec_stm32.c372
-rw-r--r--src/portable/sunxi/dcd_sunxi_musb.c32
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c926
-rw-r--r--src/portable/synopsys/dwc2/dwc2_info.md55
-rw-r--r--src/portable/synopsys/dwc2/dwc2_info.py169
-rw-r--r--src/portable/synopsys/dwc2/dwc2_stm32.h135
-rw-r--r--src/portable/synopsys/dwc2/dwc2_type.h1791
-rw-r--r--src/portable/synopsys/dwc2/hwcfg_list.md777
-rw-r--r--src/portable/template/dcd_template.c4
-rw-r--r--src/portable/template/hcd_template.c163
-rw-r--r--src/portable/wch/ch32_usbhs_reg.h (renamed from src/portable/wch/ch32v307/ch32_usbhs_reg.h)4
-rw-r--r--src/portable/wch/dcd_ch32_usbhs.c (renamed from src/portable/wch/ch32v307/dcd_usbhs.c)6
-rw-r--r--src/tinyusb.mk26
-rw-r--r--src/tusb.c310
-rw-r--r--src/tusb.h14
-rw-r--r--src/tusb_option.h164
-rw-r--r--src/typec/pd_types.h237
-rw-r--r--src/typec/tcd.h143
-rw-r--r--src/typec/usbc.c219
-rw-r--r--src/typec/usbc.h91
133 files changed, 13046 insertions, 11803 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a270ea8b7..076e1e1eb 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,12 +1,16 @@
-# TODO make tinyusb as library that depends on 'tusb_config' interface that exposes the tusb_config.h file
-# This file is WIP and should not used yet
+# TODO more docs and example on how to use this file
+# Usage: requires target tinyusb_config which expose tusb_config.h file
+# TINYUSB_TARGET_PREFIX and TINYUSB_TARGET_SUFFIX can be used to change the name of the target
cmake_minimum_required(VERSION 3.17)
+# Add tinyusb to a target, if user don't want to compile tinyusb as a library
function(add_tinyusb TARGET)
- target_sources(${TARGET} PUBLIC
+ target_sources(${TARGET} PRIVATE
+ # common
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tusb.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/common/tusb_fifo.c
+ # device
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/device/usbd_control.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/audio/audio_device.c
@@ -21,15 +25,82 @@ function(add_tinyusb TARGET)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/usbtmc/usbtmc_device.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_device.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/video/video_device.c
+ # host
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/host/usbh.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/host/hub.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/cdc/cdc_host.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_host.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_host.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_host.c
+ # typec
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/typec/usbc.c
)
-
target_include_directories(${TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+ # TODO for net driver, should be removed/changed
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../lib/networking
)
- # enable all possible warnings
- target_compile_options(${TARGET} PUBLIC
-
- )
+ if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ target_compile_options(${TARGET} PRIVATE
+ -Wall
+ -Wextra
+ -Werror
+ -Wfatal-errors
+ -Wdouble-promotion
+ -Wstrict-prototypes
+ -Wstrict-overflow
+ -Werror-implicit-function-declaration
+ -Wfloat-equal
+ -Wundef
+ -Wshadow
+ -Wwrite-strings
+ -Wsign-compare
+ -Wmissing-format-attribute
+ -Wunreachable-code
+ -Wcast-align
+ -Wcast-function-type
+ -Wcast-qual
+ -Wnull-dereference
+ -Wuninitialized
+ -Wunused
+ -Wunused-function
+ -Wreturn-type
+ -Wredundant-decls
+ )
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
+ endif ()
endfunction()
+
+#------------------------------------
+# TinyUSB as library target
+#------------------------------------
+if (NOT DEFINED TINYUSB_TARGET)
+ set(TINYUSB_TARGET "tinyusb")
+endif ()
+
+set(TINYUSB_CONFIG_TARGET "${TINYUSB_TARGET}_config")
+
+if (DEFINED TINYUSB_TARGET_PREFIX)
+ set(TINYUSB_TARGET "${TINYUSB_TARGET_PREFIX}${TINYUSB_TARGET}")
+ set(TINYUSB_CONFIG_TARGET "${TINYUSB_TARGET_PREFIX}${TINYUSB_CONFIG_TARGET}")
+endif ()
+
+if (DEFINED TINYUSB_TARGET_SUFFIX)
+ set(TINYUSB_TARGET "${TINYUSB_TARGET}${TINYUSB_TARGET_SUFFIX}")
+ set(TINYUSB_CONFIG_TARGET "${TINYUSB_CONFIG_TARGET}${TINYUSB_TARGET_SUFFIX}")
+endif ()
+
+add_library(${TINYUSB_TARGET} STATIC)
+add_tinyusb(${TINYUSB_TARGET})
+
+# Check if tinyusb_config target is defined
+if (NOT TARGET ${TINYUSB_CONFIG_TARGET})
+ message(FATAL_ERROR "${TINYUSB_CONFIG_TARGET} target is not defined")
+endif()
+
+# Link with tinyusb_config target
+target_link_libraries(${TINYUSB_TARGET} PUBLIC
+ ${TINYUSB_CONFIG_TARGET}
+ )
diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h
index 70d431282..d6f3e22e2 100644
--- a/src/class/audio/audio.h
+++ b/src/class/audio/audio.h
@@ -924,6 +924,31 @@ typedef struct TU_ATTR_PACKED {
} subrange[numSubRanges]; \
}
+// 6.1 Interrupt Data Message Format
+typedef struct TU_ATTR_PACKED
+{
+ uint8_t bInfo;
+ uint8_t bAttribute;
+ union
+ {
+ uint16_t wValue;
+ struct
+ {
+ uint8_t wValue_cn_or_mcn;
+ uint8_t wValue_cs;
+ };
+ };
+ union
+ {
+ uint16_t wIndex;
+ struct
+ {
+ uint8_t wIndex_ep_or_int;
+ uint8_t wIndex_entity_id;
+ };
+ };
+} audio_interrupt_data_t;
+
/** @} */
#ifdef __cplusplus
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c
index f487fe60e..9050b462a 100644
--- a/src/class/audio/audio_device.c
+++ b/src/class/audio/audio_device.c
@@ -66,7 +66,7 @@
// Use ring buffer if it's available, some MCUs need extra RAM requirements
#ifndef TUD_AUDIO_PREFER_RING_BUFFER
- #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT
+ #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX
#define TUD_AUDIO_PREFER_RING_BUFFER 0
#else
#define TUD_AUDIO_PREFER_RING_BUFFER 1
@@ -85,7 +85,7 @@
CFG_TUSB_MCU == OPT_MCU_RX72N || \
CFG_TUSB_MCU == OPT_MCU_LPC18XX || \
CFG_TUSB_MCU == OPT_MCU_LPC43XX || \
- CFG_TUSB_MCU == OPT_MCU_MIMXRT || \
+ CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX || \
CFG_TUSB_MCU == OPT_MCU_MSP432E4
#if TUD_AUDIO_PREFER_RING_BUFFER
#define USE_LINEAR_BUFFER 0
@@ -96,13 +96,6 @@
#define USE_LINEAR_BUFFER 1
#endif
-// Temporarily put the check here for stm32_fsdev
-#ifdef TUP_USBIP_FSDEV
- #define USE_ISO_EP_ALLOCATION 1
-#else
- #define USE_ISO_EP_ALLOCATION 0
-#endif
-
// Declaration of buffers
// Check for maximum supported numbers
@@ -110,24 +103,36 @@
#error Maximum number of audio functions restricted to three!
#endif
+// Put sw_buf in USB section only if necessary
+#if USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING
+#define IN_SW_BUF_MEM_SECTION
+#else
+#define IN_SW_BUF_MEM_SECTION CFG_TUD_MEM_SECTION
+#endif
+#if USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING
+#define OUT_SW_BUF_MEM_SECTION
+#else
+#define OUT_SW_BUF_MEM_SECTION CFG_TUD_MEM_SECTION
+#endif
+
// EP IN software buffers and mutexes
#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ];
+ IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO
#endif
#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ];
+ IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO
#endif
#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ];
+ IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO
#endif
@@ -139,36 +144,36 @@
// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into
#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING)
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX];
+ CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX];
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX];
+ CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX];
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX];
+ CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX];
#endif
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING)
// EP OUT software buffers and mutexes
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ];
+ OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO
#endif
#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ];
+ OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO
#endif
#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ];
+ OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO
#endif
@@ -180,27 +185,27 @@
// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING)
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX];
+ CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX];
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX];
+ CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX];
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX];
+ CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX];
#endif
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING)
// Control buffers
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ];
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ];
#if CFG_TUD_AUDIO > 1
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ];
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ];
#endif
#if CFG_TUD_AUDIO > 2
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ];
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ];
#endif
// Active alternate setting of interfaces
@@ -217,7 +222,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
// Software encoding/decoding support FIFOs
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ];
+ CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ];
tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
@@ -225,7 +230,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ];
+ CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ];
tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
@@ -233,7 +238,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ];
+ CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ];
tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
@@ -243,7 +248,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ];
+ CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ];
tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
@@ -251,7 +256,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ];
+ CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ];
tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
@@ -259,7 +264,7 @@ uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0
- CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ];
+ CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ];
tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
@@ -289,10 +294,12 @@ typedef struct
#endif
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
- uint8_t ep_int_ctr; // Audio control interrupt EP.
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+ uint8_t ep_int; // Audio control interrupt EP.
#endif
+ bool mounted; // Device opened
+
/*------------- From this point, data is not cleared by bus reset -------------*/
uint16_t desc_length; // Length of audio function descriptor
@@ -346,8 +353,8 @@ typedef struct
#endif
// Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74)
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
- CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE];
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+ CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6];
#endif
// Decoding parameters - parameters are set when alternate AS interface is set by host
@@ -364,14 +371,21 @@ typedef struct
#endif
#endif
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+ uint32_t sample_rate_tx;
+ uint16_t packet_sz_tx[3];
+ uint8_t bclock_id_tx;
+ uint8_t interval_tx;
+#endif
+
// Encoding parameters - parameters are set when alternate AS interface is set by host
-#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL)
audio_format_type_t format_type_tx;
uint8_t n_channels_tx;
+ uint8_t n_bytes_per_sampe_tx;
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
audio_data_format_type_I_t format_type_I_tx;
- uint8_t n_bytes_per_sampe_tx;
uint8_t n_channels_per_ff_tx;
uint8_t n_ff_used_tx;
#endif
@@ -416,7 +430,7 @@ typedef struct
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO];
+CFG_TUD_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO];
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received);
@@ -444,7 +458,7 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id);
static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id);
static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio);
-#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING
+#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING)
static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf);
static inline uint8_t tu_desc_subtype(void const* desc)
@@ -453,6 +467,11 @@ static inline uint8_t tu_desc_subtype(void const* desc)
}
#endif
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+static bool audiod_calc_tx_packet_sz(audiod_function_t* audio);
+static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_size);
+#endif
+
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq);
#endif
@@ -462,23 +481,7 @@ bool tud_audio_n_mounted(uint8_t func_id)
TU_VERIFY(func_id < CFG_TUD_AUDIO);
audiod_function_t* audio = &_audiod_fct[func_id];
-#if CFG_TUD_AUDIO_ENABLE_EP_OUT
- if (audio->ep_out == 0) return false;
-#endif
-
-#if CFG_TUD_AUDIO_ENABLE_EP_IN
- if (audio->ep_in == 0) return false;
-#endif
-
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
- if (audio->ep_int_ctr == 0) return false;
-#endif
-
-#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- if (audio->ep_fb == 0) return false;
-#endif
-
- return true;
+ return audio->mounted;
}
//--------------------------------------------------------------------+
@@ -631,73 +634,55 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t
// Decoding according to 2.3.1.5 Audio Streams
// Helper function
-static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used)
+static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesPerSample, void * dst, const void * dst_end, void * src, uint8_t const n_ff_used)
{
+ // Due to one FIFO contains 2 channels, data always aligned to (nBytesPerSample * 2)
+ uint16_t * dst16 = dst;
+ uint16_t * src16 = src;
+ const uint16_t * dst_end16 = dst_end;
+ uint32_t * dst32 = dst;
+ uint32_t * src32 = src;
+ const uint32_t * dst_end32 = dst_end;
- // This function is an optimized version of
- // while((uint8_t *)dst < dst_end)
- // {
- // memcpy(dst, src, nBytesToCopy);
- // dst = (uint8_t *)dst + nBytesToCopy;
- // src += nBytesToCopy * n_ff_used;
- // }
-
- // Optimize for fast half word copies
- typedef struct{
- uint16_t val;
- } __attribute((__packed__)) unaligned_uint16_t;
-
- // Optimize for fast word copies
- typedef struct{
- uint32_t val;
- } __attribute((__packed__)) unaligned_uint32_t;
-
- switch (nBytesToCopy)
+ if (nBytesPerSample == 1)
{
- case 1:
- while((uint8_t *)dst < dst_end)
- {
- *(uint8_t *)dst++ = *src;
- src += n_ff_used;
- }
- break;
-
- case 2:
- while((uint8_t *)dst < dst_end)
- {
- *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src;
- dst += 2;
- src += 2 * n_ff_used;
- }
- break;
-
- case 3:
- while((uint8_t *)dst < dst_end)
- {
- // memcpy(dst, src, 3);
- // dst = (uint8_t *)dst + 3;
- // src += 3 * n_ff_used;
-
- // TODO: Is there a faster way to copy 3 bytes?
- *(uint8_t *)dst++ = *src++;
- *(uint8_t *)dst++ = *src++;
- *(uint8_t *)dst++ = *src++;
-
- src += 3 * (n_ff_used - 1);
- }
- break;
-
- case 4:
- while((uint8_t *)dst < dst_end)
- {
- *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src;
- dst += 4;
- src += 4 * n_ff_used;
- }
- break;
+ while(dst16 < dst_end16)
+ {
+ *dst16++ = *src16++;
+ src16 += n_ff_used - 1;
+ }
+ return src16;
+ }
+ else if (nBytesPerSample == 2)
+ {
+ while(dst32 < dst_end32)
+ {
+ *dst32++ = *src32++;
+ src32 += n_ff_used - 1;
+ }
+ return src32;
+ }
+ else if (nBytesPerSample == 3)
+ {
+ while(dst16 < dst_end16)
+ {
+ *dst16++ = *src16++;
+ *dst16++ = *src16++;
+ *dst16++ = *src16++;
+ src16 += 3 * (n_ff_used - 1);
+ }
+ return src16;
+ }
+ else // nBytesPerSample == 4
+ {
+ while(dst32 < dst_end32)
+ {
+ *dst32++ = *src32++;
+ *dst32++ = *src32++;
+ src32 += 2 * (n_ff_used - 1);
+ }
+ return src32;
}
-
- return src;
}
static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received)
@@ -819,27 +804,32 @@ tu_fifo_t* tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx)
#endif
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
-
-// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_ctr_done_cb() is called in inform user
-uint16_t tud_audio_int_ctr_n_write(uint8_t func_id, uint8_t const* buffer, uint16_t len)
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+// If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_done_cb() is called in inform user
+bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t * data)
{
TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL);
- // We write directly into the EP's buffer - abort if previous transfer not complete
- TU_VERIFY(!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr));
+ TU_VERIFY(_audiod_fct[func_id].ep_int != 0);
- TU_VERIFY(tu_memcpy_s(_audiod_fct[func_id].ep_int_ctr_buf, CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE, buffer, len)==0);
+ // We write directly into the EP's buffer - abort if previous transfer not complete
+ TU_VERIFY(usbd_edpt_claim(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int));
- // Schedule transmit
- TU_VERIFY(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int_ctr, _audiod_fct[func_id].ep_int_ctr_buf, len));
+ // Check length
+ if (tu_memcpy_s(_audiod_fct[func_id].ep_int_buf, sizeof(_audiod_fct[func_id].ep_int_buf), data, sizeof(audio_interrupt_data_t)) == 0)
+ {
+ // Schedule transmit
+ TU_ASSERT(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int, _audiod_fct[func_id].ep_int_buf, sizeof(_audiod_fct[func_id].ep_int_buf)), 0);
+ } else
+ {
+ // Release endpoint since we don't make any transfer
+ usbd_edpt_release(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int);
+ }
return true;
}
-
#endif
-
// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission.
// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write.
@@ -904,9 +894,12 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio)
#else
// No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule
-
+#if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+ // packet_sz_tx is based on total packet size, here we want size for each support buffer.
+ n_bytes_tx = audiod_tx_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, audio->ep_in_sz);
+#else
n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz); // Limit up to max packet size, more can not be done for ISO
-
+#endif
#if USE_LINEAR_BUFFER_TX
tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx);
TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx));
@@ -944,64 +937,55 @@ range [-1, +1)
* */
// Helper function
-static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used)
+static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesPerSample, void * src, const void * src_end, void * dst, uint8_t const n_ff_used)
{
- // Optimize for fast half word copies
- typedef struct{
- uint16_t val;
- } __attribute((__packed__)) unaligned_uint16_t;
-
- // Optimize for fast word copies
- typedef struct{
- uint32_t val;
- } __attribute((__packed__)) unaligned_uint32_t;
+ // Due to one FIFO contains 2 channels, data always aligned to (nBytesPerSample * 2)
+ uint16_t * dst16 = dst;
+ uint16_t * src16 = src;
+ const uint16_t * src_end16 = src_end;
+ uint32_t * dst32 = dst;
+ uint32_t * src32 = src;
+ const uint32_t * src_end32 = src_end;
- switch (nBytesToCopy)
+ if (nBytesPerSample == 1)
{
- case 1:
- while(src < src_end)
- {
- *dst = *src++;
- dst += n_ff_used;
- }
- break;
-
- case 2:
- while(src < src_end)
- {
- *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src;
- src += 2;
- dst += 2 * n_ff_used;
- }
- break;
-
- case 3:
- while(src < src_end)
- {
- // memcpy(dst, src, 3);
- // src = (uint8_t *)src + 3;
- // dst += 3 * n_ff_used;
-
- // TODO: Is there a faster way to copy 3 bytes?
- *dst++ = *src++;
- *dst++ = *src++;
- *dst++ = *src++;
-
- dst += 3 * (n_ff_used - 1);
- }
- break;
-
- case 4:
- while(src < src_end)
- {
- *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src;
- src += 4;
- dst += 4 * n_ff_used;
- }
- break;
+ while(src16 < src_end16)
+ {
+ *dst16++ = *src16++;
+ dst16 += n_ff_used - 1;
+ }
+ return dst16;
+ }
+ else if (nBytesPerSample == 2)
+ {
+ while(src32 < src_end32)
+ {
+ *dst32++ = *src32++;
+ dst32 += n_ff_used - 1;
+ }
+ return dst32;
+ }
+ else if (nBytesPerSample == 3)
+ {
+ while(src16 < src_end16)
+ {
+ *dst16++ = *src16++;
+ *dst16++ = *src16++;
+ *dst16++ = *src16++;
+ dst16 += 3 * (n_ff_used - 1);
+ }
+ return dst16;
+ }
+ else // nBytesPerSample == 4
+ {
+ while(src32 < src_end32)
+ {
+ *dst32++ = *src32++;
+ *dst32++ = *src32++;
+ dst32 += 2 * (n_ff_used - 1);
+ }
+ return dst32;
}
-
- return dst;
}
static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio)
@@ -1014,8 +998,6 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
// Determine amount of samples
uint8_t const n_ff_used = audio->n_ff_used_tx;
- uint16_t const nBytesToCopy = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx;
- uint16_t const capPerFF = audio->ep_in_sz / n_ff_used; // Sample capacity per FIFO in bytes
uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]);
uint8_t cnt_ff;
@@ -1028,14 +1010,23 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
}
}
- // Check if there is enough
+#if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+ const uint16_t norm_packet_sz_tx[3] = {audio->packet_sz_tx[0] / n_ff_used,
+ audio->packet_sz_tx[1] / n_ff_used,
+ audio->packet_sz_tx[2] / n_ff_used};
+ // packet_sz_tx is based on total packet size, here we want size for each support buffer.
+ nBytesPerFFToSend = audiod_tx_packet_size(norm_packet_sz_tx, nBytesPerFFToSend, audio->tx_supp_ff[0].depth, audio->ep_in_sz / n_ff_used);
+ // Check if there is enough data
+ if (nBytesPerFFToSend == 0) return 0;
+#else
+ // Check if there is enough data
if (nBytesPerFFToSend == 0) return 0;
-
// Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT!
- nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, capPerFF);
-
+ nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, audio->ep_in_sz / n_ff_used);
// Round to full number of samples (flooring)
- nBytesPerFFToSend = (nBytesPerFFToSend / nBytesToCopy) * nBytesToCopy;
+ uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx;
+ nBytesPerFFToSend = (nBytesPerFFToSend / nSlotSize) * nSlotSize;
+#endif
// Encode
uint8_t * dst;
@@ -1298,7 +1289,7 @@ void audiod_init(void)
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
// Set encoding parameters for Type_I formats
-#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
switch (i)
{
#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0
@@ -1398,6 +1389,10 @@ void audiod_init(void)
}
}
+bool audiod_deinit(void) {
+ return false; // TODO not implemented yet
+}
+
void audiod_reset(uint8_t rhport)
{
(void) rhport;
@@ -1441,10 +1436,11 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
// Verify version is correct - this check can be omitted
TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2);
- // Verify interrupt control EP is enabled if demanded by descriptor - this should be best some static check however - this check can be omitted
- if (itf_desc->bNumEndpoints == 1) // 0 or 1 EPs are allowed
+ // Verify interrupt control EP is enabled if demanded by descriptor
+ TU_ASSERT(itf_desc->bNumEndpoints <= 1); // 0 or 1 EPs are allowed
+ if (itf_desc->bNumEndpoints == 1)
{
- TU_VERIFY(CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN > 0);
+ TU_ASSERT(CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP);
}
// Alternate setting MUST be zero - this check can be omitted
@@ -1477,83 +1473,143 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
#endif
}
-#if USE_ISO_EP_ALLOCATION
+#ifdef TUP_DCD_EDPT_ISO_ALLOC
+ {
#if CFG_TUD_AUDIO_ENABLE_EP_IN
- uint8_t ep_in = 0;
- uint16_t ep_in_size = 0;
+ uint8_t ep_in = 0;
+ uint16_t ep_in_size = 0;
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
- uint8_t ep_out = 0;
- uint16_t ep_out_size = 0;
+ uint8_t ep_out = 0;
+ uint16_t ep_out_size = 0;
#endif
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- uint8_t ep_fb = 0;
+ uint8_t ep_fb = 0;
#endif
-
- uint8_t const *p_desc = _audiod_fct[i].p_desc;
- uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
- while (p_desc < p_desc_end)
- {
- if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
+ uint8_t const *p_desc = _audiod_fct[i].p_desc;
+ uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
+ while (p_desc < p_desc_end)
{
- tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
- if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
+ if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
{
- #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- // Explicit feedback EP
- if (desc_ep->bmAttributes.usage == 1)
+ tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
{
- ep_fb = desc_ep->bEndpointAddress;
- }
+ #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
+ // Explicit feedback EP
+ if (desc_ep->bmAttributes.usage == 1)
+ {
+ ep_fb = desc_ep->bEndpointAddress;
+ }
#endif
- // Data EP
- if (desc_ep->bmAttributes.usage == 0)
- {
- if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
+ // Data EP
+ if (desc_ep->bmAttributes.usage == 0)
{
+ if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
+ {
#if CFG_TUD_AUDIO_ENABLE_EP_IN
- ep_in = desc_ep->bEndpointAddress;
- ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
+ ep_in = desc_ep->bEndpointAddress;
+ ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
#endif
- } else
- {
+ } else
+ {
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
- ep_out = desc_ep->bEndpointAddress;
- ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
+ ep_out = desc_ep->bEndpointAddress;
+ ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
#endif
+ }
}
- }
+ }
}
+
+ p_desc = tu_desc_next(p_desc);
}
- p_desc = tu_desc_next(p_desc);
- }
#if CFG_TUD_AUDIO_ENABLE_EP_IN
- if (ep_in)
- {
- usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size);
- }
+ if (ep_in)
+ {
+ usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size);
+ }
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
- if (ep_out)
- {
- usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size);
- }
+ if (ep_out)
+ {
+ usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size);
+ }
#endif
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- if (ep_fb)
+ if (ep_fb)
+ {
+ usbd_edpt_iso_alloc(rhport, ep_fb, 4);
+ }
+ #endif
+ }
+#endif // TUP_DCD_EDPT_ISO_ALLOC
+
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
{
- usbd_edpt_iso_alloc(rhport, ep_fb, 4);
+ uint8_t const *p_desc = _audiod_fct[i].p_desc;
+ uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
+ {
+ if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
+ {
+ tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
+ {
+ if (desc_ep->bmAttributes.usage == 0)
+ {
+ if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
+ {
+ _audiod_fct[i].interval_tx = desc_ep->bInterval;
+ }
+ }
+ }
+ } else
+ if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL)
+ {
+ if(tu_unaligned_read16(p_desc + 4) == AUDIO_TERM_TYPE_USB_STREAMING)
+ {
+ _audiod_fct[i].bclock_id_tx = p_desc[8];
+ }
+ }
+ p_desc = tu_desc_next(p_desc);
+ }
}
- #endif
+#endif // CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
-#endif // USE_ISO_EP_ALLOCATION
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+ {
+ uint8_t const *p_desc = _audiod_fct[i].p_desc;
+ uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
+ {
+ // For each endpoint
+ if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
+ {
+ tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ uint8_t const ep_addr = desc_ep->bEndpointAddress;
+ // If endpoint is input-direction and interrupt-type
+ if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT)
+ {
+ // Store endpoint number and open endpoint
+ _audiod_fct[i].ep_int = ep_addr;
+ TU_ASSERT(usbd_edpt_open(_audiod_fct[i].rhport, desc_ep));
+ }
+ }
+ p_desc = tu_desc_next(p_desc);
+ }
+ }
+#endif
+ _audiod_fct[i].mounted = true;
break;
}
}
@@ -1615,7 +1671,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
if (audio->ep_in_as_intf_num == itf)
{
audio->ep_in_as_intf_num = 0;
- #if !USE_ISO_EP_ALLOCATION
+ #ifndef TUP_DCD_EDPT_ISO_ALLOC
usbd_edpt_close(rhport, audio->ep_in);
#endif
@@ -1634,6 +1690,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
audio->ep_in = 0; // Necessary?
+ #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+ audio->packet_sz_tx[0] = 0;
+ audio->packet_sz_tx[1] = 0;
+ audio->packet_sz_tx[2] = 0;
+ #endif
}
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN
@@ -1641,7 +1702,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
if (audio->ep_out_as_intf_num == itf)
{
audio->ep_out_as_intf_num = 0;
- #if !USE_ISO_EP_ALLOCATION
+ #ifndef TUP_DCD_EDPT_ISO_ALLOC
usbd_edpt_close(rhport, audio->ep_out);
#endif
@@ -1662,7 +1723,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
// Close corresponding feedback EP
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
- #if !USE_ISO_EP_ALLOCATION
+ #ifndef TUP_DCD_EDPT_ISO_ALLOC
usbd_edpt_close(rhport, audio->ep_fb);
#endif
audio->ep_fb = 0;
@@ -1684,7 +1745,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
// Find correct interface
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt)
{
-#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING
+#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING)
uint8_t const * p_desc_parse_for_params = p_desc;
#endif
// From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary
@@ -1694,7 +1755,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
{
tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const *) p_desc;
-#if USE_ISO_EP_ALLOCATION
+#ifdef TUP_DCD_EDPT_ISO_ALLOC
TU_ASSERT(usbd_edpt_iso_activate(rhport, desc_ep));
#else
TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
@@ -1713,12 +1774,13 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
audio->ep_in_sz = tu_edpt_packet_size(desc_ep);
// If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters
- #if CFG_TUD_AUDIO_ENABLE_ENCODING
+ #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf);
// Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap
- #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
- const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / audio->n_bytes_per_sampe_tx) * audio->n_bytes_per_sampe_tx);
+ #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
+ const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx))
+ * (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx));
for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++)
{
tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true);
@@ -1850,6 +1912,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
if (disable) usbd_sof_enable(rhport, false);
#endif
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+ audiod_calc_tx_packet_sz(audio);
+#endif
+
tud_control_status(rhport, p_request);
return true;
@@ -2070,10 +2136,10 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
{
audiod_function_t* audio = &_audiod_fct[func_id];
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
// Data transmission of control interrupt finished
- if (audio->ep_int_ctr == ep_addr)
+ if (audio->ep_int == ep_addr)
{
// According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49)
// In case there is nothing to send we have to return a NAK - this is taken care of by PHY ???
@@ -2082,7 +2148,8 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
// I assume here, that things above are handled by PHY
// All transmission is done - what remains to do is to inform job was completed
- if (tud_audio_int_ctr_done_cb) TU_VERIFY(tud_audio_int_ctr_done_cb(rhport, (uint16_t) xferred_bytes));
+ if (tud_audio_int_done_cb) tud_audio_int_done_cb(rhport);
+ return true;
}
#endif
@@ -2292,6 +2359,19 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req
// Copy into buffer
TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz, data, (size_t)len));
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+ // Find data for sampling_frequency_control
+ if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE)
+ {
+ uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
+ uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue);
+ if (_audiod_fct[func_id].bclock_id_tx == entityID && ctrlSel == AUDIO_CS_CTRL_SAM_FREQ && p_request->bRequest == AUDIO_CS_REQ_CUR)
+ {
+ _audiod_fct[func_id].sample_rate_tx = tu_unaligned_read32(_audiod_fct[func_id].ctrl_buf);
+ }
+ }
+#endif
+
// Schedule transmit
return tud_control_xfer(rhport, p_request, (void*)_audiod_fct[func_id].ctrl_buf, len);
}
@@ -2431,7 +2511,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id)
return false;
}
-#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING
+#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING)
// p_desc points to the AS interface of alternate setting zero
// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter
// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for!
@@ -2469,7 +2549,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
}
#endif
-#if CFG_TUD_AUDIO_ENABLE_EP_OUT
+#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
if (as_itf == audio->ep_out_as_intf_num)
{
audio->n_channels_rx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels;
@@ -2482,7 +2562,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
}
// Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats)
-#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
+#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const * )p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I)
{
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT
@@ -2502,7 +2582,7 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
}
#endif
-#if CFG_TUD_AUDIO_ENABLE_EP_OUT
+#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
if (as_itf == audio->ep_out_as_intf_num)
{
audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize;
@@ -2518,6 +2598,96 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
}
#endif
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+
+static bool audiod_calc_tx_packet_sz(audiod_function_t* audio)
+{
+ TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I);
+ TU_VERIFY(audio->n_channels_tx);
+ TU_VERIFY(audio->n_bytes_per_sampe_tx);
+ TU_VERIFY(audio->interval_tx);
+ TU_VERIFY(audio->sample_rate_tx);
+
+ const uint8_t interval = (tud_speed_get() == TUSB_SPEED_FULL) ? audio->interval_tx : 1 << (audio->interval_tx - 1);
+
+ const uint16_t sample_normimal = (uint16_t)(audio->sample_rate_tx * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
+ const uint16_t sample_reminder = (uint16_t)(audio->sample_rate_tx * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
+
+ const uint16_t packet_sz_tx_min = (uint16_t)((sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
+ const uint16_t packet_sz_tx_norm = (uint16_t)(sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
+ const uint16_t packet_sz_tx_max = (uint16_t)((sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
+
+ // Endpoint size must larger than packet size
+ TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz);
+
+ // Frmt20.pdf 2.3.1.1 USB Packets
+ if (sample_reminder)
+ {
+ // All virtual frame packets must either contain INT(nav) audio slots (small VFP) or INT(nav)+1 (large VFP) audio slots
+ audio->packet_sz_tx[0] = packet_sz_tx_norm;
+ audio->packet_sz_tx[1] = packet_sz_tx_norm;
+ audio->packet_sz_tx[2] = packet_sz_tx_max;
+ } else
+ {
+ // In the case where nav = INT(nav), ni may vary between INT(nav)-1 (small VFP), INT(nav)
+ // (medium VFP) and INT(nav)+1 (large VFP).
+ audio->packet_sz_tx[0] = packet_sz_tx_min;
+ audio->packet_sz_tx[1] = packet_sz_tx_norm;
+ audio->packet_sz_tx[2] = packet_sz_tx_max;
+ }
+
+ return true;
+}
+
+static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_depth)
+{
+ // Flow control need a FIFO size of at least 4*Navg
+ if(norminal_size[1] && norminal_size[1] <= fifo_depth * 4)
+ {
+ // Use blackout to prioritize normal size packet
+ static int ctrl_blackout = 0;
+ uint16_t packet_size;
+ uint16_t slot_size = norminal_size[2] - norminal_size[1];
+ if (data_count < norminal_size[0])
+ {
+ // If you get here frequently, then your I2S clock deviation is too big !
+ packet_size = 0;
+ } else
+ if (data_count < fifo_depth / 2 - slot_size && !ctrl_blackout)
+ {
+ packet_size = norminal_size[0];
+ ctrl_blackout = 10;
+ } else
+ if (data_count > fifo_depth / 2 + slot_size && !ctrl_blackout)
+ {
+ packet_size = norminal_size[2];
+ if(norminal_size[0] == norminal_size[1])
+ {
+ // nav > INT(nav), eg. 44.1k, 88.2k
+ ctrl_blackout = 0;
+ } else
+ {
+ // nav = INT(nav), eg. 48k, 96k
+ ctrl_blackout = 10;
+ }
+ } else
+ {
+ packet_size = norminal_size[1];
+ if (ctrl_blackout)
+ {
+ ctrl_blackout--;
+ }
+ }
+ // Normally this cap is not necessary
+ return tu_min16(packet_size, max_depth);
+ } else
+ {
+ return tu_min16(data_count, max_depth);
+ }
+}
+
+#endif
+
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h
index 7c88b99fc..b16514fd4 100644
--- a/src/class/audio/audio_device.h
+++ b/src/class/audio/audio_device.h
@@ -181,6 +181,11 @@
#endif
#endif
+// (For TYPE-I format only) Flow control is necessary to allow IN ep send correct amount of data, unless it's a virtual device where data is perfectly synchronized to USB clock.
+#ifndef CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
+#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1
+#endif
+
// Enable/disable feedback EP (required for asynchronous RX applications)
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1
@@ -191,13 +196,9 @@
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1
#endif
-// Audio interrupt control EP size - disabled if 0
-#ifndef CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
-#define CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN 0 // Audio interrupt control - if required - 6 Bytes according to UAC 2 specification (p. 74)
-#endif
-
-#ifndef CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE
-#define CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE 6 // Buffer size of audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74)
+// Enable/disable interrupt EP (required for notifying host of control changes)
+#ifndef CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 0 // Feedback - 0 or 1
#endif
// Use software encoding/decoding
@@ -388,10 +389,11 @@ uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_i
tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx);
#endif
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
-uint16_t tud_audio_int_ctr_n_write (uint8_t func_id, uint8_t const* buffer, uint16_t len);
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+bool tud_audio_int_n_write (uint8_t func_id, const audio_interrupt_data_t * data);
#endif
+
//--------------------------------------------------------------------+
// Application API (Interface0)
//--------------------------------------------------------------------+
@@ -431,8 +433,8 @@ static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx);
// INT CTR API
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
-static inline uint16_t tud_audio_int_ctr_write (uint8_t const* buffer, uint16_t len);
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+static inline bool tud_audio_int_write (const audio_interrupt_data_t * data);
#endif
// Buffer control EP data and schedule a transmit
@@ -531,8 +533,8 @@ TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
-TU_ATTR_WEAK bool tud_audio_int_ctr_done_cb(uint8_t rhport, uint16_t n_bytes_copied);
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport);
#endif
// Invoked when audio set interface request received
@@ -663,10 +665,10 @@ static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx)
#endif
-#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
-static inline uint16_t tud_audio_int_ctr_write(uint8_t const* buffer, uint16_t len)
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+static inline bool tud_audio_int_write(const audio_interrupt_data_t * data)
{
- return tud_audio_int_ctr_n_write(0, buffer, len);
+ return tud_audio_int_n_write(0, data);
}
#endif
@@ -683,6 +685,7 @@ static inline bool tud_audio_fb_set(uint32_t feedback)
// Internal Class Driver API
//--------------------------------------------------------------------+
void audiod_init (void);
+bool audiod_deinit (void);
void audiod_reset (uint8_t rhport);
uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c
index f96bb3552..cbf6e1332 100755
--- a/src/class/bth/bth_device.c
+++ b/src/class/bth/bth_device.c
@@ -55,7 +55,7 @@ typedef struct
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_MEM_SECTION btd_interface_t _btd_itf;
+CFG_TUD_MEM_SECTION btd_interface_t _btd_itf;
static bool bt_tx_data(uint8_t ep, void *data, uint16_t len)
{
@@ -91,11 +91,14 @@ bool tud_bt_acl_data_send(void *event, uint16_t event_len)
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void btd_init(void)
-{
+void btd_init(void) {
tu_memclr(&_btd_itf, sizeof(_btd_itf));
}
+bool btd_deinit(void) {
+ return true;
+}
+
void btd_reset(uint8_t rhport)
{
(void)rhport;
@@ -204,7 +207,9 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c
request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE)
{
// HCI command packet addressing for single function Primary Controllers
- TU_VERIFY(request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0);
+ // also compatible with historical mode if enabled
+ TU_VERIFY((request->bRequest == 0 && request->wValue == 0 && request->wIndex == 0) ||
+ (CFG_TUD_BTH_HISTORICAL_COMPATIBLE && request->bRequest == 0xe0));
}
else if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE)
{
diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h
index 921bd7a1a..4f6350839 100755
--- a/src/class/bth/bth_device.h
+++ b/src/class/bth/bth_device.h
@@ -36,10 +36,17 @@
#ifndef CFG_TUD_BTH_EVENT_EPSIZE
#define CFG_TUD_BTH_EVENT_EPSIZE 16
#endif
+
#ifndef CFG_TUD_BTH_DATA_EPSIZE
#define CFG_TUD_BTH_DATA_EPSIZE 64
#endif
+// Allow BTH class to work in historically compatibility mode where the bRequest is always 0xe0.
+// See Bluetooth Core v5.3, Vol. 4, Part B, Section 2.2
+#ifndef CFG_TUD_BTH_HISTORICAL_COMPATIBLE
+#define CFG_TUD_BTH_HISTORICAL_COMPATIBLE 0
+#endif
+
typedef struct TU_ATTR_PACKED
{
uint16_t op_code;
@@ -97,6 +104,7 @@ bool tud_bt_acl_data_send(void *acl_data, uint16_t data_len);
// Internal Class Driver API
//--------------------------------------------------------------------+
void btd_init (void);
+bool btd_deinit (void);
void btd_reset (uint8_t rhport);
uint16_t btd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool btd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *request);
diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h
index 4658e43af..5cbd658fe 100644
--- a/src/class/cdc/cdc.h
+++ b/src/class/cdc/cdc.h
@@ -136,8 +136,7 @@ typedef enum{
//--------------------------------------------------------------------+
/// Communication Interface Management Element Request Codes
-typedef enum
-{
+typedef enum {
CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface
CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface.
CDC_REQUEST_SET_COMM_FEATURE = 0x02,
@@ -180,37 +179,38 @@ typedef enum
CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53,
CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60,
-}cdc_management_request_t;
+} cdc_management_request_t;
-enum
-{
+typedef enum {
CDC_CONTROL_LINE_STATE_DTR = 0x01,
CDC_CONTROL_LINE_STATE_RTS = 0x02,
-};
+} cdc_control_line_state_t;
-enum
-{
- CDC_LINE_CONDING_STOP_BITS_1 = 0, // 1 bit
- CDC_LINE_CONDING_STOP_BITS_1_5 = 1, // 1.5 bits
- CDC_LINE_CONDING_STOP_BITS_2 = 2, // 2 bits
-};
+typedef enum {
+ CDC_LINE_CODING_STOP_BITS_1 = 0, // 1 bit
+ CDC_LINE_CODING_STOP_BITS_1_5 = 1, // 1.5 bits
+ CDC_LINE_CODING_STOP_BITS_2 = 2, // 2 bits
+} cdc_line_coding_stopbits_t;
-enum
-{
+// TODO Backward compatible for typos. Maybe removed in the future release
+#define CDC_LINE_CONDING_STOP_BITS_1 CDC_LINE_CODING_STOP_BITS_1
+#define CDC_LINE_CONDING_STOP_BITS_1_5 CDC_LINE_CODING_STOP_BITS_1_5
+#define CDC_LINE_CONDING_STOP_BITS_2 CDC_LINE_CODING_STOP_BITS_2
+
+typedef enum {
CDC_LINE_CODING_PARITY_NONE = 0,
CDC_LINE_CODING_PARITY_ODD = 1,
CDC_LINE_CODING_PARITY_EVEN = 2,
CDC_LINE_CODING_PARITY_MARK = 3,
CDC_LINE_CODING_PARITY_SPACE = 4,
-};
+} cdc_line_coding_parity_t;
//--------------------------------------------------------------------+
// Management Element Notification (Notification Endpoint)
//--------------------------------------------------------------------+
/// 6.3 Notification Codes
-typedef enum
-{
+typedef enum {
CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status.
CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request.
CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08,
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index 5adce521d..7ef0530ec 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -33,6 +33,13 @@
#include "cdc_device.h"
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUD_CDC_LOG_LEVEL
+ #define CFG_TUD_CDC_LOG_LEVEL CFG_TUD_LOG_LEVEL
+#endif
+
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_CDC_LOG_LEVEL, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
@@ -76,7 +83,7 @@ typedef struct
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_MEM_SECTION tu_static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
+CFG_TUD_MEM_SECTION tu_static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
static bool _prep_out_transaction (cdcd_interface_t* p_cdc)
{
@@ -143,7 +150,7 @@ uint32_t tud_cdc_n_available(uint8_t itf)
uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize)
{
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
- uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) bufsize);
+ uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
_prep_out_transaction(p_cdc);
return num_read;
}
@@ -166,7 +173,7 @@ void tud_cdc_n_read_flush (uint8_t itf)
uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize)
{
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
- uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) bufsize);
+ uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
// flush if queue more than packet size
// may need to suppress -Wunreachable-code since most of the time CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE
@@ -246,9 +253,37 @@ void cdcd_init(void)
// In this way, the most current data is prioritized.
tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true);
- tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, osal_mutex_create(&p_cdc->rx_ff_mutex));
- tu_fifo_config_mutex(&p_cdc->tx_ff, osal_mutex_create(&p_cdc->tx_ff_mutex), NULL);
+ #if OSAL_MUTEX_REQUIRED
+ osal_mutex_t mutex_rd = osal_mutex_create(&p_cdc->rx_ff_mutex);
+ osal_mutex_t mutex_wr = osal_mutex_create(&p_cdc->tx_ff_mutex);
+ TU_ASSERT(mutex_rd != NULL && mutex_wr != NULL, );
+
+ tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, mutex_rd);
+ tu_fifo_config_mutex(&p_cdc->tx_ff, mutex_wr, NULL);
+ #endif
+ }
+}
+
+bool cdcd_deinit(void) {
+ #if OSAL_MUTEX_REQUIRED
+ for(uint8_t i=0; i<CFG_TUD_CDC; i++) {
+ cdcd_interface_t* p_cdc = &_cdcd_itf[i];
+ osal_mutex_t mutex_rd = p_cdc->rx_ff.mutex_rd;
+ osal_mutex_t mutex_wr = p_cdc->tx_ff.mutex_wr;
+
+ if (mutex_rd) {
+ osal_mutex_delete(mutex_rd);
+ tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, NULL);
+ }
+
+ if (mutex_wr) {
+ osal_mutex_delete(mutex_wr);
+ tu_fifo_config_mutex(&p_cdc->tx_ff, NULL, NULL);
+ }
}
+ #endif
+
+ return true;
}
void cdcd_reset(uint8_t rhport)
@@ -353,7 +388,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
case CDC_REQUEST_SET_LINE_CODING:
if (stage == CONTROL_STAGE_SETUP)
{
- TU_LOG2(" Set Line Coding\r\n");
+ TU_LOG_DRV(" Set Line Coding\r\n");
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
}
else if ( stage == CONTROL_STAGE_ACK)
@@ -365,7 +400,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
case CDC_REQUEST_GET_LINE_CODING:
if (stage == CONTROL_STAGE_SETUP)
{
- TU_LOG2(" Get Line Coding\r\n");
+ TU_LOG_DRV(" Get Line Coding\r\n");
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
}
break;
@@ -390,7 +425,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
// Disable fifo overwriting if DTR bit is set
tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
- TU_LOG2(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
+ TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
// Invoke callback
if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts);
@@ -403,7 +438,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
}
else if (stage == CONTROL_STAGE_ACK)
{
- TU_LOG2(" Send Break\r\n");
+ TU_LOG_DRV(" Send Break\r\n");
if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue);
}
break;
diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h
index a6e07aa5c..20e908451 100644
--- a/src/class/cdc/cdc_device.h
+++ b/src/class/cdc/cdc_device.h
@@ -247,6 +247,7 @@ static inline bool tud_cdc_write_clear(void)
// INTERNAL USBD-CLASS DRIVER API
//--------------------------------------------------------------------+
void cdcd_init (void);
+bool cdcd_deinit (void);
void cdcd_reset (uint8_t rhport);
uint16_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool cdcd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c
index e2447d033..5bdd41f1f 100644
--- a/src/class/cdc/cdc_host.c
+++ b/src/class/cdc/cdc_host.c
@@ -22,6 +22,9 @@
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
+ *
+ * Contribution
+ * - Heiko Kuester: CH34x support
*/
#include "tusb_option.h"
@@ -29,37 +32,39 @@
#if (CFG_TUH_ENABLED && CFG_TUH_CDC)
#include "host/usbh.h"
-#include "host/usbh_classdriver.h"
+#include "host/usbh_pvt.h"
#include "cdc_host.h"
-// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message
-#define CDCH_DEBUG 2
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUH_CDC_LOG_LEVEL
+ #define CFG_TUH_CDC_LOG_LEVEL CFG_TUH_LOG_LEVEL
+#endif
-#define TU_LOG_CDCH(...) TU_LOG(CDCH_DEBUG, __VA_ARGS__)
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__)
//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
+// Host CDC Interface
//--------------------------------------------------------------------+
-enum {
- SERIAL_PROTOCOL_ACM = 0,
- SERIAL_PROTOCOL_FTDI,
- SERIAL_PROTOCOL_CP210X,
-};
-
typedef struct {
uint8_t daddr;
uint8_t bInterfaceNumber;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
- uint8_t serial_protocol;
- cdc_acm_capability_t acm_capability;
uint8_t ep_notif;
+ uint8_t serial_drid; // Serial Driver ID
+ bool mounted; // Enumeration is complete
+ cdc_acm_capability_t acm_capability;
- uint8_t line_state; // DTR (bit0), RTS (bit1)
TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width
+ uint8_t line_state; // DTR (bit0), RTS (bit1)
+
+ #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X
+ cdc_line_coding_t requested_line_coding;
+ // 1 byte padding
+ #endif
tuh_xfer_cb_t user_control_cb;
@@ -73,32 +78,170 @@ typedef struct {
uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE];
CFG_TUH_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE];
} stream;
-
} cdch_interface_t;
+CFG_TUH_MEM_SECTION
+static cdch_interface_t cdch_data[CFG_TUH_CDC];
+
//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
+// Serial Driver
//--------------------------------------------------------------------+
-CFG_TUH_MEM_SECTION
-static cdch_interface_t cdch_data[CFG_TUH_CDC];
+//------------- ACM prototypes -------------//
+static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
+static void acm_process_config(tuh_xfer_t* xfer);
+
+static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+
+//------------- FTDI prototypes -------------//
+#if CFG_TUH_CDC_FTDI
+#include "serial/ftdi_sio.h"
+
+static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST};
+
+static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len);
+static void ftdi_process_config(tuh_xfer_t* xfer);
+
+static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+#endif
+
+//------------- CP210X prototypes -------------//
+#if CFG_TUH_CDC_CP210X
+#include "serial/cp210x.h"
+
+static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST};
+
+static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
+static void cp210x_process_config(tuh_xfer_t* xfer);
+
+static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+#endif
+
+//------------- CH34x prototypes -------------//
+#if CFG_TUH_CDC_CH34X
+#include "serial/ch34x.h"
+
+static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST};
+
+static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len);
+static void ch34x_process_config(tuh_xfer_t* xfer);
+
+static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+#endif
+
+//------------- Common -------------//
+enum {
+ SERIAL_DRIVER_ACM = 0,
+
+#if CFG_TUH_CDC_FTDI
+ SERIAL_DRIVER_FTDI,
+#endif
+
+#if CFG_TUH_CDC_CP210X
+ SERIAL_DRIVER_CP210X,
+#endif
+
+#if CFG_TUH_CDC_CH34X
+ SERIAL_DRIVER_CH34X,
+#endif
+
+ SERIAL_DRIVER_COUNT
+};
+
+typedef struct {
+ uint16_t const (*vid_pid_list)[2];
+ uint16_t const vid_pid_count;
+ bool (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len);
+ void (*const process_set_config)(tuh_xfer_t* xfer);
+ bool (*const set_control_line_state)(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+ bool (*const set_baudrate)(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+ bool (*const set_data_format)(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+ bool (*const set_line_coding)(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+} cdch_serial_driver_t;
+
+// Note driver list must be in the same order as SERIAL_DRIVER enum
+static const cdch_serial_driver_t serial_drivers[] = {
+ {
+ .vid_pid_list = NULL,
+ .vid_pid_count = 0,
+ .open = acm_open,
+ .process_set_config = acm_process_config,
+ .set_control_line_state = acm_set_control_line_state,
+ .set_baudrate = acm_set_baudrate,
+ .set_data_format = acm_set_data_format,
+ .set_line_coding = acm_set_line_coding
+ },
+
+ #if CFG_TUH_CDC_FTDI
+ {
+ .vid_pid_list = ftdi_vid_pid_list,
+ .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list),
+ .open = ftdi_open,
+ .process_set_config = ftdi_process_config,
+ .set_control_line_state = ftdi_sio_set_modem_ctrl,
+ .set_baudrate = ftdi_sio_set_baudrate,
+ .set_data_format = ftdi_set_data_format,
+ .set_line_coding = ftdi_set_line_coding
+ },
+ #endif
+
+ #if CFG_TUH_CDC_CP210X
+ {
+ .vid_pid_list = cp210x_vid_pid_list,
+ .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list),
+ .open = cp210x_open,
+ .process_set_config = cp210x_process_config,
+ .set_control_line_state = cp210x_set_modem_ctrl,
+ .set_baudrate = cp210x_set_baudrate,
+ .set_data_format = cp210x_set_data_format,
+ .set_line_coding = cp210x_set_line_coding
+ },
+ #endif
+
+ #if CFG_TUH_CDC_CH34X
+ {
+ .vid_pid_list = ch34x_vid_pid_list,
+ .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list),
+ .open = ch34x_open,
+ .process_set_config = ch34x_process_config,
+ .set_control_line_state = ch34x_set_modem_ctrl,
+ .set_baudrate = ch34x_set_baudrate,
+ .set_data_format = ch34x_set_data_format,
+ .set_line_coding = ch34x_set_line_coding
+ },
+ #endif
+};
+
+TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial driver count mismatch");
-static inline cdch_interface_t* get_itf(uint8_t idx)
-{
+//--------------------------------------------------------------------+
+// INTERNAL OBJECT & FUNCTION DECLARATION
+//--------------------------------------------------------------------+
+
+static inline cdch_interface_t* get_itf(uint8_t idx) {
TU_ASSERT(idx < CFG_TUH_CDC, NULL);
cdch_interface_t* p_cdc = &cdch_data[idx];
return (p_cdc->daddr != 0) ? p_cdc : NULL;
}
-static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr)
-{
- for(uint8_t i=0; i<CFG_TUH_CDC; i++)
- {
+static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) {
+ for(uint8_t i=0; i<CFG_TUH_CDC; i++) {
cdch_interface_t* p_cdc = &cdch_data[i];
if ( (p_cdc->daddr == daddr) &&
- (ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr))
- {
+ (ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr)) {
return i;
}
}
@@ -106,14 +249,10 @@ static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr)
return TUSB_INDEX_INVALID_8;
}
-
-static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const *itf_desc)
-{
- for(uint8_t i=0; i<CFG_TUH_CDC; i++)
- {
+static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const *itf_desc) {
+ for(uint8_t i=0; i<CFG_TUH_CDC; i++) {
if (cdch_data[i].daddr == 0) {
cdch_interface_t* p_cdc = &cdch_data[i];
-
p_cdc->daddr = daddr;
p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber;
p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass;
@@ -130,57 +269,20 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t c
static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num);
static void cdch_internal_control_complete(tuh_xfer_t* xfer);
-//------------- FTDI prototypes -------------//
-#if CFG_TUH_CDC_FTDI
-#include "serial/ftdi_sio.h"
-
-static uint16_t const ftdi_pids[] = { TU_FTDI_PID_LIST };
-enum {
- FTDI_PID_COUNT = sizeof(ftdi_pids) / sizeof(ftdi_pids[0])
-};
-
-static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len);
-static void process_ftdi_config(tuh_xfer_t* xfer);
-
-static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
-static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
-#endif
-
-//------------- CP210X prototypes -------------//
-#if CFG_TUH_CDC_CP210X
-#include "serial/cp210x.h"
-
-static uint16_t const cp210x_pids[] = { TU_CP210X_PID_LIST };
-enum {
- CP210X_PID_COUNT = sizeof(cp210x_pids) / sizeof(cp210x_pids[0])
-};
-
-static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
-static void process_cp210x_config(tuh_xfer_t* xfer);
-
-static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
-static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
-#endif
-
-
//--------------------------------------------------------------------+
// APPLICATION API
//--------------------------------------------------------------------+
-uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num)
-{
- for(uint8_t i=0; i<CFG_TUH_CDC; i++)
- {
+uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num) {
+ for (uint8_t i = 0; i < CFG_TUH_CDC; i++) {
const cdch_interface_t* p_cdc = &cdch_data[i];
-
if (p_cdc->daddr == daddr && p_cdc->bInterfaceNumber == itf_num) return i;
}
return TUSB_INDEX_INVALID_8;
}
-bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info)
-{
+bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc && info);
@@ -202,30 +304,27 @@ bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info)
return true;
}
-bool tuh_cdc_mounted(uint8_t idx)
-{
+bool tuh_cdc_mounted(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
- return p_cdc != NULL;
+ TU_VERIFY(p_cdc);
+ return p_cdc->mounted;
}
-bool tuh_cdc_get_dtr(uint8_t idx)
-{
+bool tuh_cdc_get_dtr(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR) ? true : false;
}
-bool tuh_cdc_get_rts(uint8_t idx)
-{
+bool tuh_cdc_get_rts(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS) ? true : false;
}
-bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding)
-{
+bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
@@ -238,32 +337,28 @@ bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding)
// Write
//--------------------------------------------------------------------+
-uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize)
-{
+uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize);
}
-uint32_t tuh_cdc_write_flush(uint8_t idx)
-{
+uint32_t tuh_cdc_write_flush(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_write_xfer(&p_cdc->stream.tx);
}
-bool tuh_cdc_write_clear(uint8_t idx)
-{
+bool tuh_cdc_write_clear(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_clear(&p_cdc->stream.tx);
}
-uint32_t tuh_cdc_write_available(uint8_t idx)
-{
+uint32_t tuh_cdc_write_available(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
@@ -274,32 +369,28 @@ uint32_t tuh_cdc_write_available(uint8_t idx)
// Read
//--------------------------------------------------------------------+
-uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize)
-{
+uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize);
}
-uint32_t tuh_cdc_read_available(uint8_t idx)
-{
+uint32_t tuh_cdc_read_available(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_read_available(&p_cdc->stream.rx);
}
-bool tuh_cdc_peek(uint8_t idx, uint8_t* ch)
-{
+bool tuh_cdc_peek(uint8_t idx, uint8_t* ch) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_peek(&p_cdc->stream.rx, ch);
}
-bool tuh_cdc_read_clear (uint8_t idx)
-{
+bool tuh_cdc_read_clear (uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
@@ -312,184 +403,217 @@ bool tuh_cdc_read_clear (uint8_t idx)
// Control Endpoint API
//--------------------------------------------------------------------+
-// internal control complete to update state such as line state, encoding
-static void cdch_internal_control_complete(tuh_xfer_t* xfer)
-{
- uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+static void process_internal_control_complete(tuh_xfer_t* xfer, uint8_t itf_num) {
uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
cdch_interface_t* p_cdc = get_itf(idx);
TU_ASSERT(p_cdc, );
+ uint16_t const value = tu_le16toh(xfer->setup->wValue);
- if (xfer->result == XFER_RESULT_SUCCESS)
- {
- if (p_cdc->serial_protocol == SERIAL_PROTOCOL_ACM) {
- switch (xfer->setup->bRequest) {
- case CDC_REQUEST_SET_CONTROL_LINE_STATE:
- p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue);
- break;
+ if (xfer->result == XFER_RESULT_SUCCESS) {
+ switch (p_cdc->serial_drid) {
+ case SERIAL_DRIVER_ACM:
+ switch (xfer->setup->bRequest) {
+ case CDC_REQUEST_SET_CONTROL_LINE_STATE:
+ p_cdc->line_state = (uint8_t) value;
+ break;
- case CDC_REQUEST_SET_LINE_CODING: {
- uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength));
- memcpy(&p_cdc->line_coding, xfer->buffer, len);
+ case CDC_REQUEST_SET_LINE_CODING: {
+ uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength));
+ memcpy(&p_cdc->line_coding, xfer->buffer, len);
+ break;
+ }
+
+ default: break;
}
- break;
+ break;
- default: break;
- }
- }
- #if CFG_TUH_CDC_FTDI
- else if (p_cdc->serial_protocol == SERIAL_PROTOCOL_FTDI) {
- switch (xfer->setup->bRequest) {
- case FTDI_SIO_MODEM_CTRL:
- p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff);
- break;
+ #if CFG_TUH_CDC_FTDI
+ case SERIAL_DRIVER_FTDI:
+ switch (xfer->setup->bRequest) {
+ case FTDI_SIO_MODEM_CTRL:
+ p_cdc->line_state = (uint8_t) value;
+ break;
- default: break;
- }
- }
- #endif
- }
+ case FTDI_SIO_SET_BAUD_RATE:
+ p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate;
+ break;
- xfer->complete_cb = p_cdc->user_control_cb;
- xfer->complete_cb(xfer);
-}
+ default: break;
+ }
+ break;
+ #endif
-static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
- TU_LOG_CDCH("CDC ACM Set Control Line State\r\n");
- tusb_control_request_t const request = {
- .bmRequestType_bit = {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE,
- .wValue = tu_htole16(line_state),
- .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber),
- .wLength = 0
- };
+ #if CFG_TUH_CDC_CP210X
+ case SERIAL_DRIVER_CP210X:
+ switch(xfer->setup->bRequest) {
+ case CP210X_SET_MHS:
+ p_cdc->line_state = (uint8_t) value;
+ break;
- p_cdc->user_control_cb = complete_cb;
+ case CP210X_SET_BAUDRATE: {
+ uint32_t baudrate;
+ memcpy(&baudrate, xfer->buffer, sizeof(uint32_t));
+ p_cdc->line_coding.bit_rate = tu_le32toh(baudrate);
+ break;
+ }
- tuh_xfer_t xfer = {
- .daddr = p_cdc->daddr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = NULL,
- .complete_cb = cdch_internal_control_complete,
- .user_data = user_data
- };
+ default: break;
+ }
+ break;
+ #endif
- TU_ASSERT(tuh_control_xfer(&xfer));
- return true;
-}
+ #if CFG_TUH_CDC_CH34X
+ case SERIAL_DRIVER_CH34X:
+ switch (xfer->setup->bRequest) {
+ case CH34X_REQ_WRITE_REG:
+ // register write request
+ switch (value) {
+ case CH34X_REG16_DIVISOR_PRESCALER:
+ // baudrate
+ p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate;
+ break;
-bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
- cdch_interface_t* p_cdc = get_itf(idx);
- TU_VERIFY(p_cdc);
+ case CH32X_REG16_LCR2_LCR:
+ // data format
+ p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits;
+ p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity;
+ p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits;
+ break;
- switch(p_cdc->serial_protocol) {
- case SERIAL_PROTOCOL_ACM:
- TU_VERIFY(p_cdc->acm_capability.support_line_request);
- return acm_set_control_line_state(p_cdc, line_state, complete_cb, user_data);
+ default: break;
+ }
+ break;
- #if CFG_TUH_CDC_FTDI
- case SERIAL_PROTOCOL_FTDI:
- return ftdi_sio_set_modem_ctrl(p_cdc, line_state, complete_cb, user_data);
- #endif
+ case CH34X_REQ_MODEM_CTRL: {
+ // set modem controls RTS/DTR request. Note: signals are inverted
+ uint16_t const modem_signal = ~value;
+ if (modem_signal & CH34X_BIT_RTS) {
+ p_cdc->line_state |= CDC_CONTROL_LINE_STATE_RTS;
+ } else {
+ p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_RTS;
+ }
- #if CFG_TUH_CDC_CP210X
- case SERIAL_PROTOCOL_CP210X:
- return ftdi_sio_set_modem_ctrl(p_cdc, line_state, complete_cb, user_data);
- #endif
+ if (modem_signal & CH34X_BIT_DTR) {
+ p_cdc->line_state |= CDC_CONTROL_LINE_STATE_DTR;
+ } else {
+ p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_DTR;
+ }
+ break;
+ }
- default:
- return false;
+ default: break;
+ }
+ break;
+ #endif
+
+ default: break;
+ }
+ }
+
+ xfer->complete_cb = p_cdc->user_control_cb;
+ if (xfer->complete_cb) {
+ xfer->complete_cb(xfer);
}
}
-bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
- TU_LOG_CDCH("CDC ACM Set Line Conding\r\n");
+// internal control complete to update state such as line state, encoding
+static void cdch_internal_control_complete(tuh_xfer_t* xfer) {
+ uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+ process_internal_control_complete(xfer, itf_num);
+}
- tusb_control_request_t const request = {
- .bmRequestType_bit = {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = CDC_REQUEST_SET_LINE_CODING,
- .wValue = 0,
- .wIndex = tu_htole16(p_cdc->bInterfaceNumber),
- .wLength = tu_htole16(sizeof(cdc_line_coding_t))
- };
+bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ cdch_interface_t* p_cdc = get_itf(idx);
+ TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT);
+ cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid];
- // use usbh enum buf to hold line coding since user line_coding variable does not live long enough
- uint8_t* enum_buf = usbh_get_enum_buf();
- memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t));
+ if (complete_cb) {
+ return driver->set_control_line_state(p_cdc, line_state, complete_cb, user_data);
+ } else {
+ // blocking
+ xfer_result_t result = XFER_RESULT_INVALID;
+ bool ret = driver->set_control_line_state(p_cdc, line_state, complete_cb, (uintptr_t) &result);
- p_cdc->user_control_cb = complete_cb;
- tuh_xfer_t xfer = {
- .daddr = p_cdc->daddr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = enum_buf,
- .complete_cb = cdch_internal_control_complete,
- .user_data = user_data
- };
+ if (user_data) {
+ // user_data is not NULL, return result via user_data
+ *((xfer_result_t*) user_data) = result;
+ }
- TU_ASSERT(tuh_control_xfer(&xfer));
- return true;
+ TU_VERIFY(ret && result == XFER_RESULT_SUCCESS);
+ p_cdc->line_state = (uint8_t) line_state;
+ return true;
+ }
}
-bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
cdch_interface_t* p_cdc = get_itf(idx);
- TU_VERIFY(p_cdc);
+ TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT);
+ cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid];
- switch(p_cdc->serial_protocol) {
- case SERIAL_PROTOCOL_ACM:
- TU_VERIFY(p_cdc->acm_capability.support_line_request);
- return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data);
+ if (complete_cb) {
+ return driver->set_baudrate(p_cdc, baudrate, complete_cb, user_data);
+ } else {
+ // blocking
+ xfer_result_t result = XFER_RESULT_INVALID;
+ bool ret = driver->set_baudrate(p_cdc, baudrate, complete_cb, (uintptr_t) &result);
- #if CFG_TUH_CDC_FTDI
- case SERIAL_PROTOCOL_FTDI:
- // FTDI need to set baud rate and data bits, parity, stop bits separately
- return ftdi_sio_set_baudrate(p_cdc, line_coding->bit_rate, complete_cb, user_data);
- #endif
-
- #if CFG_TUH_CDC_CP210X
- case SERIAL_PROTOCOL_CP210X:
- return cp210x_set_baudrate(p_cdc, line_coding->bit_rate, complete_cb, user_data);
- #endif
+ if (user_data) {
+ // user_data is not NULL, return result via user_data
+ *((xfer_result_t*) user_data) = result;
+ }
- default: return false;
+ TU_VERIFY(ret && result == XFER_RESULT_SUCCESS);
+ p_cdc->line_coding.bit_rate = baudrate;
+ return true;
}
}
-bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
cdch_interface_t* p_cdc = get_itf(idx);
- TU_VERIFY(p_cdc);
+ TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT);
+ cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid];
- switch(p_cdc->serial_protocol) {
- case SERIAL_PROTOCOL_ACM: {
- TU_VERIFY(p_cdc->acm_capability.support_line_request);
- cdc_line_coding_t line_coding = p_cdc->line_coding;
- line_coding.bit_rate = baudrate;
- return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data);
+ if (complete_cb) {
+ return driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, user_data);
+ } else {
+ // blocking
+ xfer_result_t result = XFER_RESULT_INVALID;
+ bool ret = driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, (uintptr_t) &result);
+
+ if (user_data) {
+ // user_data is not NULL, return result via user_data
+ *((xfer_result_t*) user_data) = result;
}
- #if CFG_TUH_CDC_FTDI
- case SERIAL_PROTOCOL_FTDI:
- // FTDI need to set baud rate and data bits, parity, stop bits separately
- return ftdi_sio_set_baudrate(p_cdc, baudrate, complete_cb, user_data);
- #endif
+ TU_VERIFY(ret && result == XFER_RESULT_SUCCESS);
+ p_cdc->line_coding.stop_bits = stop_bits;
+ p_cdc->line_coding.parity = parity;
+ p_cdc->line_coding.data_bits = data_bits;
+ return true;
+ }
+}
- #if CFG_TUH_CDC_CP210X
- case SERIAL_PROTOCOL_CP210X:
- return cp210x_set_baudrate(p_cdc, baudrate, complete_cb, user_data);
- #endif
+bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ cdch_interface_t* p_cdc = get_itf(idx);
+ TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT);
+ cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid];
- default: return false;
+ if ( complete_cb ) {
+ return driver->set_line_coding(p_cdc, line_coding, complete_cb, user_data);
+ } else {
+ // blocking
+ xfer_result_t result = XFER_RESULT_INVALID;
+ bool ret = driver->set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result);
+
+ if (user_data) {
+ // user_data is not NULL, return result via user_data
+ *((xfer_result_t*) user_data) = result;
+ }
+
+ TU_VERIFY(ret && result == XFER_RESULT_SUCCESS);
+ p_cdc->line_coding = *line_coding;
+ return true;
}
}
@@ -497,45 +621,51 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete
// CLASS-USBH API
//--------------------------------------------------------------------+
-void cdch_init(void)
-{
+bool cdch_init(void) {
+ TU_LOG_DRV("sizeof(cdch_interface_t) = %u\r\n", sizeof(cdch_interface_t));
tu_memclr(cdch_data, sizeof(cdch_data));
-
- for(size_t i=0; i<CFG_TUH_CDC; i++)
- {
+ for (size_t i = 0; i < CFG_TUH_CDC; i++) {
cdch_interface_t* p_cdc = &cdch_data[i];
-
tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false,
- p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE,
- p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE);
+ p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE,
+ p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE);
tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false,
- p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE,
- p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE);
+ p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE,
+ p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE);
}
+
+ return true;
}
-void cdch_close(uint8_t daddr)
-{
- for(uint8_t idx=0; idx<CFG_TUH_CDC; idx++)
- {
+bool cdch_deinit(void) {
+ for (size_t i = 0; i < CFG_TUH_CDC; i++) {
+ cdch_interface_t* p_cdc = &cdch_data[i];
+ tu_edpt_stream_deinit(&p_cdc->stream.tx);
+ tu_edpt_stream_deinit(&p_cdc->stream.rx);
+ }
+ return true;
+}
+
+void cdch_close(uint8_t daddr) {
+ for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
cdch_interface_t* p_cdc = &cdch_data[idx];
- if (p_cdc->daddr == daddr)
- {
+ if (p_cdc->daddr == daddr) {
+ TU_LOG_DRV(" CDCh close addr = %u index = %u\r\n", daddr, idx);
+
// Invoke application callback
if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx);
- //tu_memclr(p_cdc, sizeof(cdch_interface_t));
p_cdc->daddr = 0;
p_cdc->bInterfaceNumber = 0;
+ p_cdc->mounted = false;
tu_edpt_stream_close(&p_cdc->stream.tx);
tu_edpt_stream_close(&p_cdc->stream.rx);
}
}
}
-bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
-{
+bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) {
// TODO handle stall response, retry failed transfer ...
TU_ASSERT(event == XFER_RESULT_SUCCESS);
@@ -543,41 +673,35 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t
cdch_interface_t * p_cdc = get_itf(idx);
TU_ASSERT(p_cdc);
- if ( ep_addr == p_cdc->stream.tx.ep_addr )
- {
+ if ( ep_addr == p_cdc->stream.tx.ep_addr ) {
// invoke tx complete callback to possibly refill tx fifo
if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx);
- if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) )
- {
+ if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) {
// If there is no data left, a ZLP should be sent if:
// - xferred_bytes is multiple of EP Packet size and not zero
tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes);
}
- }
- else if ( ep_addr == p_cdc->stream.rx.ep_addr )
- {
- tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes);
-
+ } else if ( ep_addr == p_cdc->stream.rx.ep_addr ) {
#if CFG_TUH_CDC_FTDI
- // FTDI reserve 2 bytes for status
- if (p_cdc->serial_protocol == SERIAL_PROTOCOL_FTDI) {
- uint8_t status[2];
- tu_edpt_stream_read(&p_cdc->stream.rx, status, 2);
- (void) status; // TODO handle status
- }
+ if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) {
+ // FTDI reserve 2 bytes for status
+ // uint8_t status[2] = {p_cdc->stream.rx.ep_buf[0], p_cdc->stream.rx.ep_buf[1]};
+ tu_edpt_stream_read_xfer_complete_offset(&p_cdc->stream.rx, xferred_bytes, 2);
+ }else
#endif
+ {
+ tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes);
+ }
// invoke receive callback
if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(idx);
// prepare for next transfer if needed
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
- }else if ( ep_addr == p_cdc->ep_notif )
- {
+ }else if ( ep_addr == p_cdc->ep_notif ) {
// TODO handle notification endpoint
- }else
- {
+ }else {
TU_ASSERT(false);
}
@@ -587,28 +711,16 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t
//--------------------------------------------------------------------+
// Enumeration
//--------------------------------------------------------------------+
-enum
-{
- // ACM
- CONFIG_ACM_SET_CONTROL_LINE_STATE = 0,
- CONFIG_ACM_SET_LINE_CODING,
- CONFIG_ACM_COMPLETE,
-};
-static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t const *desc_ep)
-{
- for(size_t i=0; i<2; i++)
- {
+static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const* desc_ep) {
+ for (size_t i = 0; i < 2; i++) {
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType &&
- TUSB_XFER_BULK == desc_ep->bmAttributes.xfer);
-
+ TUSB_XFER_BULK == desc_ep->bmAttributes.xfer);
TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep));
- if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN )
- {
+ if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
tu_edpt_stream_open(&p_cdc->stream.rx, p_cdc->daddr, desc_ep);
- }else
- {
+ } else {
tu_edpt_stream_open(&p_cdc->stream.tx, p_cdc->daddr, desc_ep);
}
@@ -618,125 +730,130 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t c
return true;
}
-static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
-{
- uint8_t const * p_desc_end = ((uint8_t const*) itf_desc) + max_len;
+bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) {
+ (void) rhport;
- cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc);
- TU_VERIFY(p_cdc);
+ // For CDC: only support ACM subclass
+ // Note: Protocol 0xFF can be RNDIS device
+ if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
+ CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) {
+ return acm_open(daddr, itf_desc, max_len);
+ }
+ else if (SERIAL_DRIVER_COUNT > 1 &&
+ TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) {
+ uint16_t vid, pid;
+ TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid));
+
+ for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) {
+ cdch_serial_driver_t const* driver = &serial_drivers[dr];
+ for (size_t i = 0; i < driver->vid_pid_count; i++) {
+ if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) {
+ return driver->open(daddr, itf_desc, max_len);
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) {
+ TU_LOG_DRV("CDCh Set Configure complete\r\n");
+ p_cdc->mounted = true;
+ if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx);
+
+ // Prepare for incoming data
+ tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
+
+ // notify usbh that driver enumeration is complete
+ usbh_driver_set_config_complete(p_cdc->daddr, itf_num);
+}
+
+bool cdch_set_config(uint8_t daddr, uint8_t itf_num) {
+ tusb_control_request_t request;
+ request.wIndex = tu_htole16((uint16_t) itf_num);
+
+ // fake transfer to kick-off process
+ tuh_xfer_t xfer;
+ xfer.daddr = daddr;
+ xfer.result = XFER_RESULT_SUCCESS;
+ xfer.setup = &request;
+ xfer.user_data = 0; // initial state
- p_cdc->serial_protocol = SERIAL_PROTOCOL_ACM;
+ uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num);
+ cdch_interface_t * p_cdc = get_itf(idx);
+ TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT);
+
+ serial_drivers[p_cdc->serial_drid].process_set_config(&xfer);
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// ACM
+//--------------------------------------------------------------------+
+
+enum {
+ CONFIG_ACM_SET_CONTROL_LINE_STATE = 0,
+ CONFIG_ACM_SET_LINE_CODING,
+ CONFIG_ACM_COMPLETE,
+};
+
+static bool acm_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len) {
+ uint8_t const* p_desc_end = ((uint8_t const*) itf_desc) + max_len;
+
+ cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc);
+ TU_VERIFY(p_cdc);
+ p_cdc->serial_drid = SERIAL_DRIVER_ACM;
//------------- Control Interface -------------//
- uint8_t const * p_desc = tu_desc_next(itf_desc);
+ uint8_t const* p_desc = tu_desc_next(itf_desc);
// Communication Functional Descriptors
- while( (p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) )
- {
- if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) )
- {
+ while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) {
+ if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) {
// save ACM bmCapabilities
- p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities;
+ p_cdc->acm_capability = ((cdc_desc_func_acm_t const*) p_desc)->bmCapabilities;
}
p_desc = tu_desc_next(p_desc);
}
// Open notification endpoint of control interface if any
- if (itf_desc->bNumEndpoints == 1)
- {
+ if (itf_desc->bNumEndpoints == 1) {
TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc));
- tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc;
- TU_ASSERT( tuh_edpt_open(daddr, desc_ep) );
+ TU_ASSERT(tuh_edpt_open(daddr, desc_ep));
p_cdc->ep_notif = desc_ep->bEndpointAddress;
p_desc = tu_desc_next(p_desc);
}
//------------- Data Interface (if any) -------------//
- if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
- (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
- {
+ if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
+ (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) {
// next to endpoint descriptor
p_desc = tu_desc_next(p_desc);
// data endpoints expected to be in pairs
- TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc));
+ TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const*) p_desc));
}
return true;
}
-
-bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
-{
- (void) rhport;
-
- // Only support ACM subclass
- // Note: Protocol 0xFF can be RNDIS device
- if ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
- CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass)
- {
- return acm_open(daddr, itf_desc, max_len);
- }
- #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X
- else if ( 0xff == itf_desc->bInterfaceClass )
- {
- uint16_t vid, pid;
- TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid));
-
- #if CFG_TUH_CDC_FTDI
- if (TU_FTDI_VID == vid) {
- for (size_t i = 0; i < FTDI_PID_COUNT; i++) {
- if (ftdi_pids[i] == pid) {
- return ftdi_open(daddr, itf_desc, max_len);
- }
- }
- }
- #endif
-
- #if CFG_TUH_CDC_CP210X
- if (TU_CP210X_VID == vid) {
- for (size_t i = 0; i < CP210X_PID_COUNT; i++) {
- if (cp210x_pids[i] == pid) {
- return cp210x_open(daddr, itf_desc, max_len);
- }
- }
- }
- #endif
- }
- #endif
-
- return false;
-}
-
-static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) {
- if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx);
-
- // Prepare for incoming data
- tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
-
- // notify usbh that driver enumeration is complete
- usbh_driver_set_config_complete(p_cdc->daddr, itf_num);
-}
-
-static void process_acm_config(tuh_xfer_t* xfer)
-{
+static void acm_process_config(tuh_xfer_t* xfer) {
uintptr_t const state = xfer->user_data;
uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
- cdch_interface_t * p_cdc = get_itf(idx);
- TU_ASSERT(p_cdc, );
+ cdch_interface_t* p_cdc = get_itf(idx);
+ TU_ASSERT(p_cdc,);
- switch(state)
- {
+ switch (state) {
case CONFIG_ACM_SET_CONTROL_LINE_STATE:
#if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
- if (p_cdc->acm_capability.support_line_request)
- {
- TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, process_acm_config,
- CONFIG_ACM_SET_LINE_CODING), );
+ if (p_cdc->acm_capability.support_line_request) {
+ TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, acm_process_config, CONFIG_ACM_SET_LINE_CODING),);
break;
}
#endif
@@ -744,10 +861,9 @@ static void process_acm_config(tuh_xfer_t* xfer)
case CONFIG_ACM_SET_LINE_CODING:
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
- if (p_cdc->acm_capability.support_line_request)
- {
+ if (p_cdc->acm_capability.support_line_request) {
cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM;
- TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, process_acm_config, CONFIG_ACM_COMPLETE), );
+ TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE),);
break;
}
#endif
@@ -755,52 +871,98 @@ static void process_acm_config(tuh_xfer_t* xfer)
case CONFIG_ACM_COMPLETE:
// itf_num+1 to account for data interface as well
- set_config_complete(p_cdc, idx, itf_num+1);
- break;
+ set_config_complete(p_cdc, idx, itf_num + 1);
+ break;
- default: break;
+ default:
+ break;
}
}
-bool cdch_set_config(uint8_t daddr, uint8_t itf_num)
-{
- tusb_control_request_t request;
- request.wIndex = tu_htole16((uint16_t) itf_num);
+static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ TU_VERIFY(p_cdc->acm_capability.support_line_request);
+ TU_LOG_DRV("CDC ACM Set Control Line State\r\n");
- tuh_xfer_t xfer;
- xfer.daddr = daddr;
- xfer.result = XFER_RESULT_SUCCESS;
- xfer.setup = &request;
- xfer.user_data = 0;
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE,
+ .wValue = tu_htole16(line_state),
+ .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber),
+ .wLength = 0
+ };
- // fake transfer to kick-off process
- uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num);
- cdch_interface_t * p_cdc = get_itf(idx);
- TU_ASSERT(p_cdc);
+ p_cdc->user_control_cb = complete_cb;
- switch (p_cdc->serial_protocol) {
- case SERIAL_PROTOCOL_ACM:
- process_acm_config(&xfer);
- break;
+ tuh_xfer_t xfer = {
+ .daddr = p_cdc->daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = NULL,
+ .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call
+ .user_data = user_data
+ };
- #if CFG_TUH_CDC_FTDI
- case SERIAL_PROTOCOL_FTDI:
- process_ftdi_config(&xfer);
- break;
- #endif
+ TU_ASSERT(tuh_control_xfer(&xfer));
+ return true;
+}
- #if CFG_TUH_CDC_CP210X
- case SERIAL_PROTOCOL_CP210X:
- process_cp210x_config(&xfer);
- break;
- #endif
+static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ TU_LOG_DRV("CDC ACM Set Line Conding\r\n");
- default: return false;
- }
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = CDC_REQUEST_SET_LINE_CODING,
+ .wValue = 0,
+ .wIndex = tu_htole16(p_cdc->bInterfaceNumber),
+ .wLength = tu_htole16(sizeof(cdc_line_coding_t))
+ };
+
+ // use usbh enum buf to hold line coding since user line_coding variable does not live long enough
+ uint8_t* enum_buf = usbh_get_enum_buf();
+ memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t));
+
+ p_cdc->user_control_cb = complete_cb;
+ tuh_xfer_t xfer = {
+ .daddr = p_cdc->daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = enum_buf,
+ .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call
+ .user_data = user_data
+ };
+ TU_ASSERT(tuh_control_xfer(&xfer));
return true;
}
+static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ TU_LOG_DRV("CDC ACM Set Data Format\r\n");
+
+ cdc_line_coding_t line_coding;
+ line_coding.bit_rate = p_cdc->line_coding.bit_rate;
+ line_coding.stop_bits = stop_bits;
+ line_coding.parity = parity;
+ line_coding.data_bits = data_bits;
+
+ return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data);
+}
+
+static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ TU_VERIFY(p_cdc->acm_capability.support_line_request);
+ cdc_line_coding_t line_coding = p_cdc->line_coding;
+ line_coding.bit_rate = baudrate;
+ return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data);
+}
+
//--------------------------------------------------------------------+
// FTDI
//--------------------------------------------------------------------+
@@ -822,9 +984,8 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint
cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc);
TU_VERIFY(p_cdc);
- TU_LOG_CDCH("FTDI opened\r\n");
-
- p_cdc->serial_protocol = SERIAL_PROTOCOL_FTDI;
+ TU_LOG_DRV("FTDI opened\r\n");
+ p_cdc->serial_drid = SERIAL_DRIVER_FTDI;
// endpoint pair
tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc);
@@ -859,21 +1020,40 @@ static bool ftdi_sio_set_request(cdch_interface_t* p_cdc, uint8_t command, uint1
return tuh_control_xfer(&xfer);
}
-static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return ftdi_sio_set_request(p_cdc, FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, complete_cb, user_data);
}
-static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
- TU_LOG_CDCH("CDC FTDI Set Control Line State\r\n");
+static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ (void) p_cdc;
+ (void) stop_bits;
+ (void) parity;
+ (void) data_bits;
+ (void) complete_cb;
+ (void) user_data;
+ // TODO not implemented yet
+ return false;
+}
+
+static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ (void) p_cdc;
+ (void) line_coding;
+ (void) complete_cb;
+ (void) user_data;
+ // TODO not implemented yet
+ return false;
+}
+
+static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ TU_LOG_DRV("CDC FTDI Set Control Line State\r\n");
p_cdc->user_control_cb = complete_cb;
- TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, cdch_internal_control_complete, user_data));
+ TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state,
+ complete_cb ? cdch_internal_control_complete : NULL, user_data));
return true;
}
-static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base)
-{
+static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) {
const uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
uint32_t divisor;
@@ -893,22 +1073,23 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base)
return divisor;
}
-static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud)
-{
+static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) {
return ftdi_232bm_baud_base_to_divisor(baud, 48000000u);
}
-static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate);
- TU_LOG_CDCH("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\n", baudrate, divisor);
+ TU_LOG_DRV("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\r\n", baudrate, divisor);
p_cdc->user_control_cb = complete_cb;
- TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, cdch_internal_control_complete, user_data));
+ p_cdc->requested_line_coding.bit_rate = baudrate;
+ TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor,
+ complete_cb ? cdch_internal_control_complete : NULL, user_data));
+
return true;
}
-static void process_ftdi_config(tuh_xfer_t* xfer) {
+static void ftdi_process_config(tuh_xfer_t* xfer) {
uintptr_t const state = xfer->user_data;
uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
@@ -918,13 +1099,12 @@ static void process_ftdi_config(tuh_xfer_t* xfer) {
switch(state) {
// Note may need to read FTDI eeprom
case CONFIG_FTDI_RESET:
- TU_ASSERT(ftdi_sio_reset(p_cdc, process_ftdi_config, CONFIG_FTDI_MODEM_CTRL),);
+ TU_ASSERT(ftdi_sio_reset(p_cdc, ftdi_process_config, CONFIG_FTDI_MODEM_CTRL),);
break;
case CONFIG_FTDI_MODEM_CTRL:
#if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
- TU_ASSERT(
- ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, process_ftdi_config, CONFIG_FTDI_SET_BAUDRATE),);
+ TU_ASSERT(ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),);
break;
#else
TU_ATTR_FALLTHROUGH;
@@ -933,7 +1113,7 @@ static void process_ftdi_config(tuh_xfer_t* xfer) {
case CONFIG_FTDI_SET_BAUDRATE: {
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM;
- TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, line_coding.bit_rate, process_ftdi_config, CONFIG_FTDI_SET_DATA),);
+ TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, line_coding.bit_rate, ftdi_process_config, CONFIG_FTDI_SET_DATA),);
break;
#else
TU_ATTR_FALLTHROUGH;
@@ -985,8 +1165,8 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui
cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc);
TU_VERIFY(p_cdc);
- TU_LOG_CDCH("CP210x opened\r\n");
- p_cdc->serial_protocol = SERIAL_PROTOCOL_CP210X;
+ TU_LOG_DRV("CP210x opened\r\n");
+ p_cdc->serial_drid = SERIAL_DRIVER_CP210X;
// endpoint pair
tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc);
@@ -1032,20 +1212,43 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe
return cp210x_set_request(p_cdc, CP210X_IFC_ENABLE, enabled, NULL, 0, complete_cb, user_data);
}
+static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ // TODO implement later
+ (void) p_cdc;
+ (void) line_coding;
+ (void) complete_cb;
+ (void) user_data;
+ return false;
+}
+
static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
- TU_LOG_CDCH("CDC CP210x Set BaudRate = %lu\n", baudrate);
- baudrate = tu_htole32(baudrate);
- return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baudrate, 4, complete_cb, user_data);
+ TU_LOG_DRV("CDC CP210x Set BaudRate = %lu\r\n", baudrate);
+ uint32_t baud_le = tu_htole32(baudrate);
+ p_cdc->user_control_cb = complete_cb;
+ return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4,
+ complete_cb ? cdch_internal_control_complete : NULL, user_data);
}
-static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
- TU_LOG_CDCH("CDC CP210x Set Control Line State\r\n");
+static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ (void) p_cdc;
+ (void) stop_bits;
+ (void) parity;
+ (void) data_bits;
+ (void) complete_cb;
+ (void) user_data;
+ // TODO not implemented yet
+ return false;
+}
+
+static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ TU_LOG_DRV("CDC CP210x Set Control Line State\r\n");
p_cdc->user_control_cb = complete_cb;
- return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, cdch_internal_control_complete, user_data);
+ return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0,
+ complete_cb ? cdch_internal_control_complete : NULL, user_data);
}
-static void process_cp210x_config(tuh_xfer_t* xfer) {
+static void cp210x_process_config(tuh_xfer_t* xfer) {
uintptr_t const state = xfer->user_data;
uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
@@ -1054,13 +1257,13 @@ static void process_cp210x_config(tuh_xfer_t* xfer) {
switch (state) {
case CONFIG_CP210X_IFC_ENABLE:
- TU_ASSERT(cp210x_ifc_enable(p_cdc, 1, process_cp210x_config, CONFIG_CP210X_SET_BAUDRATE),);
+ TU_ASSERT(cp210x_ifc_enable(p_cdc, 1, cp210x_process_config, CONFIG_CP210X_SET_BAUDRATE),);
break;
case CONFIG_CP210X_SET_BAUDRATE: {
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM;
- TU_ASSERT(cp210x_set_baudrate(p_cdc, line_coding.bit_rate, process_cp210x_config, CONFIG_CP210X_SET_LINE_CTL),);
+ TU_ASSERT(cp210x_set_baudrate(p_cdc, line_coding.bit_rate, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL),);
break;
#else
TU_ATTR_FALLTHROUGH;
@@ -1078,7 +1281,7 @@ static void process_cp210x_config(tuh_xfer_t* xfer) {
case CONFIG_CP210X_SET_DTR_RTS:
#if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
- TU_ASSERT(cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, process_cp210x_config, CONFIG_CP210X_COMPLETE),);
+ TU_ASSERT(cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, cp210x_process_config, CONFIG_CP210X_COMPLETE),);
break;
#else
TU_ATTR_FALLTHROUGH;
@@ -1094,4 +1297,374 @@ static void process_cp210x_config(tuh_xfer_t* xfer) {
#endif
+//--------------------------------------------------------------------+
+// CH34x (CH340 & CH341)
+//--------------------------------------------------------------------+
+
+#if CFG_TUH_CDC_CH34X
+
+static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits);
+static uint16_t ch34x_get_divisor_prescaler(uint32_t baval);
+
+//------------- control request -------------//
+
+static bool ch34x_set_request(cdch_interface_t* p_cdc, uint8_t direction, uint8_t request, uint16_t value,
+ uint16_t index, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ tusb_control_request_t const request_setup = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_VENDOR,
+ .direction = direction & 0x01u
+ },
+ .bRequest = request,
+ .wValue = tu_htole16 (value),
+ .wIndex = tu_htole16 (index),
+ .wLength = tu_htole16 (length)
+ };
+
+ // use usbh enum buf since application variable does not live long enough
+ uint8_t* enum_buf = NULL;
+
+ if (buffer && length > 0) {
+ enum_buf = usbh_get_enum_buf();
+ if (direction == TUSB_DIR_OUT) {
+ tu_memcpy_s(enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length);
+ }
+ }
+
+ tuh_xfer_t xfer = {
+ .daddr = p_cdc->daddr,
+ .ep_addr = 0,
+ .setup = &request_setup,
+ .buffer = enum_buf,
+ .complete_cb = complete_cb,
+ .user_data = user_data
+ };
+
+ return tuh_control_xfer(&xfer);
+}
+
+static inline bool ch34x_control_out(cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ return ch34x_set_request(p_cdc, TUSB_DIR_OUT, request, value, index, NULL, 0, complete_cb, user_data);
+}
+
+static inline bool ch34x_control_in(cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index,
+ uint8_t* buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ return ch34x_set_request(p_cdc, TUSB_DIR_IN, request, value, index, buffer, buffersize,
+ complete_cb, user_data);
+}
+
+static inline bool ch34x_write_reg(cdch_interface_t* p_cdc, uint16_t reg, uint16_t reg_value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ return ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, reg, reg_value, complete_cb, user_data);
+}
+
+//static bool ch34x_read_reg_request ( cdch_interface_t* p_cdc, uint16_t reg,
+// uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data )
+//{
+// return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data );
+//}
+
+static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ uint16_t const div_ps = ch34x_get_divisor_prescaler(baudrate);
+ TU_VERIFY(div_ps);
+ TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps,
+ complete_cb, user_data));
+ return true;
+}
+
+//------------- Driver API -------------//
+
+// internal control complete to update state such as line state, encoding
+static void ch34x_control_complete(tuh_xfer_t* xfer) {
+ // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber
+ process_internal_control_complete(xfer, 0);
+}
+
+static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ p_cdc->requested_line_coding.stop_bits = stop_bits;
+ p_cdc->requested_line_coding.parity = parity;
+ p_cdc->requested_line_coding.data_bits = data_bits;
+
+ uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits);
+ TU_VERIFY(lcr);
+ TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr,
+ complete_cb ? ch34x_control_complete : NULL, user_data));
+ return true;
+}
+
+static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ p_cdc->requested_line_coding.bit_rate = baudrate;
+ p_cdc->user_control_cb = complete_cb;
+ TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate,
+ complete_cb ? ch34x_control_complete : NULL, user_data));
+ return true;
+}
+
+static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) {
+ // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber
+ uint8_t const itf_num = 0;
+ uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
+ cdch_interface_t* p_cdc = get_itf(idx);
+ TU_ASSERT(p_cdc, );
+
+ if (xfer->result == XFER_RESULT_SUCCESS) {
+ // stage 1 success, continue to stage 2
+ p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate;
+ TU_ASSERT(ch34x_set_data_format(p_cdc, p_cdc->requested_line_coding.stop_bits, p_cdc->requested_line_coding.parity,
+ p_cdc->requested_line_coding.data_bits, ch34x_control_complete, xfer->user_data), );
+ } else {
+ // stage 1 failed, notify user
+ xfer->complete_cb = p_cdc->user_control_cb;
+ if (xfer->complete_cb) {
+ xfer->complete_cb(xfer);
+ }
+ }
+}
+
+// 2 stages: set baudrate (stage1) + set data format (stage2)
+static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ p_cdc->requested_line_coding = *line_coding;
+ p_cdc->user_control_cb = complete_cb;
+
+ if (complete_cb) {
+ // stage 1 set baudrate
+ TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate,
+ ch34x_set_line_coding_stage1_complete, user_data));
+ } else {
+ // sync call
+ xfer_result_t result;
+
+ // stage 1 set baudrate
+ TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, NULL, (uintptr_t) &result));
+ TU_VERIFY(result == XFER_RESULT_SUCCESS);
+ p_cdc->line_coding.bit_rate = line_coding->bit_rate;
+
+ // stage 2 set data format
+ TU_ASSERT(ch34x_set_data_format(p_cdc, line_coding->stop_bits, line_coding->parity, line_coding->data_bits,
+ NULL, (uintptr_t) &result));
+ TU_VERIFY(result == XFER_RESULT_SUCCESS);
+ p_cdc->line_coding.stop_bits = line_coding->stop_bits;
+ p_cdc->line_coding.parity = line_coding->parity;
+ p_cdc->line_coding.data_bits = line_coding->data_bits;
+
+ // update transfer result, user_data is expected to point to xfer_result_t
+ if (user_data) {
+ *((xfer_result_t*) user_data) = result;
+ }
+ }
+
+ return true;
+}
+
+static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ uint8_t control = 0;
+ if (line_state & CDC_CONTROL_LINE_STATE_RTS) {
+ control |= CH34X_BIT_RTS;
+ }
+ if (line_state & CDC_CONTROL_LINE_STATE_DTR) {
+ control |= CH34X_BIT_DTR;
+ }
+
+ // CH34x signals are inverted
+ control = ~control;
+
+ p_cdc->user_control_cb = complete_cb;
+ TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0,
+ complete_cb ? ch34x_control_complete : NULL, user_data));
+ return true;
+}
+
+//------------- Enumeration -------------//
+enum {
+ CONFIG_CH34X_READ_VERSION = 0,
+ CONFIG_CH34X_SERIAL_INIT,
+ CONFIG_CH34X_SPECIAL_REG_WRITE,
+ CONFIG_CH34X_FLOW_CONTROL,
+ CONFIG_CH34X_MODEM_CONTROL,
+ CONFIG_CH34X_COMPLETE
+};
+
+static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len) {
+ // CH34x Interface includes 1 vendor interface + 2 bulk + 1 interrupt endpoints
+ TU_VERIFY (itf_desc->bNumEndpoints == 3);
+ TU_VERIFY (sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len);
+
+ cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc);
+ TU_VERIFY (p_cdc);
+
+ TU_LOG_DRV ("CH34x opened\r\n");
+ p_cdc->serial_drid = SERIAL_DRIVER_CH34X;
+
+ tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(itf_desc);
+
+ // data endpoints expected to be in pairs
+ TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep));
+ desc_ep += 2;
+
+ // Interrupt endpoint: not used for now
+ TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) &&
+ TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer);
+ TU_ASSERT(tuh_edpt_open(daddr, desc_ep));
+ p_cdc->ep_notif = desc_ep->bEndpointAddress;
+
+ return true;
+}
+
+static void ch34x_process_config(tuh_xfer_t* xfer) {
+ // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber
+ uint8_t const itf_num = 0;
+ uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num);
+ cdch_interface_t* p_cdc = get_itf(idx);
+ uintptr_t const state = xfer->user_data;
+ uint8_t buffer[2]; // TODO remove
+ TU_ASSERT (p_cdc,);
+ TU_ASSERT (xfer->result == XFER_RESULT_SUCCESS,);
+
+ switch (state) {
+ case CONFIG_CH34X_READ_VERSION:
+ TU_LOG_DRV("[%u] CDCh CH34x attempt to read Chip Version\r\n", p_cdc->daddr);
+ TU_ASSERT (ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, ch34x_process_config, CONFIG_CH34X_SERIAL_INIT),);
+ break;
+
+ case CONFIG_CH34X_SERIAL_INIT: {
+ // handle version read data, set CH34x line coding (incl. baudrate)
+ uint8_t const version = xfer->buffer[0];
+ TU_LOG_DRV("[%u] CDCh CH34x Chip Version = %02x\r\n", p_cdc->daddr, version);
+ // only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD
+ TU_ASSERT (version >= 0x30,);
+ // init CH34x with line coding
+ cdc_line_coding_t const line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X;
+ uint16_t const div_ps = ch34x_get_divisor_prescaler(line_coding.bit_rate);
+ TU_ASSERT(div_ps, );
+ uint8_t const lcr = ch34x_get_lcr(line_coding.stop_bits, line_coding.parity, line_coding.data_bits);
+ TU_ASSERT(lcr, );
+ TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps,
+ ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE),);
+ break;
+ }
+
+ case CONFIG_CH34X_SPECIAL_REG_WRITE:
+ // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver
+ p_cdc->line_coding = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X);
+ TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL),);
+ break;
+
+ case CONFIG_CH34X_FLOW_CONTROL:
+ // no hardware flow control
+ TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL),);
+ break;
+
+ case CONFIG_CH34X_MODEM_CONTROL:
+ // !always! set modem controls RTS/DTR (CH34x has no reset state after CH34X_REQ_SERIAL_INIT)
+ TU_ASSERT (ch34x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ch34x_process_config, CONFIG_CH34X_COMPLETE),);
+ break;
+
+ case CONFIG_CH34X_COMPLETE:
+ set_config_complete(p_cdc, idx, itf_num);
+ break;
+
+ default:
+ TU_ASSERT (false,);
+ break;
+ }
+}
+
+//------------- CH34x helper -------------//
+
+// calculate divisor and prescaler for baudrate, return it as 16-bit combined value
+static uint16_t ch34x_get_divisor_prescaler(uint32_t baval) {
+ uint8_t a;
+ uint8_t b;
+ uint32_t c;
+
+ TU_VERIFY(baval != 0 && baval <= 2000000, 0);
+ switch (baval) {
+ case 921600:
+ a = 0xf3;
+ b = 7;
+ break;
+
+ case 307200:
+ a = 0xd9;
+ b = 7;
+ break;
+
+ default:
+ if (baval > 6000000 / 255) {
+ b = 3;
+ c = 6000000;
+ } else if (baval > 750000 / 255) {
+ b = 2;
+ c = 750000;
+ } else if (baval > 93750 / 255) {
+ b = 1;
+ c = 93750;
+ } else {
+ b = 0;
+ c = 11719;
+ }
+ a = (uint8_t) (c / baval);
+ if (a == 0 || a == 0xFF) {
+ return 0;
+ }
+ if ((c / a - baval) > (baval - c / (a + 1))) {
+ a++;
+ }
+ a = (uint8_t) (256 - a);
+ break;
+ }
+
+ // reg divisor = a, reg prescaler = b
+ // According to linux code we need to set bit 7 of UCHCOM_REG_BPS_PRE,
+ // otherwise the chip will buffer data.
+ return (uint16_t) ((uint16_t)a << 8 | 0x80 | b);
+}
+
+// calculate lcr value from data coding
+static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits) {
+ uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX;
+ TU_VERIFY(data_bits >= 5 && data_bits <= 8, 0);
+ lcr |= (uint8_t) (data_bits - 5);
+
+ switch(parity) {
+ case CDC_LINE_CODING_PARITY_NONE:
+ break;
+
+ case CDC_LINE_CODING_PARITY_ODD:
+ lcr |= CH34X_LCR_ENABLE_PAR;
+ break;
+
+ case CDC_LINE_CODING_PARITY_EVEN:
+ lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_PAR_EVEN;
+ break;
+
+ case CDC_LINE_CODING_PARITY_MARK:
+ lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE;
+ break;
+
+ case CDC_LINE_CODING_PARITY_SPACE:
+ lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE | CH34X_LCR_PAR_EVEN;
+ break;
+
+ default: break;
+ }
+
+ // 1.5 stop bits not supported
+ TU_VERIFY(stop_bits != CDC_LINE_CODING_STOP_BITS_1_5, 0);
+ if (stop_bits == CDC_LINE_CODING_STOP_BITS_2) {
+ lcr |= CH34X_LCR_STOP_BITS_2;
+ }
+
+ return lcr;
+}
+
+
+#endif // CFG_TUH_CDC_CH34X
+
#endif
diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h
index 971ebe2ae..b63dd1530 100644
--- a/src/class/cdc/cdc_host.h
+++ b/src/class/cdc/cdc_host.h
@@ -44,7 +44,7 @@
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
//#ifndef CFG_TUH_CDC_LINE_CODING_ON_ENUM
-//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
+//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
//#endif
// RX FIFO size
@@ -134,7 +134,12 @@ bool tuh_cdc_read_clear (uint8_t idx);
//--------------------------------------------------------------------+
// Control Endpoint (Request) API
-// Each Function will make a USB transfer request to/from device
+// Each Function will make a USB control transfer request to/from device
+// - If complete_cb is provided, the function will return immediately and invoke
+// the callback when request is complete.
+// - If complete_cb is NULL, the function will block until request is complete.
+// - In this case, user_data should be pointed to xfer_result_t to hold the transfer result.
+// - The function will return true if transfer is successful, false otherwise.
//--------------------------------------------------------------------+
// Request to Set Control Line State: DTR (bit 0), RTS (bit 1)
@@ -143,7 +148,11 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c
// Request to set baudrate
bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
-// Request to Set Line Coding (ACM only)
+// Request to set data format
+bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+
+// Request to Set Line Coding = baudrate + data format
+// Note: only implemented by ACM and CH34x, not supported by FTDI and CP210x yet
bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Request to Get Line Coding (ACM only)
@@ -153,15 +162,13 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding,
// Connect by set both DTR, RTS
TU_ATTR_ALWAYS_INLINE static inline
-bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data);
}
// Disconnect by clear both DTR, RTS
TU_ATTR_ALWAYS_INLINE static inline
-bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return tuh_cdc_set_control_line_state(idx, 0x00, complete_cb, user_data);
}
@@ -185,7 +192,8 @@ TU_ATTR_WEAK extern void tuh_cdc_tx_complete_cb(uint8_t idx);
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
-void cdch_init (void);
+bool cdch_init (void);
+bool cdch_deinit (void);
bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num);
bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
diff --git a/src/class/cdc/serial/ch34x.h b/src/class/cdc/serial/ch34x.h
new file mode 100644
index 000000000..c18066f57
--- /dev/null
+++ b/src/class/cdc/serial/ch34x.h
@@ -0,0 +1,84 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Heiko Kuester
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _CH34X_H_
+#define _CH34X_H_
+
+// There is no official documentation for the CH34x (CH340, CH341) chips. Reference can be found
+// - https://github.com/WCHSoftGroup/ch341ser_linux
+// - https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.c
+// - https://github.com/freebsd/freebsd-src/blob/main/sys/dev/usb/serial/uchcom.c
+
+// set line_coding @ enumeration
+#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
+#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X CFG_TUH_CDC_LINE_CODING_ON_ENUM
+#else // this default is necessary to work properly
+#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X { 9600, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
+#endif
+
+// USB requests
+#define CH34X_REQ_READ_VERSION 0x5F // dec 95
+#define CH34X_REQ_WRITE_REG 0x9A // dec 154
+#define CH34X_REQ_READ_REG 0x95 // dec 149
+#define CH34X_REQ_SERIAL_INIT 0xA1 // dec 161
+#define CH34X_REQ_MODEM_CTRL 0xA4 // dev 164
+
+// registers
+#define CH34X_REG_BREAK 0x05
+#define CH34X_REG_PRESCALER 0x12
+#define CH34X_REG_DIVISOR 0x13
+#define CH34X_REG_LCR 0x18
+#define CH34X_REG_LCR2 0x25
+#define CH34X_REG_MCR_MSR 0x06
+#define CH34X_REG_MCR_MSR2 0x07
+#define CH34X_NBREAK_BITS 0x01
+
+#define CH341_REG_0x0F 0x0F // undocumented register
+#define CH341_REG_0x2C 0x2C // undocumented register
+#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts)
+
+#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER)
+#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR)
+
+// modem control bits
+#define CH34X_BIT_RTS ( 1 << 6 )
+#define CH34X_BIT_DTR ( 1 << 5 )
+
+// line control bits
+#define CH34X_LCR_ENABLE_RX 0x80
+#define CH34X_LCR_ENABLE_TX 0x40
+#define CH34X_LCR_MARK_SPACE 0x20
+#define CH34X_LCR_PAR_EVEN 0x10
+#define CH34X_LCR_ENABLE_PAR 0x08
+#define CH34X_LCR_PAR_MASK 0x38 // all parity bits
+#define CH34X_LCR_STOP_BITS_2 0x04
+#define CH34X_LCR_CS8 0x03
+#define CH34X_LCR_CS7 0x02
+#define CH34X_LCR_CS6 0x01
+#define CH34X_LCR_CS5 0x00
+#define CH34X_LCR_CS_MASK 0x03 // all CSx bits
+
+#endif /* _CH34X_H_ */
diff --git a/src/class/cdc/serial/cp210x.h b/src/class/cdc/serial/cp210x.h
index b01417092..2c749f522 100644
--- a/src/class/cdc/serial/cp210x.h
+++ b/src/class/cdc/serial/cp210x.h
@@ -29,8 +29,6 @@
// https://www.silabs.com/documents/public/application-notes/AN571.pdf
#define TU_CP210X_VID 0x10C4
-#define TU_CP210X_PID_LIST \
- 0xEA60, 0xEA70
/* Config request codes */
#define CP210X_IFC_ENABLE 0x00
diff --git a/src/class/cdc/serial/ftdi_sio.h b/src/class/cdc/serial/ftdi_sio.h
index 6916e4031..0825f0719 100644
--- a/src/class/cdc/serial/ftdi_sio.h
+++ b/src/class/cdc/serial/ftdi_sio.h
@@ -25,11 +25,8 @@
#ifndef TUSB_FTDI_SIO_H
#define TUSB_FTDI_SIO_H
-// VID/PID for matching FTDI devices
+// VID for matching FTDI devices
#define TU_FTDI_VID 0x0403
-#define TU_FTDI_PID_LIST \
- 0x6001, 0x6006, 0x6010, 0x6011, 0x6014, 0x6015, 0x8372, 0xFBFA, \
- 0xcd18
// Commands
#define FTDI_SIO_RESET 0 /* Reset the port */
diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c
index 464c4bd6b..71e7ac2b3 100644
--- a/src/class/dfu/dfu_device.c
+++ b/src/class/dfu/dfu_device.c
@@ -37,6 +37,13 @@
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUD_DFU_LOG_LEVEL
+ #define CFG_TUD_DFU_LOG_LEVEL CFG_TUD_LOG_LEVEL
+#endif
+
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_DFU_LOG_LEVEL, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
@@ -56,7 +63,7 @@ typedef struct
} dfu_state_ctx_t;
// Only a single dfu state is allowed
-CFG_TUSB_MEM_SECTION tu_static dfu_state_ctx_t _dfu_ctx;
+CFG_TUD_MEM_SECTION tu_static dfu_state_ctx_t _dfu_ctx;
static void reset_state(void)
{
@@ -153,11 +160,14 @@ void dfu_moded_reset(uint8_t rhport)
reset_state();
}
-void dfu_moded_init(void)
-{
+void dfu_moded_init(void) {
dfu_moded_reset(0);
}
+bool dfu_moded_deinit(void) {
+ return true;
+}
+
uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
(void) rhport;
@@ -205,7 +215,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque
{
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
- TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status));
+ TU_LOG_DRV(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status));
if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD )
{
@@ -235,7 +245,7 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque
}
else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS )
{
- TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest));
+ TU_LOG_DRV(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest));
// Class request
switch ( request->bRequest )
diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h
index fecf8596f..00c22ea8b 100644
--- a/src/class/dfu/dfu_device.h
+++ b/src/class/dfu/dfu_device.h
@@ -86,6 +86,7 @@ TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt);
// Internal Class Driver API
//--------------------------------------------------------------------+
void dfu_moded_init(void);
+bool dfu_moded_deinit(void);
void dfu_moded_reset(uint8_t rhport);
uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c
index 7b77b3f8f..3b801b787 100644
--- a/src/class/dfu/dfu_rt_device.c
+++ b/src/class/dfu/dfu_rt_device.c
@@ -37,6 +37,13 @@
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUD_DFU_RUNTIME_LOG_LEVEL
+ #define CFG_TUD_DFU_RUNTIME_LOG_LEVEL CFG_TUD_LOG_LEVEL
+#endif
+
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_DFU_RUNTIME_LOG_LEVEL, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
@@ -44,8 +51,11 @@
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void dfu_rtd_init(void)
-{
+void dfu_rtd_init(void) {
+}
+
+bool dfu_rtd_deinit(void) {
+ return true;
}
void dfu_rtd_reset(uint8_t rhport)
@@ -99,7 +109,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
{
case DFU_REQUEST_DETACH:
{
- TU_LOG2(" DFU RT Request: DETACH\r\n");
+ TU_LOG_DRV(" DFU RT Request: DETACH\r\n");
tud_control_status(rhport, request);
tud_dfu_runtime_reboot_to_dfu_cb();
}
@@ -107,7 +117,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
case DFU_REQUEST_GETSTATUS:
{
- TU_LOG2(" DFU RT Request: GETSTATUS\r\n");
+ TU_LOG_DRV(" DFU RT Request: GETSTATUS\r\n");
dfu_status_response_t resp;
// Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0
TU_VERIFY(tu_memset_s(&resp, sizeof(resp), 0x00, sizeof(resp))==0);
@@ -117,7 +127,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
default:
{
- TU_LOG2(" DFU RT Unexpected Request: %d\r\n", request->bRequest);
+ TU_LOG_DRV(" DFU RT Unexpected Request: %d\r\n", request->bRequest);
return false; // stall unsupported request
}
}
diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h
index babaa8214..67eb26d95 100644
--- a/src/class/dfu/dfu_rt_device.h
+++ b/src/class/dfu/dfu_rt_device.h
@@ -43,6 +43,7 @@ void tud_dfu_runtime_reboot_to_dfu_cb(void);
// Internal Class Driver API
//--------------------------------------------------------------------+
void dfu_rtd_init(void);
+bool dfu_rtd_deinit(void);
void dfu_rtd_reset(uint8_t rhport);
uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h
index fbd3eef38..fcaab7a50 100644
--- a/src/class/hid/hid.h
+++ b/src/class/hid/hid.h
@@ -300,6 +300,19 @@ typedef struct TU_ATTR_PACKED
int8_t pan; // using AC Pan
} hid_mouse_report_t;
+
+// Absolute Mouse: same as the Standard (relative) Mouse Report but
+// with int16_t instead of int8_t for X and Y coordinates.
+typedef struct TU_ATTR_PACKED
+{
+ uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
+ int16_t x; /**< Current x position of the mouse. */
+ int16_t y; /**< Current y position of the mouse. */
+ int8_t wheel; /**< Current delta wheel movement on the mouse. */
+ int8_t pan; // using AC Pan
+} hid_abs_mouse_report_t;
+
+
/// Standard Mouse Buttons Bitmap
typedef enum
{
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index 9240fe2ca..5cc5a2488 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -58,7 +58,7 @@ typedef struct
tusb_hid_descriptor_hid_t const * hid_descriptor;
} hidd_interface_t;
-CFG_TUSB_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID];
+CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID];
/*------------- Helpers -------------*/
static inline uint8_t get_index_by_itfnum(uint8_t itf_num)
@@ -146,6 +146,19 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id,
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
}
+bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal)
+{
+ hid_abs_mouse_report_t report =
+ {
+ .buttons = buttons,
+ .x = x,
+ .y = y,
+ .wheel = vertical,
+ .pan = horizontal
+ };
+ return tud_hid_n_report(instance, report_id, &report, sizeof(report));
+}
+
bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id,
int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) {
hid_gamepad_report_t report =
@@ -166,11 +179,14 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id,
//--------------------------------------------------------------------+
// USBD-CLASS API
//--------------------------------------------------------------------+
-void hidd_init(void)
-{
+void hidd_init(void) {
hidd_reset(0);
}
+bool hidd_deinit(void) {
+ return true;
+}
+
void hidd_reset(uint8_t rhport)
{
(void) rhport;
diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h
index 17b24def1..040cad162 100644
--- a/src/class/hid/hid_device.h
+++ b/src/class/hid/hid_device.h
@@ -72,6 +72,16 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi
// use template layout report as defined by hid_mouse_report_t
bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal);
+// ABSOLUTE MOUSE: convenient helper to send absolute mouse report if application
+// use template layout report as defined by hid_abs_mouse_report_t
+bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal);
+
+
+static inline bool tud_hid_abs_mouse_report(uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal)
+{
+ return tud_hid_n_abs_mouse_report(0, report_id, buttons, x, y, vertical, horizontal);
+}
+
// Gamepad: convenient helper to send gamepad report if application
// use template layout report TUD_HID_REPORT_DESC_GAMEPAD
bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons);
@@ -266,6 +276,55 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y
HID_COLLECTION_END , \
HID_COLLECTION_END \
+// Absolute Mouse Report Descriptor Template
+#define TUD_HID_REPORT_DESC_ABSMOUSE(...) \
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
+ HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\
+ HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
+ /* Report ID if any */\
+ __VA_ARGS__ \
+ HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\
+ HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
+ HID_USAGE_MIN ( 1 ) ,\
+ HID_USAGE_MAX ( 5 ) ,\
+ HID_LOGICAL_MIN ( 0 ) ,\
+ HID_LOGICAL_MAX ( 1 ) ,\
+ /* Left, Right, Middle, Backward, Forward buttons */ \
+ HID_REPORT_COUNT( 5 ) ,\
+ HID_REPORT_SIZE ( 1 ) ,\
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
+ /* 3 bit padding */ \
+ HID_REPORT_COUNT( 1 ) ,\
+ HID_REPORT_SIZE ( 3 ) ,\
+ HID_INPUT ( HID_CONSTANT ) ,\
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
+ /* X, Y absolute position [0, 32767] */ \
+ HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
+ HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
+ HID_LOGICAL_MIN ( 0x00 ) ,\
+ HID_LOGICAL_MAX_N( 0x7FFF, 2 ) ,\
+ HID_REPORT_SIZE ( 16 ) ,\
+ HID_REPORT_COUNT ( 2 ) ,\
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
+ /* Vertical wheel scroll [-127, 127] */ \
+ HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\
+ HID_LOGICAL_MIN ( 0x81 ) ,\
+ HID_LOGICAL_MAX ( 0x7f ) ,\
+ HID_REPORT_COUNT( 1 ) ,\
+ HID_REPORT_SIZE ( 8 ) ,\
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \
+ /* Horizontal wheel scroll [-127, 127] */ \
+ HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \
+ HID_LOGICAL_MIN ( 0x81 ), \
+ HID_LOGICAL_MAX ( 0x7f ), \
+ HID_REPORT_COUNT( 1 ), \
+ HID_REPORT_SIZE ( 8 ), \
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \
+ HID_COLLECTION_END , \
+ HID_COLLECTION_END \
+
// Consumer Control Report Descriptor Template
#define TUD_HID_REPORT_DESC_CONSUMER(...) \
HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ) ,\
@@ -406,6 +465,7 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y
// Internal Class Driver API
//--------------------------------------------------------------------+
void hidd_init (void);
+bool hidd_deinit (void);
void hidd_reset (uint8_t rhport);
uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index d95d3ef35..621fb2a55 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -29,26 +29,32 @@
#if (CFG_TUH_ENABLED && CFG_TUH_HID)
#include "host/usbh.h"
-#include "host/usbh_classdriver.h"
+#include "host/usbh_pvt.h"
#include "hid_host.h"
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUH_HID_LOG_LEVEL
+ #define CFG_TUH_HID_LOG_LEVEL CFG_TUH_LOG_LEVEL
+#endif
+
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_HID_LOG_LEVEL, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-
-typedef struct
-{
+typedef struct {
uint8_t daddr;
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out;
+ bool mounted; // Enumeration is complete
uint8_t itf_protocol; // None, Keyboard, Mouse
uint8_t protocol_mode; // Boot (0) or Report protocol (1)
- uint8_t report_desc_type;
+ uint8_t report_desc_type;
uint16_t report_desc_len;
uint16_t epin_size;
@@ -61,81 +67,62 @@ typedef struct
CFG_TUH_MEM_SECTION
tu_static hidh_interface_t _hidh_itf[CFG_TUH_HID];
+tu_static uint8_t _hidh_default_protocol = HID_PROTOCOL_BOOT;
+
//--------------------------------------------------------------------+
// Helper
//--------------------------------------------------------------------+
-
-TU_ATTR_ALWAYS_INLINE static inline
-hidh_interface_t* get_hid_itf(uint8_t daddr, uint8_t idx)
-{
- TU_ASSERT(daddr && idx < CFG_TUH_HID, NULL);
+TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_hid_itf(uint8_t daddr, uint8_t idx) {
+ TU_ASSERT(daddr > 0 && idx < CFG_TUH_HID, NULL);
hidh_interface_t* p_hid = &_hidh_itf[idx];
return (p_hid->daddr == daddr) ? p_hid : NULL;
}
// Get instance ID by endpoint address
-static uint8_t get_idx_by_epaddr(uint8_t daddr, uint8_t ep_addr)
-{
- for ( uint8_t idx = 0; idx < CFG_TUH_HID; idx++ )
- {
- hidh_interface_t const * p_hid = &_hidh_itf[idx];
-
- if ( p_hid->daddr == daddr &&
- (p_hid->ep_in == ep_addr || p_hid->ep_out == ep_addr) )
- {
+static uint8_t get_idx_by_epaddr(uint8_t daddr, uint8_t ep_addr) {
+ for (uint8_t idx = 0; idx < CFG_TUH_HID; idx++) {
+ hidh_interface_t const* p_hid = &_hidh_itf[idx];
+ if (p_hid->daddr == daddr &&
+ (p_hid->ep_in == ep_addr || p_hid->ep_out == ep_addr)) {
return idx;
}
}
-
return TUSB_INDEX_INVALID_8;
}
-static hidh_interface_t* find_new_itf(void)
-{
- for(uint8_t i=0; i<CFG_TUH_HID; i++)
- {
+static hidh_interface_t* find_new_itf(void) {
+ for (uint8_t i = 0; i < CFG_TUH_HID; i++) {
if (_hidh_itf[i].daddr == 0) return &_hidh_itf[i];
}
-
return NULL;
}
//--------------------------------------------------------------------+
// Interface API
//--------------------------------------------------------------------+
-
-uint8_t tuh_hid_itf_get_count(uint8_t daddr)
-{
+uint8_t tuh_hid_itf_get_count(uint8_t daddr) {
uint8_t count = 0;
-
- for(uint8_t i=0; i<CFG_TUH_HID; i++)
- {
+ for (uint8_t i = 0; i < CFG_TUH_HID; i++) {
if (_hidh_itf[i].daddr == daddr) count++;
}
-
return count;
}
-uint8_t tuh_hid_itf_get_total_count(void)
-{
+uint8_t tuh_hid_itf_get_total_count(void) {
uint8_t count = 0;
-
- for(uint8_t i=0; i<CFG_TUH_HID; i++)
- {
+ for (uint8_t i = 0; i < CFG_TUH_HID; i++) {
if (_hidh_itf[i].daddr != 0) count++;
}
-
return count;
}
-bool tuh_hid_mounted(uint8_t daddr, uint8_t idx)
-{
+bool tuh_hid_mounted(uint8_t daddr, uint8_t idx) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
- return p_hid != NULL;
+ TU_VERIFY(p_hid);
+ return p_hid->mounted;
}
-bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* info)
-{
+bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* info) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
TU_VERIFY(p_hid && info);
@@ -143,34 +130,30 @@ bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* info)
// re-construct descriptor
tusb_desc_interface_t* desc = &info->desc;
- desc->bLength = sizeof(tusb_desc_interface_t);
- desc->bDescriptorType = TUSB_DESC_INTERFACE;
+ desc->bLength = sizeof(tusb_desc_interface_t);
+ desc->bDescriptorType = TUSB_DESC_INTERFACE;
- desc->bInterfaceNumber = p_hid->itf_num;
- desc->bAlternateSetting = 0;
- desc->bNumEndpoints = (uint8_t) ((p_hid->ep_in ? 1u : 0u) + (p_hid->ep_out ? 1u : 0u));
- desc->bInterfaceClass = TUSB_CLASS_HID;
+ desc->bInterfaceNumber = p_hid->itf_num;
+ desc->bAlternateSetting = 0;
+ desc->bNumEndpoints = (uint8_t) ((p_hid->ep_in ? 1u : 0u) + (p_hid->ep_out ? 1u : 0u));
+ desc->bInterfaceClass = TUSB_CLASS_HID;
desc->bInterfaceSubClass = (p_hid->itf_protocol ? HID_SUBCLASS_BOOT : HID_SUBCLASS_NONE);
desc->bInterfaceProtocol = p_hid->itf_protocol;
- desc->iInterface = 0; // not used yet
+ desc->iInterface = 0; // not used yet
return true;
}
-uint8_t tuh_hid_itf_get_index(uint8_t daddr, uint8_t itf_num)
-{
- for ( uint8_t idx = 0; idx < CFG_TUH_HID; idx++ )
- {
- hidh_interface_t const * p_hid = &_hidh_itf[idx];
-
- if ( p_hid->daddr == daddr && p_hid->itf_num == itf_num) return idx;
+uint8_t tuh_hid_itf_get_index(uint8_t daddr, uint8_t itf_num) {
+ for (uint8_t idx = 0; idx < CFG_TUH_HID; idx++) {
+ hidh_interface_t const* p_hid = &_hidh_itf[idx];
+ if (p_hid->daddr == daddr && p_hid->itf_num == itf_num) return idx;
}
return TUSB_INDEX_INVALID_8;
}
-uint8_t tuh_hid_interface_protocol(uint8_t daddr, uint8_t idx)
-{
+uint8_t tuh_hid_interface_protocol(uint8_t daddr, uint8_t idx) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
return p_hid ? p_hid->itf_protocol : 0;
}
@@ -178,150 +161,135 @@ uint8_t tuh_hid_interface_protocol(uint8_t daddr, uint8_t idx)
//--------------------------------------------------------------------+
// Control Endpoint API
//--------------------------------------------------------------------+
-
-uint8_t tuh_hid_get_protocol(uint8_t daddr, uint8_t idx)
-{
+uint8_t tuh_hid_get_protocol(uint8_t daddr, uint8_t idx) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
return p_hid ? p_hid->protocol_mode : 0;
}
-static void set_protocol_complete(tuh_xfer_t* xfer)
-{
+static void set_protocol_complete(tuh_xfer_t* xfer) {
uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
- uint8_t const daddr = xfer->daddr;
- uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num);
+ uint8_t const daddr = xfer->daddr;
+ uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num);
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
- TU_VERIFY(p_hid, );
+ TU_VERIFY(p_hid,);
- if (XFER_RESULT_SUCCESS == xfer->result)
- {
+ if (XFER_RESULT_SUCCESS == xfer->result) {
p_hid->protocol_mode = (uint8_t) tu_le16toh(xfer->setup->wValue);
}
- if (tuh_hid_set_protocol_complete_cb)
- {
+ if (tuh_hid_set_protocol_complete_cb) {
tuh_hid_set_protocol_complete_cb(daddr, idx, p_hid->protocol_mode);
}
}
-static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
- TU_LOG2("HID Set Protocol = %d\r\n", protocol);
+void tuh_hid_set_default_protocol(uint8_t protocol) {
+ _hidh_default_protocol = protocol;
+}
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HID_REQ_CONTROL_SET_PROTOCOL,
- .wValue = protocol,
- .wIndex = itf_num,
- .wLength = 0
+static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ TU_LOG_DRV("HID Set Protocol = %d\r\n", protocol);
+
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = HID_REQ_CONTROL_SET_PROTOCOL,
+ .wValue = protocol,
+ .wIndex = itf_num,
+ .wLength = 0
};
- tuh_xfer_t xfer =
- {
- .daddr = daddr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = NULL,
- .complete_cb = complete_cb,
- .user_data = user_data
+ tuh_xfer_t xfer = {
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = NULL,
+ .complete_cb = complete_cb,
+ .user_data = user_data
};
return tuh_control_xfer(&xfer);
}
-bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol)
-{
+bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
TU_VERIFY(p_hid && p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE);
return _hidh_set_protocol(daddr, p_hid->itf_num, protocol, set_protocol_complete, 0);
}
-static void set_report_complete(tuh_xfer_t* xfer)
-{
- TU_LOG2("HID Set Report complete\r\n");
+static void set_report_complete(tuh_xfer_t* xfer) {
+ TU_LOG_DRV("HID Set Report complete\r\n");
- if (tuh_hid_set_report_complete_cb)
- {
+ if (tuh_hid_set_report_complete_cb) {
uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
- uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num);
+ uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num);
uint8_t const report_type = tu_u16_high(xfer->setup->wValue);
- uint8_t const report_id = tu_u16_low(xfer->setup->wValue);
+ uint8_t const report_id = tu_u16_low(xfer->setup->wValue);
tuh_hid_set_report_complete_cb(xfer->daddr, idx, report_id, report_type,
(xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0);
}
}
-bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len)
-{
+bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
TU_VERIFY(p_hid);
+ TU_LOG_DRV("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len);
- TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len);
-
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HID_REQ_CONTROL_SET_REPORT,
- .wValue = tu_htole16(tu_u16(report_type, report_id)),
- .wIndex = tu_htole16((uint16_t)p_hid->itf_num),
- .wLength = len
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = HID_REQ_CONTROL_SET_REPORT,
+ .wValue = tu_htole16(tu_u16(report_type, report_id)),
+ .wIndex = tu_htole16((uint16_t) p_hid->itf_num),
+ .wLength = len
};
- tuh_xfer_t xfer =
- {
- .daddr = daddr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = report,
- .complete_cb = set_report_complete,
- .user_data = 0
+ tuh_xfer_t xfer = {
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = report,
+ .complete_cb = set_report_complete,
+ .user_data = 0
};
return tuh_control_xfer(&xfer);
}
-static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
// SET IDLE request, device can stall if not support this request
- TU_LOG2("HID Set Idle \r\n");
+ TU_LOG_DRV("HID Set Idle \r\n");
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HID_REQ_CONTROL_SET_IDLE,
- .wValue = tu_htole16(idle_rate),
- .wIndex = tu_htole16((uint16_t)itf_num),
- .wLength = 0
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = HID_REQ_CONTROL_SET_IDLE,
+ .wValue = tu_htole16(idle_rate),
+ .wIndex = tu_htole16((uint16_t) itf_num),
+ .wLength = 0
};
- tuh_xfer_t xfer =
- {
- .daddr = daddr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = NULL,
- .complete_cb = complete_cb,
- .user_data = user_data
+ tuh_xfer_t xfer = {
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = NULL,
+ .complete_cb = complete_cb,
+ .user_data = user_data
};
return tuh_control_xfer(&xfer);
@@ -332,68 +300,60 @@ static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, t
//--------------------------------------------------------------------+
// Check if HID interface is ready to receive report
-bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx)
-{
+bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx) {
hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx);
TU_VERIFY(p_hid);
-
return !usbh_edpt_busy(dev_addr, p_hid->ep_in);
}
-bool tuh_hid_receive_report(uint8_t daddr, uint8_t idx)
-{
+bool tuh_hid_receive_report(uint8_t daddr, uint8_t idx) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
TU_VERIFY(p_hid);
// claim endpoint
- TU_VERIFY( usbh_edpt_claim(daddr, p_hid->ep_in) );
+ TU_VERIFY(usbh_edpt_claim(daddr, p_hid->ep_in));
- if ( !usbh_edpt_xfer(daddr, p_hid->ep_in, p_hid->epin_buf, p_hid->epin_size) )
- {
+ if (!usbh_edpt_xfer(daddr, p_hid->ep_in, p_hid->epin_buf, p_hid->epin_size)) {
usbh_edpt_release(daddr, p_hid->ep_in);
return false;
}
return true;
}
-
-bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx)
-{
+bool tuh_hid_receive_abort(uint8_t dev_addr, uint8_t idx) {
hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx);
TU_VERIFY(p_hid);
+ return tuh_edpt_abort_xfer(dev_addr, p_hid->ep_in);
+}
+bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx) {
+ hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx);
+ TU_VERIFY(p_hid);
return !usbh_edpt_busy(dev_addr, p_hid->ep_out);
}
-bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len)
-{
- TU_LOG2("HID Send Report %d\r\n", report_id);
+bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len) {
+ TU_LOG_DRV("HID Send Report %d\r\n", report_id);
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
TU_VERIFY(p_hid);
- if (p_hid->ep_out == 0)
- {
+ if (p_hid->ep_out == 0) {
// This HID does not have an out endpoint (other than control)
return false;
- }
- else if (len > CFG_TUH_HID_EPOUT_BUFSIZE ||
- (report_id != 0 && len > (CFG_TUH_HID_EPOUT_BUFSIZE - 1)))
- {
+ } else if (len > CFG_TUH_HID_EPOUT_BUFSIZE ||
+ (report_id != 0 && len > (CFG_TUH_HID_EPOUT_BUFSIZE - 1))) {
// ep_out buffer is not large enough to hold contents
return false;
}
// claim endpoint
- TU_VERIFY( usbh_edpt_claim(daddr, p_hid->ep_out) );
+ TU_VERIFY(usbh_edpt_claim(daddr, p_hid->ep_out));
- if (report_id == 0)
- {
+ if (report_id == 0) {
// No report ID in transmission
memcpy(&p_hid->epout_buf[0], report, len);
- }
- else
- {
+ } else {
p_hid->epout_buf[0] = report_id;
memcpy(&p_hid->epout_buf[1], report, len);
++len; // 1 more byte for report_id
@@ -401,8 +361,7 @@ bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const vo
TU_LOG3_MEM(p_hid->epout_buf, len, 2);
- if ( !usbh_edpt_xfer(daddr, p_hid->ep_out, p_hid->epout_buf, len) )
- {
+ if (!usbh_edpt_xfer(daddr, p_hid->ep_out, p_hid->epout_buf, len)) {
usbh_edpt_release(daddr, p_hid->ep_out);
return false;
}
@@ -413,13 +372,17 @@ bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const vo
//--------------------------------------------------------------------+
// USBH API
//--------------------------------------------------------------------+
-void hidh_init(void)
-{
+bool hidh_init(void) {
+ TU_LOG_DRV("sizeof(hidh_interface_t) = %u\r\n", sizeof(hidh_interface_t));
tu_memclr(_hidh_itf, sizeof(_hidh_itf));
+ return true;
}
-bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
+bool hidh_deinit(void) {
+ return true;
+}
+
+bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) result;
uint8_t const dir = tu_edpt_dir(ep_addr);
@@ -428,28 +391,26 @@ bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
TU_VERIFY(p_hid);
- if ( dir == TUSB_DIR_IN )
- {
- TU_LOG2(" Get Report callback (%u, %u)\r\n", daddr, idx);
+ if (dir == TUSB_DIR_IN) {
+ TU_LOG_DRV(" Get Report callback (%u, %u)\r\n", daddr, idx);
TU_LOG3_MEM(p_hid->epin_buf, xferred_bytes, 2);
tuh_hid_report_received_cb(daddr, idx, p_hid->epin_buf, (uint16_t) xferred_bytes);
- }else
- {
- if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(daddr, idx, p_hid->epout_buf, (uint16_t) xferred_bytes);
+ } else {
+ if (tuh_hid_report_sent_cb) {
+ tuh_hid_report_sent_cb(daddr, idx, p_hid->epout_buf, (uint16_t) xferred_bytes);
+ }
}
return true;
}
-void hidh_close(uint8_t daddr)
-{
- for(uint8_t i=0; i<CFG_TUH_HID; i++)
- {
+void hidh_close(uint8_t daddr) {
+ for (uint8_t i = 0; i < CFG_TUH_HID; i++) {
hidh_interface_t* p_hid = &_hidh_itf[i];
- if (p_hid->daddr == daddr)
- {
- if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i);
- p_hid->daddr = 0;
+ if (p_hid->daddr == daddr) {
+ TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i);
+ if (tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i);
+ tu_memclr(p_hid, sizeof(hidh_interface_t));
}
}
}
@@ -458,25 +419,22 @@ void hidh_close(uint8_t daddr)
// Enumeration
//--------------------------------------------------------------------+
-bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
-{
+bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) {
(void) rhport;
(void) max_len;
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass);
-
- TU_LOG2("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber);
+ TU_LOG_DRV("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber);
// len = interface + hid + n*endpoints
uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) +
desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
TU_ASSERT(max_len >= drv_len);
-
- uint8_t const *p_desc = (uint8_t const *) desc_itf;
+ uint8_t const* p_desc = (uint8_t const*) desc_itf;
//------------- HID descriptor -------------//
p_desc = tu_desc_next(p_desc);
- tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
+ tusb_hid_descriptor_hid_t const* desc_hid = (tusb_hid_descriptor_hid_t const*) p_desc;
TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType);
hidh_interface_t* p_hid = find_new_itf();
@@ -485,38 +443,33 @@ bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_
//------------- Endpoint Descriptors -------------//
p_desc = tu_desc_next(p_desc);
- tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc;
- for(int i = 0; i < desc_itf->bNumEndpoints; i++)
- {
+ for (int i = 0; i < desc_itf->bNumEndpoints; i++) {
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType);
- TU_ASSERT( tuh_edpt_open(daddr, desc_ep) );
+ TU_ASSERT(tuh_edpt_open(daddr, desc_ep));
- if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
- {
- p_hid->ep_in = desc_ep->bEndpointAddress;
+ if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
+ p_hid->ep_in = desc_ep->bEndpointAddress;
p_hid->epin_size = tu_edpt_packet_size(desc_ep);
- }
- else
- {
- p_hid->ep_out = desc_ep->bEndpointAddress;
+ } else {
+ p_hid->ep_out = desc_ep->bEndpointAddress;
p_hid->epout_size = tu_edpt_packet_size(desc_ep);
}
p_desc = tu_desc_next(p_desc);
- desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ desc_ep = (tusb_desc_endpoint_t const*) p_desc;
}
- p_hid->itf_num = desc_itf->bInterfaceNumber;
+ p_hid->itf_num = desc_itf->bInterfaceNumber;
// Assume bNumDescriptors = 1
p_hid->report_desc_type = desc_hid->bReportType;
- p_hid->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength);
+ p_hid->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength);
// Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config
- p_hid->protocol_mode = HID_PROTOCOL_BOOT;
- if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass )
- {
+ p_hid->protocol_mode = _hidh_default_protocol;
+ if (HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass) {
p_hid->itf_protocol = desc_itf->bInterfaceProtocol;
}
@@ -537,15 +490,14 @@ enum {
static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len);
static void process_set_config(tuh_xfer_t* xfer);
-bool hidh_set_config(uint8_t daddr, uint8_t itf_num)
-{
+bool hidh_set_config(uint8_t daddr, uint8_t itf_num) {
tusb_control_request_t request;
request.wIndex = tu_htole16((uint16_t) itf_num);
tuh_xfer_t xfer;
- xfer.daddr = daddr;
- xfer.result = XFER_RESULT_SUCCESS;
- xfer.setup = &request;
+ xfer.daddr = daddr;
+ xfer.result = XFER_RESULT_SUCCESS;
+ xfer.setup = &request;
xfer.user_data = CONFG_SET_IDLE;
// fake request to kick-off the set config process
@@ -554,71 +506,68 @@ bool hidh_set_config(uint8_t daddr, uint8_t itf_num)
return true;
}
-static void process_set_config(tuh_xfer_t* xfer)
-{
+static void process_set_config(tuh_xfer_t* xfer) {
// Stall is a valid response for SET_IDLE, sometime SET_PROTOCOL as well
// therefore we could ignore its result
- if ( !(xfer->setup->bRequest == HID_REQ_CONTROL_SET_IDLE ||
- xfer->setup->bRequest == HID_REQ_CONTROL_SET_PROTOCOL) )
- {
- TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
+ if (!(xfer->setup->bRequest == HID_REQ_CONTROL_SET_IDLE ||
+ xfer->setup->bRequest == HID_REQ_CONTROL_SET_PROTOCOL)) {
+ TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS,);
}
uintptr_t const state = xfer->user_data;
uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
- uint8_t const daddr = xfer->daddr;
+ uint8_t const daddr = xfer->daddr;
- uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num);
+ uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num);
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
- TU_VERIFY(p_hid, );
+ TU_VERIFY(p_hid,);
- switch(state)
- {
- case CONFG_SET_IDLE:
- {
+ switch (state) {
+ case CONFG_SET_IDLE: {
// Idle rate = 0 mean only report when there is changes
const uint16_t idle_rate = 0;
- const uintptr_t next_state = (p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE) ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC;
+ const uintptr_t next_state = (p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE)
+ ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC;
_hidh_set_idle(daddr, itf_num, idle_rate, process_set_config, next_state);
+ break;
}
- break;
case CONFIG_SET_PROTOCOL:
- _hidh_set_protocol(daddr, p_hid->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC);
- break;
+ _hidh_set_protocol(daddr, p_hid->itf_num, _hidh_default_protocol, process_set_config, CONFIG_GET_REPORT_DESC);
+ break;
case CONFIG_GET_REPORT_DESC:
// Get Report Descriptor if possible
// using usbh enumeration buffer since report descriptor can be very long
- if( p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE )
- {
- TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len);
+ if (p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE) {
+ TU_LOG_DRV("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len);
// Driver is mounted without report descriptor
config_driver_mount_complete(daddr, idx, NULL, 0);
- }else
- {
- tuh_descriptor_get_hid_report(daddr, itf_num, p_hid->report_desc_type, 0, usbh_get_enum_buf(), p_hid->report_desc_len, process_set_config, CONFIG_COMPLETE);
+ } else {
+ tuh_descriptor_get_hid_report(daddr, itf_num, p_hid->report_desc_type, 0,
+ usbh_get_enum_buf(), p_hid->report_desc_len,
+ process_set_config, CONFIG_COMPLETE);
}
break;
- case CONFIG_COMPLETE:
- {
+ case CONFIG_COMPLETE: {
uint8_t const* desc_report = usbh_get_enum_buf();
- uint16_t const desc_len = tu_le16toh(xfer->setup->wLength);
+ uint16_t const desc_len = tu_le16toh(xfer->setup->wLength);
config_driver_mount_complete(daddr, idx, desc_report, desc_len);
+ break;
}
- break;
- default: break;
+ default:
+ break;
}
}
-static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len)
-{
+static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len) {
hidh_interface_t* p_hid = get_hid_itf(daddr, idx);
- TU_VERIFY(p_hid, );
+ TU_VERIFY(p_hid,);
+ p_hid->mounted = true;
// enumeration is complete
if (tuh_hid_mount_cb) tuh_hid_mount_cb(daddr, idx, desc_report, desc_len);
@@ -631,21 +580,19 @@ static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t con
// Report Descriptor Parser
//--------------------------------------------------------------------+
-uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len)
-{
+uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count,
+ uint8_t const* desc_report, uint16_t desc_len) {
// Report Item 6.2.2.2 USB HID 1.11
- union TU_ATTR_PACKED
- {
+ union TU_ATTR_PACKED {
uint8_t byte;
- struct TU_ATTR_PACKED
- {
- uint8_t size : 2;
- uint8_t type : 2;
- uint8_t tag : 4;
+ struct TU_ATTR_PACKED {
+ uint8_t size : 2;
+ uint8_t type : 2;
+ uint8_t tag : 4;
};
} header;
- tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t));
+ tu_memclr(report_info_arr, arr_count * sizeof(tuh_hid_report_info_t));
uint8_t report_num = 0;
tuh_hid_report_info_t* info = report_info_arr;
@@ -655,115 +602,106 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr,
// uint8_t ri_report_size = 0;
uint8_t ri_collection_depth = 0;
-
- while(desc_len && report_num < arr_count)
- {
+ while (desc_len && report_num < arr_count) {
header.byte = *desc_report++;
desc_len--;
- uint8_t const tag = header.tag;
+ uint8_t const tag = header.tag;
uint8_t const type = header.type;
uint8_t const size = header.size;
uint8_t const data8 = desc_report[0];
TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size);
- for(uint32_t i=0; i<size; i++) TU_LOG(3, "%02X ", desc_report[i]);
+ for (uint32_t i = 0; i < size; i++) TU_LOG(3, "%02X ", desc_report[i]);
TU_LOG(3, "\r\n");
- switch(type)
- {
+ switch (type) {
case RI_TYPE_MAIN:
- switch (tag)
- {
+ switch (tag) {
case RI_MAIN_INPUT: break;
case RI_MAIN_OUTPUT: break;
case RI_MAIN_FEATURE: break;
-
case RI_MAIN_COLLECTION:
ri_collection_depth++;
- break;
+ break;
case RI_MAIN_COLLECTION_END:
ri_collection_depth--;
- if (ri_collection_depth == 0)
- {
+ if (ri_collection_depth == 0) {
info++;
report_num++;
}
- break;
+ break;
- default: break;
+ default:break;
}
- break;
+ break;
case RI_TYPE_GLOBAL:
- switch(tag)
- {
+ switch (tag) {
case RI_GLOBAL_USAGE_PAGE:
// only take in account the "usage page" before REPORT ID
- if ( ri_collection_depth == 0 ) memcpy(&info->usage_page, desc_report, size);
- break;
+ if (ri_collection_depth == 0) memcpy(&info->usage_page, desc_report, size);
+ break;
- case RI_GLOBAL_LOGICAL_MIN : break;
- case RI_GLOBAL_LOGICAL_MAX : break;
- case RI_GLOBAL_PHYSICAL_MIN : break;
- case RI_GLOBAL_PHYSICAL_MAX : break;
+ case RI_GLOBAL_LOGICAL_MIN: break;
+ case RI_GLOBAL_LOGICAL_MAX: break;
+ case RI_GLOBAL_PHYSICAL_MIN: break;
+ case RI_GLOBAL_PHYSICAL_MAX: break;
case RI_GLOBAL_REPORT_ID:
info->report_id = data8;
- break;
+ break;
case RI_GLOBAL_REPORT_SIZE:
// ri_report_size = data8;
- break;
+ break;
case RI_GLOBAL_REPORT_COUNT:
// ri_report_count = data8;
- break;
+ break;
- case RI_GLOBAL_UNIT_EXPONENT : break;
- case RI_GLOBAL_UNIT : break;
- case RI_GLOBAL_PUSH : break;
- case RI_GLOBAL_POP : break;
+ case RI_GLOBAL_UNIT_EXPONENT: break;
+ case RI_GLOBAL_UNIT: break;
+ case RI_GLOBAL_PUSH: break;
+ case RI_GLOBAL_POP: break;
default: break;
}
- break;
+ break;
case RI_TYPE_LOCAL:
- switch(tag)
- {
+ switch (tag) {
case RI_LOCAL_USAGE:
// only take in account the "usage" before starting REPORT ID
- if ( ri_collection_depth == 0 ) info->usage = data8;
- break;
+ if (ri_collection_depth == 0) info->usage = data8;
+ break;
- case RI_LOCAL_USAGE_MIN : break;
- case RI_LOCAL_USAGE_MAX : break;
- case RI_LOCAL_DESIGNATOR_INDEX : break;
- case RI_LOCAL_DESIGNATOR_MIN : break;
- case RI_LOCAL_DESIGNATOR_MAX : break;
- case RI_LOCAL_STRING_INDEX : break;
- case RI_LOCAL_STRING_MIN : break;
- case RI_LOCAL_STRING_MAX : break;
- case RI_LOCAL_DELIMITER : break;
+ case RI_LOCAL_USAGE_MIN: break;
+ case RI_LOCAL_USAGE_MAX: break;
+ case RI_LOCAL_DESIGNATOR_INDEX: break;
+ case RI_LOCAL_DESIGNATOR_MIN: break;
+ case RI_LOCAL_DESIGNATOR_MAX: break;
+ case RI_LOCAL_STRING_INDEX: break;
+ case RI_LOCAL_STRING_MIN: break;
+ case RI_LOCAL_STRING_MAX: break;
+ case RI_LOCAL_DELIMITER: break;
default: break;
}
- break;
+ break;
- // error
+ // error
default: break;
}
desc_report += size;
- desc_len -= size;
+ desc_len -= size;
}
- for ( uint8_t i = 0; i < report_num; i++ )
- {
- info = report_info_arr+i;
- TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage);
+ for (uint8_t i = 0; i < report_num; i++) {
+ info = report_info_arr + i;
+ TU_LOG_DRV("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage);
}
return report_num;
diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h
index 08ad421d2..0902bf1af 100644
--- a/src/class/hid/hid_host.h
+++ b/src/class/hid/hid_host.h
@@ -30,7 +30,7 @@
#include "hid.h"
#ifdef __cplusplus
- extern "C" {
+extern "C" {
#endif
//--------------------------------------------------------------------+
@@ -47,10 +47,9 @@
#endif
-typedef struct
-{
- uint8_t report_id;
- uint8_t usage;
+typedef struct {
+ uint8_t report_id;
+ uint8_t usage;
uint16_t usage_page;
// TODO still use the endpoint size for now
@@ -86,7 +85,8 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t idx);
// Parse report descriptor into array of report_info struct and return number of reports.
// For complicated report, application should write its own parser.
-uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED;
+TU_ATTR_UNUSED uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count,
+ uint8_t const* desc_report, uint16_t desc_len);
//--------------------------------------------------------------------+
// Control Endpoint API
@@ -97,13 +97,18 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr,
// Application can use set_protocol() to switch back to Report protocol.
uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t idx);
+// Device by default is enumerated in Boot protocol for simplicity. Application
+// can use this to modify the default protocol for next enumeration.
+void tuh_hid_set_default_protocol(uint8_t protocol);
+
// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1)
// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE)
bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t idx, uint8_t protocol);
// Set Report using control endpoint
// report_type is either Input, Output or Feature, (value from hid_report_type_t)
-bool tuh_hid_set_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len);
+bool tuh_hid_set_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type,
+ void* report, uint16_t len);
//--------------------------------------------------------------------+
// Interrupt Endpoint API
@@ -117,6 +122,9 @@ bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx);
// - false if failed to queue the transfer e.g endpoint is busy
bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t idx);
+// Abort receiving report on Interrupt Endpoint
+bool tuh_hid_receive_abort(uint8_t dev_addr, uint8_t idx);
+
// Check if HID interface is ready to send report
bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx);
@@ -155,11 +163,12 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
-void hidh_init (void);
-bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
-bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num);
-bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
-void hidh_close (uint8_t dev_addr);
+bool hidh_init(void);
+bool hidh_deinit(void);
+bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len);
+bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num);
+bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
+void hidh_close(uint8_t dev_addr);
#ifdef __cplusplus
}
diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c
index e3e7826da..42905ab0d 100644
--- a/src/class/midi/midi_device.c
+++ b/src/class/midi/midi_device.c
@@ -82,7 +82,7 @@ typedef struct
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI];
+CFG_TUD_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI];
bool tud_midi_n_mounted (uint8_t itf)
{
@@ -373,12 +373,10 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4])
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void midid_init(void)
-{
+void midid_init(void) {
tu_memclr(_midid_itf, sizeof(_midid_itf));
- for(uint8_t i=0; i<CFG_TUD_MIDI; i++)
- {
+ for (uint8_t i = 0; i < CFG_TUD_MIDI; i++) {
midid_interface_t* midi = &_midid_itf[i];
// config fifo
@@ -386,12 +384,38 @@ void midid_init(void)
tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS.
#if CFG_FIFO_MUTEX
- tu_fifo_config_mutex(&midi->rx_ff, NULL, osal_mutex_create(&midi->rx_ff_mutex));
- tu_fifo_config_mutex(&midi->tx_ff, osal_mutex_create(&midi->tx_ff_mutex), NULL);
+ osal_mutex_t mutex_rd = osal_mutex_create(&midi->rx_ff_mutex);
+ osal_mutex_t mutex_wr = osal_mutex_create(&midi->tx_ff_mutex);
+ TU_ASSERT(mutex_wr != NULL && mutex_wr != NULL, );
+
+ tu_fifo_config_mutex(&midi->rx_ff, NULL, mutex_rd);
+ tu_fifo_config_mutex(&midi->tx_ff, mutex_wr, NULL);
#endif
}
}
+bool midid_deinit(void) {
+ #if CFG_FIFO_MUTEX
+ for(uint8_t i=0; i<CFG_TUD_MIDI; i++) {
+ midid_interface_t* midi = &_midid_itf[i];
+ osal_mutex_t mutex_rd = midi->rx_ff.mutex_rd;
+ osal_mutex_t mutex_wr = midi->tx_ff.mutex_wr;
+
+ if (mutex_rd) {
+ osal_mutex_delete(mutex_rd);
+ tu_fifo_config_mutex(&midi->rx_ff, NULL, NULL);
+ }
+
+ if (mutex_wr) {
+ osal_mutex_delete(mutex_wr);
+ tu_fifo_config_mutex(&midi->tx_ff, NULL, NULL);
+ }
+ }
+ #endif
+
+ return true;
+}
+
void midid_reset(uint8_t rhport)
{
(void) rhport;
diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h
index 1c6f996be..3e89cc0a3 100644
--- a/src/class/midi/midi_device.h
+++ b/src/class/midi/midi_device.h
@@ -158,6 +158,7 @@ static inline bool tud_midi_packet_write (uint8_t const packet[4])
// Internal Class Driver API
//--------------------------------------------------------------------+
void midid_init (void);
+bool midid_deinit (void);
void midid_reset (uint8_t rhport);
uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h
index 7f25a29ba..bbfd35a43 100644
--- a/src/class/msc/msc.h
+++ b/src/class/msc/msc.h
@@ -53,7 +53,7 @@ enum {
};
/// \brief MassStorage Protocol.
-/// \details CBI only approved to use with full-speed floopy disk & should not used with highspeed or device other than floopy
+/// \details CBI only approved to use with full-speed floppy disk & should not used with highspeed or device other than floppy
typedef enum
{
MSC_PROTOCOL_CBI = 0 , ///< Control/Bulk/Interrupt protocol (with command completion interrupt)
@@ -97,7 +97,7 @@ typedef struct TU_ATTR_PACKED
{
uint32_t signature ; ///< Signature that helps identify this data packet as a CSW. The signature field shall contain the value 53425355h (little endian), indicating CSW.
uint32_t tag ; ///< The device shall set this field to the value received in the dCBWTag of the associated CBW.
- uint32_t data_residue ; ///< For Data-Out the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLengthand the actual amount of relevant data sent by the device
+ uint32_t data_residue ; ///< For Data-Out the device shall report in the dCSWDataResidue the difference between the amount of data expected as stated in the dCBWDataTransferLength, and the actual amount of data processed by the device. For Data-In the device shall report in the dCSWDataResiduethe difference between the amount of data expected as stated in the dCBWDataTransferLengthand the actual amount of relevant data sent by the device
uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t
}msc_csw_t;
@@ -120,14 +120,14 @@ typedef enum
SCSI_CMD_REQUEST_SENSE = 0x03, ///< The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used to obtain sense data -- status/error information -- from a target device.
SCSI_CMD_READ_FORMAT_CAPACITY = 0x23, ///< The command allows the Host to request a list of the possible format capacities for an installed writable media. This command also has the capability to report the writable capacity for a media when it is installed
SCSI_CMD_READ_10 = 0x28, ///< The READ (10) command requests that the device server read the specified logical block(s) and transfer them to the data-in buffer.
- SCSI_CMD_WRITE_10 = 0x2A, ///< The WRITE (10) command requests thatthe device server transfer the specified logical block(s) from the data-out buffer and write them.
+ SCSI_CMD_WRITE_10 = 0x2A, ///< The WRITE (10) command requests that the device server transfer the specified logical block(s) from the data-out buffer and write them.
}scsi_cmd_type_t;
/// SCSI Sense Key
typedef enum
{
SCSI_SENSE_NONE = 0x00, ///< no specific Sense Key. This would be the case for a successful command
- SCSI_SENSE_RECOVERED_ERROR = 0x01, ///< ndicates the last command completed successfully with some recovery action performed by the disc drive.
+ SCSI_SENSE_RECOVERED_ERROR = 0x01, ///< Indicates the last command completed successfully with some recovery action performed by the disc drive.
SCSI_SENSE_NOT_READY = 0x02, ///< Indicates the logical unit addressed cannot be accessed.
SCSI_SENSE_MEDIUM_ERROR = 0x03, ///< Indicates the command terminated with a non-recovered error condition.
SCSI_SENSE_HARDWARE_ERROR = 0x04, ///< Indicates the disc drive detected a nonrecoverable hardware failure while performing the command or during a self test.
@@ -138,7 +138,7 @@ typedef enum
SCSI_SENSE_ABORTED_COMMAND = 0x0b, ///< Indicates the disc drive aborted the command.
SCSI_SENSE_EQUAL = 0x0c, ///< Indicates a SEARCH DATA command has satisfied an equal comparison.
SCSI_SENSE_VOLUME_OVERFLOW = 0x0d, ///< Indicates a buffered peripheral device has reached the end of medium partition and data remains in the buffer that has not been written to the medium.
- SCSI_SENSE_MISCOMPARE = 0x0e ///< ndicates that the source data did not match the data read from the medium.
+ SCSI_SENSE_MISCOMPARE = 0x0e ///< Indicates that the source data did not match the data read from the medium.
}scsi_sense_key_type_t;
//--------------------------------------------------------------------+
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c
index 159a11259..588fcaaca 100644
--- a/src/class/msc/msc_device.c
+++ b/src/class/msc/msc_device.c
@@ -34,13 +34,16 @@
#include "msc_device.h"
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUD_MSC_LOG_LEVEL
+ #define CFG_TUD_MSC_LOG_LEVEL CFG_TUD_LOG_LEVEL
+#endif
+
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_MSC_LOG_LEVEL, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-
-// Can be selectively disabled to reduce logging when troubleshooting other driver
-#define MSC_DEBUG 2
-
enum
{
MSC_STAGE_CMD = 0,
@@ -71,8 +74,8 @@ typedef struct
uint8_t add_sense_qualifier;
}mscd_interface_t;
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static mscd_interface_t _mscd_itf;
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE];
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static mscd_interface_t _mscd_itf;
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t _mscd_buf[CFG_TUD_MSC_EP_BUFSIZE];
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
@@ -164,7 +167,7 @@ uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw)
{
if ( block_count )
{
- TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n");
+ TU_LOG_DRV(" SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n");
status = MSC_CSW_STATUS_PHASE_ERROR;
}else
{
@@ -174,22 +177,22 @@ uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw)
{
if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) )
{
- TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n");
+ TU_LOG_DRV(" SCSI case 10 (Ho <> Di)\r\n");
status = MSC_CSW_STATUS_PHASE_ERROR;
}
else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) )
{
- TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n");
+ TU_LOG_DRV(" SCSI case 8 (Hi <> Do)\r\n");
status = MSC_CSW_STATUS_PHASE_ERROR;
}
else if ( 0 == block_count )
{
- TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n");
+ TU_LOG_DRV(" SCSI case 4 Hi > Dn (READ10) or case 9 Ho > Dn (WRITE10) \r\n");
status = MSC_CSW_STATUS_FAILED;
}
else if ( cbw->total_bytes / block_count == 0 )
{
- TU_LOG(MSC_DEBUG, " Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n");
+ TU_LOG_DRV(" Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n");
status = MSC_CSW_STATUS_PHASE_ERROR;
}
}
@@ -200,7 +203,7 @@ uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw)
//--------------------------------------------------------------------+
// Debug
//--------------------------------------------------------------------+
-#if CFG_TUSB_DEBUG >= 2
+#if CFG_TUSB_DEBUG >= CFG_TUD_MSC_LOG_LEVEL
TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] =
{
@@ -248,11 +251,15 @@ static inline void set_sense_medium_not_present(uint8_t lun)
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void mscd_init(void)
-{
+void mscd_init(void) {
tu_memclr(&_mscd_itf, sizeof(mscd_interface_t));
}
+bool mscd_deinit(void) {
+ // nothing to do
+ return true;
+}
+
void mscd_reset(uint8_t rhport)
{
(void) rhport;
@@ -352,7 +359,7 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
switch ( request->bRequest )
{
case MSC_REQ_RESET:
- TU_LOG(MSC_DEBUG, " MSC BOT Reset\r\n");
+ TU_LOG_DRV(" MSC BOT Reset\r\n");
TU_VERIFY(request->wValue == 0 && request->wLength == 0);
// driver state reset
@@ -363,7 +370,7 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
case MSC_REQ_GET_MAX_LUN:
{
- TU_LOG(MSC_DEBUG, " MSC Get Max Lun\r\n");
+ TU_LOG_DRV(" MSC Get Max Lun\r\n");
TU_VERIFY(request->wValue == 0 && request->wLength == 1);
uint8_t maxlun = 1;
@@ -400,7 +407,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) )
{
- TU_LOG(MSC_DEBUG, " SCSI CBW is not valid\r\n");
+ TU_LOG_DRV(" SCSI CBW is not valid\r\n");
// BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery
p_msc->stage = MSC_STAGE_NEED_RESET;
@@ -412,7 +419,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
return false;
}
- TU_LOG(MSC_DEBUG, " SCSI Command [Lun%u]: %s\r\n", p_cbw->lun, tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
+ TU_LOG_DRV(" SCSI Command [Lun%u]: %s\r\n", p_cbw->lun, tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
//TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2);
p_csw->signature = MSC_CSW_SIGNATURE;
@@ -457,7 +464,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
{
if (p_cbw->total_bytes > sizeof(_mscd_buf))
{
- TU_LOG(MSC_DEBUG, " SCSI reject non READ10/WRITE10 with large data\r\n");
+ TU_LOG_DRV(" SCSI reject non READ10/WRITE10 with large data\r\n");
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}else
{
@@ -479,7 +486,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if ( resplen < 0 )
{
// unsupported command
- TU_LOG(MSC_DEBUG, " SCSI unsupported or failed command\r\n");
+ TU_LOG_DRV(" SCSI unsupported or failed command\r\n");
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}
else if (resplen == 0)
@@ -514,7 +521,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
break;
case MSC_STAGE_DATA:
- TU_LOG(MSC_DEBUG, " SCSI Data [Lun%u]\r\n", p_cbw->lun);
+ TU_LOG_DRV(" SCSI Data [Lun%u]\r\n", p_cbw->lun);
//TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2);
if (SCSI_CMD_READ_10 == p_cbw->command[0])
@@ -546,7 +553,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if ( cb_result < 0 )
{
// unsupported command
- TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n");
+ TU_LOG_DRV(" SCSI unsupported command\r\n");
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}else
{
@@ -575,7 +582,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// Wait for the Status phase to complete
if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) )
{
- TU_LOG(MSC_DEBUG, " SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status);
+ TU_LOG_DRV(" SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status);
// TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2);
// Invoke complete callback if defined
@@ -845,7 +852,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
if ( nbytes < 0 )
{
// negative means error -> endpoint is stalled & status in CSW set to failed
- TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n");
+ TU_LOG_DRV(" tud_msc_read10_cb() return -1\r\n");
// set sense
set_sense_medium_not_present(p_cbw->lun);
@@ -907,7 +914,7 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3
if ( nbytes < 0 )
{
// negative means error -> failed this scsi op
- TU_LOG(MSC_DEBUG, " tud_msc_write10_cb() return -1\r\n");
+ TU_LOG_DRV(" tud_msc_write10_cb() return -1\r\n");
// update actual byte before failed
p_msc->xferred_len += xferred_bytes;
diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h
index 72f95be06..4247a40bd 100644
--- a/src/class/msc/msc_device.h
+++ b/src/class/msc/msc_device.h
@@ -150,6 +150,7 @@ TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun);
// Internal Class Driver API
//--------------------------------------------------------------------+
void mscd_init (void);
+bool mscd_deinit (void);
void mscd_reset (uint8_t rhport);
uint16_t mscd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool mscd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request);
diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c
index 1b48813ec..ce6e7fb2d 100644
--- a/src/class/msc/msc_host.c
+++ b/src/class/msc/msc_host.c
@@ -29,28 +29,28 @@
#if CFG_TUH_ENABLED && CFG_TUH_MSC
#include "host/usbh.h"
-#include "host/usbh_classdriver.h"
+#include "host/usbh_pvt.h"
#include "msc_host.h"
-// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message
-#define MSCH_DEBUG 2
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUH_MSC_LOG_LEVEL
+ #define CFG_TUH_MSC_LOG_LEVEL CFG_TUH_LOG_LEVEL
+#endif
-#define TU_LOG_MSCH(...) TU_LOG(MSCH_DEBUG, __VA_ARGS__)
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MSC_LOG_LEVEL, __VA_ARGS__)
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-enum
-{
+enum {
MSC_STAGE_IDLE = 0,
MSC_STAGE_CMD,
MSC_STAGE_DATA,
MSC_STAGE_STATUS,
};
-typedef struct
-{
+typedef struct {
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out;
@@ -67,13 +67,13 @@ typedef struct
//------------- SCSI -------------//
uint8_t stage;
- void* buffer;
+ void* buffer;
tuh_msc_complete_cb_t complete_cb;
uintptr_t complete_arg;
CFG_TUH_MEM_ALIGN msc_cbw_t cbw;
CFG_TUH_MEM_ALIGN msc_csw_t csw;
-}msch_interface_t;
+} msch_interface_t;
CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX];
@@ -82,62 +82,57 @@ CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX];
CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN
static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
+// FIXME potential nul reference
TU_ATTR_ALWAYS_INLINE
-static inline msch_interface_t* get_itf(uint8_t dev_addr)
-{
- return &_msch_itf[dev_addr-1];
+static inline msch_interface_t* get_itf(uint8_t dev_addr) {
+ return &_msch_itf[dev_addr - 1];
}
//--------------------------------------------------------------------+
// PUBLIC API
//--------------------------------------------------------------------+
-uint8_t tuh_msc_get_maxlun(uint8_t dev_addr)
-{
+uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->max_lun;
}
-uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun)
-{
+uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->capacity[lun].block_count;
}
-uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun)
-{
+uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->capacity[lun].block_size;
}
-bool tuh_msc_mounted(uint8_t dev_addr)
-{
+bool tuh_msc_mounted(uint8_t dev_addr) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->mounted;
}
-bool tuh_msc_ready(uint8_t dev_addr)
-{
+bool tuh_msc_ready(uint8_t dev_addr) {
msch_interface_t* p_msc = get_itf(dev_addr);
- return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in);
+ return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in) && !usbh_edpt_busy(dev_addr, p_msc->ep_out);
}
//--------------------------------------------------------------------+
// PUBLIC API: SCSI COMMAND
//--------------------------------------------------------------------+
-static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun)
-{
+static inline void cbw_init(msc_cbw_t* cbw, uint8_t lun) {
tu_memclr(cbw, sizeof(msc_cbw_t));
cbw->signature = MSC_CBW_SIGNATURE;
cbw->tag = 0x54555342; // TUSB
cbw->lun = lun;
}
-bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
-{
- msch_interface_t* p_msc = get_itf(dev_addr);
+bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data,
+ tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
+ msch_interface_t* p_msc = get_itf(daddr);
TU_VERIFY(p_msc->configured);
- // TODO claim endpoint
+ // claim endpoint
+ TU_VERIFY(usbh_edpt_claim(daddr, p_msc->ep_out));
p_msc->cbw = *cbw;
p_msc->stage = MSC_STAGE_CMD;
@@ -145,15 +140,18 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu
p_msc->complete_cb = complete_cb;
p_msc->complete_arg = arg;
- TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)));
+ if (!usbh_edpt_xfer(daddr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))) {
+ usbh_edpt_release(daddr, p_msc->ep_out);
+ return false;
+ }
return true;
}
-bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
-{
- msch_interface_t* p_msc = get_itf(dev_addr);
- TU_VERIFY(p_msc->configured);
+bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response,
+ tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
+ msch_interface_t* p_msc = get_itf(dev_addr);
+ TU_VERIFY(p_msc->configured);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
@@ -166,8 +164,8 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r
return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
}
-bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
-{
+bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response,
+ tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
@@ -178,18 +176,16 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_inquiry_t);
- scsi_inquiry_t const cmd_inquiry =
- {
- .cmd_code = SCSI_CMD_INQUIRY,
- .alloc_length = sizeof(scsi_inquiry_resp_t)
+ scsi_inquiry_t const cmd_inquiry = {
+ .cmd_code = SCSI_CMD_INQUIRY,
+ .alloc_length = sizeof(scsi_inquiry_resp_t)
};
memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len);
return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
}
-bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
-{
+bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->configured);
@@ -197,16 +193,16 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_
cbw_init(&cbw, lun);
cbw.total_bytes = 0;
- cbw.dir = TUSB_DIR_OUT;
- cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
- cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
- cbw.command[1] = lun; // according to wiki TODO need verification
+ cbw.dir = TUSB_DIR_OUT;
+ cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
+ cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
+ cbw.command[1] = lun; // according to wiki TODO need verification
return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb, arg);
}
-bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
-{
+bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void* response,
+ tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msc_cbw_t cbw;
cbw_init(&cbw, lun);
@@ -214,73 +210,64 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_ms
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_request_sense_t);
- scsi_request_sense_t const cmd_request_sense =
- {
- .cmd_code = SCSI_CMD_REQUEST_SENSE,
- .alloc_length = 18
+ scsi_request_sense_t const cmd_request_sense = {
+ .cmd_code = SCSI_CMD_REQUEST_SENSE,
+ .alloc_length = 18
};
-
memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len);
return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
}
-bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
-{
+bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void* buffer, uint32_t lba, uint16_t block_count,
+ tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
- cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
- cbw.dir = TUSB_DIR_IN_MASK;
- cbw.cmd_len = sizeof(scsi_read10_t);
+ cbw.total_bytes = block_count * p_msc->capacity[lun].block_size;
+ cbw.dir = TUSB_DIR_IN_MASK;
+ cbw.cmd_len = sizeof(scsi_read10_t);
- scsi_read10_t const cmd_read10 =
- {
- .cmd_code = SCSI_CMD_READ_10,
- .lba = tu_htonl(lba),
- .block_count = tu_htons(block_count)
+ scsi_read10_t const cmd_read10 = {
+ .cmd_code = SCSI_CMD_READ_10,
+ .lba = tu_htonl(lba),
+ .block_count = tu_htons(block_count)
};
-
memcpy(cbw.command, &cmd_read10, cbw.cmd_len);
return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb, arg);
}
-bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
-{
+bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const* buffer, uint32_t lba, uint16_t block_count,
+ tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
- cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
+ cbw.total_bytes = block_count * p_msc->capacity[lun].block_size;
cbw.dir = TUSB_DIR_OUT;
cbw.cmd_len = sizeof(scsi_write10_t);
- scsi_write10_t const cmd_write10 =
- {
- .cmd_code = SCSI_CMD_WRITE_10,
- .lba = tu_htonl(lba),
- .block_count = tu_htons(block_count)
+ scsi_write10_t const cmd_write10 = {
+ .cmd_code = SCSI_CMD_WRITE_10,
+ .lba = tu_htonl(lba),
+ .block_count = tu_htons(block_count)
};
-
memcpy(cbw.command, &cmd_write10, cbw.cmd_len);
- return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb, arg);
+ return tuh_msc_scsi_command(dev_addr, &cbw, (void*) (uintptr_t) buffer, complete_cb, arg);
}
#if 0
// MSC interface Reset (not used now)
-bool tuh_msc_reset(uint8_t dev_addr)
-{
- tusb_control_request_t const new_request =
- {
- .bmRequestType_bit =
- {
+bool tuh_msc_reset(uint8_t dev_addr) {
+ tusb_control_request_t const new_request = {
+ .bmRequestType_bit = {
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_OUT
@@ -297,75 +284,77 @@ bool tuh_msc_reset(uint8_t dev_addr)
//--------------------------------------------------------------------+
// CLASS-USBH API
//--------------------------------------------------------------------+
-void msch_init(void)
-{
+bool msch_init(void) {
+ TU_LOG_DRV("sizeof(msch_interface_t) = %u\r\n", sizeof(msch_interface_t));
tu_memclr(_msch_itf, sizeof(_msch_itf));
+ return true;
}
-void msch_close(uint8_t dev_addr)
-{
- TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, );
+bool msch_deinit(void) {
+ return true;
+}
+void msch_close(uint8_t dev_addr) {
+ TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX,);
msch_interface_t* p_msc = get_itf(dev_addr);
+ TU_VERIFY(p_msc->configured,);
+
+ TU_LOG_DRV(" MSCh close addr = %d\r\n", dev_addr);
// invoke Application Callback
- if (p_msc->mounted && tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr);
+ if (p_msc->mounted) {
+ if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr);
+ }
tu_memclr(p_msc, sizeof(msch_interface_t));
}
-bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
-{
+bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) {
msch_interface_t* p_msc = get_itf(dev_addr);
msc_cbw_t const * cbw = &p_msc->cbw;
msc_csw_t * csw = &p_msc->csw;
- switch (p_msc->stage)
- {
+ switch (p_msc->stage) {
case MSC_STAGE_CMD:
// Must be Command Block
- TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t));
+ TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t));
- if ( cbw->total_bytes && p_msc->buffer )
- {
+ if (cbw->total_bytes && p_msc->buffer) {
// Data stage if any
p_msc->stage = MSC_STAGE_DATA;
-
uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out;
TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes));
- }else
- {
+ } else {
// Status stage
p_msc->stage = MSC_STAGE_STATUS;
TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t)));
}
- break;
+ break;
case MSC_STAGE_DATA:
// Status stage
p_msc->stage = MSC_STAGE_STATUS;
TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t)));
- break;
+ break;
case MSC_STAGE_STATUS:
// SCSI op is complete
p_msc->stage = MSC_STAGE_IDLE;
- if (p_msc->complete_cb)
- {
- tuh_msc_complete_data_t const cb_data =
- {
- .cbw = cbw,
- .csw = csw,
- .scsi_data = p_msc->buffer,
- .user_arg = p_msc->complete_arg
+ if (p_msc->complete_cb) {
+ tuh_msc_complete_data_t const cb_data = {
+ .cbw = cbw,
+ .csw = csw,
+ .scsi_data = p_msc->buffer,
+ .user_arg = p_msc->complete_arg
};
p_msc->complete_cb(dev_addr, &cb_data);
}
- break;
+ break;
- // unknown state
- default: break;
+ // unknown state
+ default:
+ break;
}
return true;
@@ -374,39 +363,35 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
//--------------------------------------------------------------------+
// MSC Enumeration
//--------------------------------------------------------------------+
-
-static void config_get_maxlun_complete (tuh_xfer_t* xfer);
-static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data);
+static void config_get_maxlun_complete(tuh_xfer_t* xfer);
+static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
-bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
-{
+bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) {
(void) rhport;
TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass &&
- MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol);
+ MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol);
// msc driver length is fixed
- uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
+ uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) +
+ desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
TU_ASSERT(drv_len <= max_len);
msch_interface_t* p_msc = get_itf(dev_addr);
- tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf);
+ tusb_desc_endpoint_t const* ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(desc_itf);
- for(uint32_t i=0; i<2; i++)
- {
+ for (uint32_t i = 0; i < 2; i++) {
TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc));
- if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
- {
+ if (TUSB_DIR_IN == tu_edpt_dir(ep_desc->bEndpointAddress)) {
p_msc->ep_in = ep_desc->bEndpointAddress;
- }else
- {
+ } else {
p_msc->ep_out = ep_desc->bEndpointAddress;
}
- ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc);
+ ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(ep_desc);
}
p_msc->itf_num = desc_itf->bInterfaceNumber;
@@ -414,45 +399,40 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
return true;
}
-bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
-{
+bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_ASSERT(p_msc->itf_num == itf_num);
p_msc->configured = true;
//------------- Get Max Lun -------------//
- TU_LOG_MSCH("MSC Get Max Lun\r\n");
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_IN
- },
- .bRequest = MSC_REQ_GET_MAX_LUN,
- .wValue = 0,
- .wIndex = itf_num,
- .wLength = 1
+ TU_LOG_DRV("MSC Get Max Lun\r\n");
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_IN
+ },
+ .bRequest = MSC_REQ_GET_MAX_LUN,
+ .wValue = 0,
+ .wIndex = itf_num,
+ .wLength = 1
};
- tuh_xfer_t xfer =
- {
- .daddr = dev_addr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = &p_msc->max_lun,
- .complete_cb = config_get_maxlun_complete,
- .user_data = 0
+ tuh_xfer_t xfer = {
+ .daddr = dev_addr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = _msch_buffer,
+ .complete_cb = config_get_maxlun_complete,
+ .user_data = 0
};
TU_ASSERT(tuh_control_xfer(&xfer));
return true;
}
-static void config_get_maxlun_complete (tuh_xfer_t* xfer)
-{
+static void config_get_maxlun_complete(tuh_xfer_t* xfer) {
uint8_t const daddr = xfer->daddr;
msch_interface_t* p_msc = get_itf(daddr);
@@ -460,36 +440,35 @@ static void config_get_maxlun_complete (tuh_xfer_t* xfer)
p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0;
p_msc->max_lun++; // MAX LUN is minus 1 by specs
+ TU_LOG_DRV(" Max LUN = %u\r\n", p_msc->max_lun);
+
// TODO multiple LUN support
- TU_LOG_MSCH("SCSI Test Unit Ready\r\n");
+ TU_LOG_DRV("SCSI Test Unit Ready\r\n");
uint8_t const lun = 0;
tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete, 0);
}
-static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data)
-{
+static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
msc_cbw_t const* cbw = cb_data->cbw;
msc_csw_t const* csw = cb_data->csw;
- if (csw->status == 0)
- {
+ if (csw->status == 0) {
// Unit is ready, read its capacity
- TU_LOG_MSCH("SCSI Read Capacity\r\n");
- tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete, 0);
- }else
- {
+ TU_LOG_DRV("SCSI Read Capacity\r\n");
+ tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer),
+ config_read_capacity_complete, 0);
+ } else {
// Note: During enumeration, some device fails Test Unit Ready and require a few retries
// with Request Sense to start working !!
// TODO limit number of retries
- TU_LOG_MSCH("SCSI Request Sense\r\n");
+ TU_LOG_DRV("SCSI Request Sense\r\n");
TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete, 0));
}
return true;
}
-static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data)
-{
+static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
msc_cbw_t const* cbw = cb_data->cbw;
msc_csw_t const* csw = cb_data->csw;
@@ -498,8 +477,7 @@ static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_dat
return true;
}
-static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data)
-{
+static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
msc_cbw_t const* cbw = cb_data->cbw;
msc_csw_t const* csw = cb_data->csw;
diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h
index 6c0e5c9dd..9fda566d8 100644
--- a/src/class/msc/msc_host.h
+++ b/src/class/msc/msc_host.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_MSC_HOST_H_
-#define _TUSB_MSC_HOST_H_
+#ifndef TUSB_MSC_HOST_H_
+#define TUSB_MSC_HOST_H_
#include "msc.h"
@@ -73,7 +73,7 @@ uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun);
// Perform a full SCSI command (cbw, data, csw) in non-blocking manner.
// Complete callback is invoked when SCSI op is complete.
// return true if success, false if there is already pending operation.
-bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg);
+bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg);
// Perform SCSI Inquiry command
// Complete callback is invoked when SCSI op is complete.
@@ -113,7 +113,8 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr);
// Internal Class Driver API
//--------------------------------------------------------------------+
-void msch_init (void);
+bool msch_init (void);
+bool msch_deinit (void);
bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
bool msch_set_config (uint8_t dev_addr, uint8_t itf_num);
void msch_close (uint8_t dev_addr);
@@ -123,4 +124,4 @@ bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, ui
}
#endif
-#endif /* _TUSB_MSC_HOST_H_ */
+#endif
diff --git a/src/class/net/ecm_rndis_device.c b/src/class/net/ecm_rndis_device.c
index 8ac7cbd01..f7a5fd225 100644
--- a/src/class/net/ecm_rndis_device.c
+++ b/src/class/net/ecm_rndis_device.c
@@ -61,10 +61,10 @@ typedef struct
#define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t)
#define CFG_TUD_NET_PACKET_SUFFIX_LEN 0
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static
uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN];
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static
uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN];
struct ecm_notify_struct
@@ -94,8 +94,8 @@ tu_static const struct ecm_notify_struct ecm_notify_csc =
.uplink = 9728000,
};
-// TODO remove CFG_TUSB_MEM_SECTION, control internal buffer is already in this special section
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static union
+// TODO remove CFG_TUD_MEM_SECTION, control internal buffer is already in this special section
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static union
{
uint8_t rndis_buf[120];
struct ecm_notify_struct ecm_buf;
@@ -104,8 +104,8 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static union
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-// TODO remove CFG_TUSB_MEM_SECTION
-CFG_TUSB_MEM_SECTION tu_static netd_interface_t _netd_itf;
+// TODO remove CFG_TUD_MEM_SECTION
+CFG_TUD_MEM_SECTION tu_static netd_interface_t _netd_itf;
tu_static bool can_xmit;
@@ -132,11 +132,14 @@ void netd_report(uint8_t *buf, uint16_t len)
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void netd_init(void)
-{
+void netd_init(void) {
tu_memclr(&_netd_itf, sizeof(_netd_itf));
}
+bool netd_deinit(void) {
+ return true;
+}
+
void netd_reset(uint8_t rhport)
{
(void) rhport;
diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c
index 9e9580249..f84bd9f73 100644
--- a/src/class/net/ncm_device.c
+++ b/src/class/net/ncm_device.c
@@ -34,6 +34,13 @@
#include "device/usbd_pvt.h"
#include "net_device.h"
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUD_NCM_LOG_LEVEL
+ #define CFG_TUD_NCM_LOG_LEVEL CFG_TUD_LOG_LEVEL
+#endif
+
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_NCM_LOG_LEVEL, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
@@ -130,7 +137,7 @@ typedef struct
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static const ntb_parameters_t ntb_parameters = {
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static const ntb_parameters_t ntb_parameters = {
.wLength = sizeof(ntb_parameters_t),
.bmNtbFormatsSupported = 0x01,
.dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE,
@@ -145,9 +152,9 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static const ntb_parameters_t ntb_par
.wNtbOutMaxDatagrams = 0
};
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static transmit_ntb_t transmit_ntb[2];
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static transmit_ntb_t transmit_ntb[2];
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t receive_ntb[CFG_TUD_NCM_OUT_NTB_MAX_SIZE];
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static uint8_t receive_ntb[CFG_TUD_NCM_OUT_NTB_MAX_SIZE];
tu_static ncm_interface_t ncm_interface;
@@ -253,6 +260,10 @@ void netd_init(void)
ncm_prepare_for_tx();
}
+bool netd_deinit(void) {
+ return true;
+}
+
void netd_reset(uint8_t rhport)
{
(void) rhport;
@@ -473,13 +484,13 @@ bool tud_network_can_xmit(uint16_t size)
TU_VERIFY(ncm_interface.itf_data_alt == 1);
if (ncm_interface.datagram_count >= ncm_interface.max_datagrams_per_ntb) {
- TU_LOG2("NTB full [by count]\r\n");
+ TU_LOG_DRV("NTB full [by count]\r\n");
return false;
}
size_t next_datagram_offset = ncm_interface.next_datagram_offset;
if (next_datagram_offset + size > ncm_interface.ntb_in_size) {
- TU_LOG2("ntb full [by size]\r\n");
+ TU_LOG_DRV("ntb full [by size]\r\n");
return false;
}
diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h
index 399916355..da1a7b1e8 100644
--- a/src/class/net/net_device.h
+++ b/src/class/net/net_device.h
@@ -105,6 +105,7 @@ void tud_network_link_state_cb(bool state);
// INTERNAL USBD-CLASS DRIVER API
//--------------------------------------------------------------------+
void netd_init (void);
+bool netd_deinit (void);
void netd_reset (uint8_t rhport);
uint16_t netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c
index 4e320a778..286cbe108 100644
--- a/src/class/usbtmc/usbtmc_device.c
+++ b/src/class/usbtmc/usbtmc_device.c
@@ -143,7 +143,7 @@ typedef struct
usbtmc_capabilities_specific_t const * capabilities;
} usbtmc_interface_state_t;
-CFG_TUSB_MEM_SECTION tu_static usbtmc_interface_state_t usbtmc_state =
+CFG_TUD_MEM_SECTION tu_static usbtmc_interface_state_t usbtmc_state =
{
.itf_id = 0xFF,
};
@@ -260,6 +260,13 @@ void usbtmcd_init_cb(void)
usbtmcLock = osal_mutex_create(&usbtmcLockBuffer);
}
+bool usbtmcd_deinit(void) {
+ #if OSAL_MUTEX_REQUIRED
+ osal_mutex_delete(usbtmcLock);
+ #endif
+ return true;
+}
+
uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
(void)rhport;
diff --git a/src/class/usbtmc/usbtmc_device.h b/src/class/usbtmc/usbtmc_device.h
index c1298ddb8..3299a36eb 100644
--- a/src/class/usbtmc/usbtmc_device.h
+++ b/src/class/usbtmc/usbtmc_device.h
@@ -98,11 +98,12 @@ bool tud_usbtmc_start_bus_read(void);
/* "callbacks" from USB device core */
+void usbtmcd_init_cb(void);
+bool usbtmcd_deinit(void);
uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
void usbtmcd_reset_cb(uint8_t rhport);
bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
-void usbtmcd_init_cb(void);
/************************************************************
* USBTMC Descriptor Templates
diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c
index 93596ee33..e87ce3997 100644
--- a/src/class/vendor/vendor_device.c
+++ b/src/class/vendor/vendor_device.c
@@ -49,17 +49,15 @@ typedef struct
uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE];
uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE];
-#if CFG_FIFO_MUTEX
- osal_mutex_def_t rx_ff_mutex;
- osal_mutex_def_t tx_ff_mutex;
-#endif
+ OSAL_MUTEX_DEF(rx_ff_mutex);
+ OSAL_MUTEX_DEF(tx_ff_mutex);
// Endpoint Transfer buffer
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE];
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_VENDOR_EPSIZE];
} vendord_interface_t;
-CFG_TUSB_MEM_SECTION tu_static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR];
+CFG_TUD_MEM_SECTION tu_static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR];
#define ITF_MEM_RESET_SIZE offsetof(vendord_interface_t, rx_ff)
@@ -171,23 +169,47 @@ uint32_t tud_vendor_n_write_available (uint8_t itf)
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void vendord_init(void)
-{
+void vendord_init(void) {
tu_memclr(_vendord_itf, sizeof(_vendord_itf));
- for(uint8_t i=0; i<CFG_TUD_VENDOR; i++)
- {
+ for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
vendord_interface_t* p_itf = &_vendord_itf[i];
// config fifo
tu_fifo_config(&p_itf->rx_ff, p_itf->rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, 1, false);
tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false);
-#if CFG_FIFO_MUTEX
- tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex));
- tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL);
-#endif
+ #if OSAL_MUTEX_REQUIRED
+ osal_mutex_t mutex_rd = osal_mutex_create(&p_itf->rx_ff_mutex);
+ osal_mutex_t mutex_wr = osal_mutex_create(&p_itf->tx_ff_mutex);
+ TU_ASSERT(mutex_rd && mutex_wr,);
+
+ tu_fifo_config_mutex(&p_itf->rx_ff, NULL, mutex_rd);
+ tu_fifo_config_mutex(&p_itf->tx_ff, mutex_wr, NULL);
+ #endif
+ }
+}
+
+bool vendord_deinit(void) {
+ #if OSAL_MUTEX_REQUIRED
+ for(uint8_t i=0; i<CFG_TUD_VENDOR; i++) {
+ vendord_interface_t* p_itf = &_vendord_itf[i];
+ osal_mutex_t mutex_rd = p_itf->rx_ff.mutex_rd;
+ osal_mutex_t mutex_wr = p_itf->tx_ff.mutex_wr;
+
+ if (mutex_rd) {
+ osal_mutex_delete(mutex_rd);
+ tu_fifo_config_mutex(&p_itf->rx_ff, NULL, NULL);
+ }
+
+ if (mutex_wr) {
+ osal_mutex_delete(mutex_wr);
+ tu_fifo_config_mutex(&p_itf->tx_ff, NULL, NULL);
+ }
}
+ #endif
+
+ return true;
}
void vendord_reset(uint8_t rhport)
diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h
index d239406b4..cd69ec7c6 100644
--- a/src/class/vendor/vendor_device.h
+++ b/src/class/vendor/vendor_device.h
@@ -139,6 +139,7 @@ static inline uint32_t tud_vendor_write_available (void)
// Internal Class Driver API
//--------------------------------------------------------------------+
void vendord_init(void);
+bool vendord_deinit(void);
void vendord_reset(uint8_t rhport);
uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
diff --git a/src/class/video/video.h b/src/class/video/video.h
index c0088c4f6..b8a9b6369 100644
--- a/src/class/video/video.h
+++ b/src/class/video/video.h
@@ -29,6 +29,10 @@
#include "common/tusb_common.h"
+enum {
+ VIDEO_BCD_1_50 = 0x0150,
+};
+
// Table 3-19 Color Matching Descriptor
typedef enum {
VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00,
@@ -156,22 +160,23 @@ typedef enum {
/* A.9.1 VideoControl Interface Control Selectors */
typedef enum {
VIDEO_VC_CTL_UNDEFINED = 0x00,
- VIDEO_VC_CTL_VIDEO_POWER_MODE,
- VIDEO_VC_CTL_REQUEST_ERROR_CODE,
+ VIDEO_VC_CTL_VIDEO_POWER_MODE, // 0x01
+ VIDEO_VC_CTL_REQUEST_ERROR_CODE, // 0x02
} video_interface_control_selector_t;
/* A.9.8 VideoStreaming Interface Control Selectors */
typedef enum {
VIDEO_VS_CTL_UNDEFINED = 0x00,
- VIDEO_VS_CTL_PROBE,
- VIDEO_VS_CTL_COMMIT,
- VIDEO_VS_CTL_STILL_PROBE,
- VIDEO_VS_CTL_STILL_COMMIT,
- VIDEO_VS_CTL_STILL_IMAGE_TRIGGER,
- VIDEO_VS_CTL_STREAM_ERROR_CODE,
- VIDEO_VS_CTL_GENERATE_KEY_FRAME,
- VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT,
- VIDEO_VS_CTL_SYNCH_DELAY_CONTROL,
+ VIDEO_VS_CTL_PROBE, // 0x01
+ VIDEO_VS_CTL_COMMIT, // 0x02
+ VIDEO_VS_CTL_STILL_PROBE, // 0x03
+ VIDEO_VS_CTL_STILL_COMMIT, // 0x04
+ VIDEO_VS_CTL_STILL_IMAGE_TRIGGER, // 0x05
+ VIDEO_VS_CTL_STREAM_ERROR_CODE, // 0x06
+ VIDEO_VS_CTL_GENERATE_KEY_FRAME, // 0x07
+ VIDEO_VS_CTL_UPDATE_FRAME_SEGMENT, // 0x08
+ VIDEO_VS_CTL_SYNCH_DELAY_CONTROL, // 0x09
+
} video_interface_streaming_selector_t;
/* B. Terminal Types */
@@ -198,55 +203,98 @@ typedef enum {
} video_terminal_type_t;
//--------------------------------------------------------------------+
-// Descriptors
+// Video Control (VC) Descriptors
//--------------------------------------------------------------------+
/* 2.3.4.2 */
+#define tusb_desc_video_control_header_nitf_t(_nitf) \
+ struct TU_ATTR_PACKED { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint16_t bcdUVC; \
+ uint16_t wTotalLength; \
+ uint32_t dwClockFrequency; /* deprecated */ \
+ uint8_t bInCollection; \
+ uint8_t baInterfaceNr[_nitf]; \
+ }
+
+typedef tusb_desc_video_control_header_nitf_t() tusb_desc_video_control_header_t;
+typedef tusb_desc_video_control_header_nitf_t(1) tusb_desc_video_control_header_1itf_t;
+typedef tusb_desc_video_control_header_nitf_t(2) tusb_desc_video_control_header_2itf_t;
+typedef tusb_desc_video_control_header_nitf_t(3) tusb_desc_video_control_header_3itf_t;
+typedef tusb_desc_video_control_header_nitf_t(4) tusb_desc_video_control_header_4itf_t;
+
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
- uint16_t bcdUVC;
- uint16_t wTotalLength;
- uint32_t dwClockFrequency;
- uint8_t bInCollection;
- uint8_t baInterfaceNr[];
-} tusb_desc_cs_video_ctl_itf_hdr_t;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t iTerminal;
+} tusb_desc_video_control_input_terminal_t;
+
+TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_input_terminal_t) == 8, "size is not correct");
-/* 2.4.3.3 */
typedef struct TU_ATTR_PACKED {
- uint8_t bHeaderLength;
- union {
- uint8_t bmHeaderInfo;
- struct {
- uint8_t FrameID: 1;
- uint8_t EndOfFrame: 1;
- uint8_t PresentationTime: 1;
- uint8_t SourceClockReference: 1;
- uint8_t PayloadSpecific: 1;
- uint8_t StillImage: 1;
- uint8_t Error: 1;
- uint8_t EndOfHeader: 1;
- };
- };
-} tusb_video_payload_header_t;
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t bSourceID;
+ uint8_t iTerminal;
+} tusb_desc_video_control_output_terminal_t;
+
+TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_output_terminal_t) == 9, "size is not correct");
-/* 3.9.2.1 */
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
- uint8_t bNumFormats;
- uint16_t wTotalLength;
- uint8_t bEndpointAddress;
- uint8_t bmInfo;
- uint8_t bTerminalLink;
- uint8_t bStillCaptureMethod;
- uint8_t bTriggerSupport;
- uint8_t bTriggerUsage;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t iTerminal;
+
+ uint16_t wObjectiveFocalLengthMin;
+ uint16_t wObjectiveFocalLengthMax;
+ uint16_t wOcularFocalLength;
uint8_t bControlSize;
- uint8_t bmaControls[];
-} tusb_desc_cs_video_stm_itf_in_hdr_t;
+ uint8_t bmControls[3];
+} tusb_desc_video_control_camera_terminal_t;
+
+TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_camera_terminal_t) == 18, "size is not correct");
+
+//--------------------------------------------------------------------+
+// Video Streaming (VS) Descriptors
+//--------------------------------------------------------------------+
+
+/* 3.9.2.1 */
+#define tusb_desc_video_streaming_input_header_nbyte_t(_nb) \
+ struct TU_ATTR_PACKED { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bNumFormats; /* Number of video payload Format descriptors for this interface */ \
+ uint16_t wTotalLength; \
+ uint8_t bEndpointAddress; \
+ uint8_t bmInfo; /* Bit 0: dynamic format change supported */ \
+ uint8_t bTerminalLink; \
+ uint8_t bStillCaptureMethod; \
+ uint8_t bTriggerSupport; /* Hardware trigger supported */ \
+ uint8_t bTriggerUsage; \
+ uint8_t bControlSize; /* sizeof of each control item */ \
+ uint8_t bmaControls[_nb]; \
+ }
+
+typedef tusb_desc_video_streaming_input_header_nbyte_t() tusb_desc_video_streaming_input_header_t;
+typedef tusb_desc_video_streaming_input_header_nbyte_t(1) tusb_desc_video_streaming_input_header_1byte_t;
+typedef tusb_desc_video_streaming_input_header_nbyte_t(2) tusb_desc_video_streaming_input_header_2byte_t;
+typedef tusb_desc_video_streaming_input_header_nbyte_t(3) tusb_desc_video_streaming_input_header_3byte_t;
+typedef tusb_desc_video_streaming_input_header_nbyte_t(4) tusb_desc_video_streaming_input_header_4byte_t;
/* 3.9.2.2 */
typedef struct TU_ATTR_PACKED {
@@ -259,7 +307,7 @@ typedef struct TU_ATTR_PACKED {
uint8_t bTerminalLink;
uint8_t bControlSize;
uint8_t bmaControls[];
-} tusb_desc_cs_video_stm_itf_out_hdr_t;
+} tusb_desc_video_streaming_output_header_t;
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
@@ -285,14 +333,33 @@ typedef struct TU_ATTR_PACKED {
uint8_t bmaControls[];
} output;
};
-} tusb_desc_cs_video_stm_itf_hdr_t;
+} tusb_desc_video_streaming_inout_header_t;
+// 3.9.2.6 Color Matching Descriptor
+typedef struct TU_ATTR_PACKED {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bColorPrimaries;
+ uint8_t bTransferCharacteristics;
+ uint8_t bMatrixCoefficients;
+} tusb_desc_video_streaming_color_matching_t;
+
+TU_VERIFY_STATIC(sizeof(tusb_desc_video_streaming_color_matching_t) == 6, "size is not correct");
+
+//--------------------------------------------------------------------+
+// Format and Frame Descriptor
+// Note: bFormatIndex & bFrameIndex are 1-based index
+//--------------------------------------------------------------------+
+
+//------------- Uncompressed -------------//
+// Uncompressed payload specs: 3.1.1 format descriptor
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
- uint8_t bNumFrameDescriptors;
+ uint8_t bNumFrameDescriptors; // Number of frame descriptors for this format
uint8_t guidFormat[16];
uint8_t bBitsPerPixel;
uint8_t bDefaultFrameIndex;
@@ -300,22 +367,69 @@ typedef struct TU_ATTR_PACKED {
uint8_t bAspectRatioY;
uint8_t bmInterlaceFlags;
uint8_t bCopyProtect;
-} tusb_desc_cs_video_fmt_uncompressed_t;
+} tusb_desc_video_format_uncompressed_t;
+
+TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_uncompressed_t) == 27, "size is not correct");
+
+// Uncompressed payload specs: 3.1.2 frame descriptor
+#define tusb_desc_video_frame_uncompressed_nint_t(_nint) \
+ struct TU_ATTR_PACKED { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bFrameIndex; \
+ uint8_t bmCapabilities; \
+ uint16_t wWidth; \
+ uint16_t wHeight; \
+ uint32_t dwMinBitRate; \
+ uint32_t dwMaxBitRate; \
+ uint32_t dwMaxVideoFrameBufferSize; /* deprecated in 1.5 */ \
+ uint32_t dwDefaultFrameInterval; /* 100ns unit */\
+ uint8_t bFrameIntervalType; \
+ uint32_t dwFrameInterval[_nint]; \
+ }
+typedef tusb_desc_video_frame_uncompressed_nint_t() tusb_desc_video_frame_uncompressed_t;
+typedef tusb_desc_video_frame_uncompressed_nint_t(1) tusb_desc_video_frame_uncompressed_1int_t;
+typedef tusb_desc_video_frame_uncompressed_nint_t(2) tusb_desc_video_frame_uncompressed_2int_t;
+typedef tusb_desc_video_frame_uncompressed_nint_t(3) tusb_desc_video_frame_uncompressed_3int_t;
+typedef tusb_desc_video_frame_uncompressed_nint_t(4) tusb_desc_video_frame_uncompressed_4int_t;
+
+// continuous = 3 intervals: min, max, step
+typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_uncompressed_continuous_t;
+
+TU_VERIFY_STATIC(sizeof(tusb_desc_video_frame_uncompressed_continuous_t) == 38, "size is not correct");
+
+//------------- MJPEG -------------//
+// MJPEG payload specs: 3.1.1 format descriptor
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bNumFrameDescriptors;
- uint8_t bmFlags;
+ uint8_t bmFlags; // Bit 0: fixed size samples (1 = yes)
uint8_t bDefaultFrameIndex;
uint8_t bAspectRatioX;
uint8_t bAspectRatioY;
uint8_t bmInterlaceFlags;
uint8_t bCopyProtect;
-} tusb_desc_cs_video_fmt_mjpeg_t;
+} tusb_desc_video_format_mjpeg_t;
+
+TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_mjpeg_t) == 11, "size is not correct");
+
+// MJPEG payload specs: 3.1.2 frame descriptor (same as uncompressed)
+typedef tusb_desc_video_frame_uncompressed_t tusb_desc_video_frame_mjpeg_t;
+typedef tusb_desc_video_frame_uncompressed_1int_t tusb_desc_video_frame_mjpeg_1int_t;
+typedef tusb_desc_video_frame_uncompressed_2int_t tusb_desc_video_frame_mjpeg_2int_t;
+typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_mjpeg_3int_t;
+typedef tusb_desc_video_frame_uncompressed_4int_t tusb_desc_video_frame_mjpeg_4int_t;
+
+// continuous = 3 intervals: min, max, step
+typedef tusb_desc_video_frame_mjpeg_3int_t tusb_desc_video_frame_mjpeg_continuous_t;
+//------------- DV -------------//
+// DV payload specs: 3.1.1
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -323,8 +437,9 @@ typedef struct TU_ATTR_PACKED {
uint8_t bFormatIndex;
uint32_t dwMaxVideoFrameBufferSize; /* deprecated */
uint8_t bFormatType;
-} tusb_desc_cs_video_fmt_dv_t;
+} tusb_desc_video_format_dv_t;
+// Frame Based payload specs: 3.1.1
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -339,25 +454,7 @@ typedef struct TU_ATTR_PACKED {
uint8_t bmInterlaceFlags;
uint8_t bCopyProtect;
uint8_t bVaribaleSize;
-} tusb_desc_cs_video_fmt_frame_based_t;
-
-typedef struct TU_ATTR_PACKED {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubType;
- uint8_t bFrameIndex;
- uint8_t bmCapabilities;
- uint16_t wWidth;
- uint16_t wHeight;
- uint32_t dwMinBitRate;
- uint32_t dwMaxBitRate;
- uint32_t dwMaxVideoFrameBufferSize; /* deprecated */
- uint32_t dwDefaultFrameInterval;
- uint8_t bFrameIntervalType;
- uint32_t dwFrameInterval[];
-} tusb_desc_cs_video_frm_uncompressed_t;
-
-typedef tusb_desc_cs_video_frm_uncompressed_t tusb_desc_cs_video_frm_mjpeg_t;
+} tusb_desc_video_format_framebased_t;
typedef struct TU_ATTR_PACKED {
uint8_t bLength;
@@ -373,12 +470,30 @@ typedef struct TU_ATTR_PACKED {
uint8_t bFrameIntervalType;
uint32_t dwBytesPerLine;
uint32_t dwFrameInterval[];
-} tusb_desc_cs_video_frm_frame_based_t;
+} tusb_desc_video_frame_framebased_t;
//--------------------------------------------------------------------+
// Requests
//--------------------------------------------------------------------+
+/* 2.4.3.3 */
+typedef struct TU_ATTR_PACKED {
+ uint8_t bHeaderLength;
+ union {
+ uint8_t bmHeaderInfo;
+ struct {
+ uint8_t FrameID: 1;
+ uint8_t EndOfFrame: 1;
+ uint8_t PresentationTime: 1;
+ uint8_t SourceClockReference: 1;
+ uint8_t PayloadSpecific: 1;
+ uint8_t StillImage: 1;
+ uint8_t Error: 1;
+ uint8_t EndOfHeader: 1;
+ };
+ };
+} tusb_video_payload_header_t;
+
/* 4.3.1.1 */
typedef struct TU_ATTR_PACKED {
union {
@@ -448,9 +563,9 @@ TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not c
#define TUD_VIDEO_GUID_M420 0x4D,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71
#define TUD_VIDEO_GUID_I420 0x49,0x34,0x32,0x30,0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71
-#define TUD_VIDEO_DESC_IAD(_firstitfs, _nitfs, _stridx) \
+#define TUD_VIDEO_DESC_IAD(_firstitf, _nitfs, _stridx) \
TUD_VIDEO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, \
- _firstitfs, _nitfs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_INTERFACE_COLLECTION, \
+ _firstitf, _nitfs, TUSB_CLASS_VIDEO, VIDEO_SUBCLASS_INTERFACE_COLLECTION, \
VIDEO_ITF_PROTOCOL_UNDEFINED, _stridx
#define TUD_VIDEO_DESC_STD_VC(_itfnum, _nEPs, _stridx) \
@@ -537,7 +652,7 @@ TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not c
/* Motion-JPEG 3.1.1 Table 3-2 and 3-4 */
#define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \
TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \
- TUSB_DESC_CS_INTERFACE, VIDEO_CS_VS_INTERFACE_FRAME_MJPEG, \
+ TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_MJPEG, \
_frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \
U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__
diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c
index d6e98602b..4218835aa 100644
--- a/src/class/video/video_device.c
+++ b/src/class/video/video_device.c
@@ -34,22 +34,33 @@
#include "video_device.h"
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUD_VIDEO_LOG_LEVEL
+ #define CFG_TUD_VIDEO_LOG_LEVEL CFG_TUD_LOG_LEVEL
+#endif
+
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_VIDEO_LOG_LEVEL, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+#define VS_STATE_PROBING 0 /* Configuration in progress */
+#define VS_STATE_COMMITTED 1 /* Ready for streaming or Streaming via bulk endpoint */
+#define VS_STATE_STREAMING 2 /* Streaming via isochronous endpoint */
+
typedef struct {
tusb_desc_interface_t std;
- tusb_desc_cs_video_ctl_itf_hdr_t ctl;
+ tusb_desc_video_control_header_t ctl;
} tusb_desc_vc_itf_t;
typedef struct {
tusb_desc_interface_t std;
- tusb_desc_cs_video_stm_itf_hdr_t stm;
+ tusb_desc_video_streaming_inout_header_t stm;
} tusb_desc_vs_itf_t;
typedef union {
- tusb_desc_cs_video_ctl_itf_hdr_t ctl;
- tusb_desc_cs_video_stm_itf_hdr_t stm;
+ tusb_desc_video_control_header_t ctl;
+ tusb_desc_video_streaming_inout_header_t stm;
} tusb_desc_video_itf_hdr_t;
typedef struct TU_ATTR_PACKED {
@@ -67,9 +78,9 @@ typedef union {
uint8_t bFormatIndex;
uint8_t bNumFrameDescriptors;
};
- tusb_desc_cs_video_fmt_uncompressed_t uncompressed;
- tusb_desc_cs_video_fmt_mjpeg_t mjpeg;
- tusb_desc_cs_video_fmt_frame_based_t frame_based;
+ tusb_desc_video_format_uncompressed_t uncompressed;
+ tusb_desc_video_format_mjpeg_t mjpeg;
+ tusb_desc_video_format_framebased_t frame_based;
} tusb_desc_cs_video_fmt_t;
typedef union {
@@ -82,9 +93,9 @@ typedef union {
uint16_t wWidth;
uint16_t wHeight;
};
- tusb_desc_cs_video_frm_uncompressed_t uncompressed;
- tusb_desc_cs_video_frm_mjpeg_t mjpeg;
- tusb_desc_cs_video_frm_frame_based_t frame_based;
+ tusb_desc_video_frame_uncompressed_t uncompressed;
+ tusb_desc_video_frame_mjpeg_t mjpeg;
+ tusb_desc_video_frame_framebased_t frame_based;
} tusb_desc_cs_video_frm_t;
/* video streaming interface */
@@ -102,6 +113,9 @@ typedef struct TU_ATTR_PACKED {
uint32_t offset; /* offset for the next payload transfer */
uint32_t max_payload_transfer_size;
uint8_t error_code;/* error code */
+ uint8_t state; /* 0:probing 1:committed 2:streaming */
+
+ video_probe_and_commit_control_t probe_commit_payload; /* Probe and Commit control */
/*------------- From this point, data is not cleared by bus reset -------------*/
CFG_TUSB_MEM_ALIGN uint8_t ep_buf[CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE]; /* EP transfer buffer for streaming */
} videod_streaming_interface_t;
@@ -125,19 +139,71 @@ typedef struct TU_ATTR_PACKED {
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_MEM_SECTION tu_static videod_interface_t _videod_itf[CFG_TUD_VIDEO];
-CFG_TUSB_MEM_SECTION tu_static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING];
+CFG_TUD_MEM_SECTION tu_static videod_interface_t _videod_itf[CFG_TUD_VIDEO];
+CFG_TUD_MEM_SECTION tu_static videod_streaming_interface_t _videod_streaming_itf[CFG_TUD_VIDEO_STREAMING];
tu_static uint8_t const _cap_get = 0x1u; /* support for GET */
tu_static uint8_t const _cap_get_set = 0x3u; /* support for GET and SET */
+//--------------------------------------------------------------------+
+// Debug
+//--------------------------------------------------------------------+
+#if CFG_TUSB_DEBUG >= CFG_TUD_VIDEO_LOG_LEVEL
+
+static tu_lookup_entry_t const tu_lookup_video_request[] = {
+ {.key = VIDEO_REQUEST_UNDEFINED, .data = "Undefined"},
+ {.key = VIDEO_REQUEST_SET_CUR, .data = "SetCur"},
+ {.key = VIDEO_REQUEST_SET_CUR_ALL, .data = "SetCurAll"},
+ {.key = VIDEO_REQUEST_GET_CUR, .data = "GetCur"},
+ {.key = VIDEO_REQUEST_GET_MIN, .data = "GetMin"},
+ {.key = VIDEO_REQUEST_GET_MAX, .data = "GetMax"},
+ {.key = VIDEO_REQUEST_GET_RES, .data = "GetRes"},
+ {.key = VIDEO_REQUEST_GET_LEN, .data = "GetLen"},
+ {.key = VIDEO_REQUEST_GET_INFO, .data = "GetInfo"},
+ {.key = VIDEO_REQUEST_GET_DEF, .data = "GetDef"},
+ {.key = VIDEO_REQUEST_GET_CUR_ALL, .data = "GetCurAll"},
+ {.key = VIDEO_REQUEST_GET_MIN_ALL, .data = "GetMinAll"},
+ {.key = VIDEO_REQUEST_GET_MAX_ALL, .data = "GetMaxAll"},
+ {.key = VIDEO_REQUEST_GET_RES_ALL, .data = "GetResAll"},
+ {.key = VIDEO_REQUEST_GET_DEF_ALL, .data = "GetDefAll"},
+};
+
+static tu_lookup_table_t const tu_table_video_request = {
+ .count = TU_ARRAY_SIZE(tu_lookup_video_request),
+ .items = tu_lookup_video_request
+};
+
+static char const* const tu_str_video_vc_control_selector[] = {
+ "Undefined",
+ "Video Power Mode",
+ "Request Error Code",
+};
+
+static char const* const tu_str_video_vs_control_selector[] = {
+ "Undefined",
+ "Probe",
+ "Commit",
+ "Still Probe",
+ "Still Commit",
+ "Still Image Trigger",
+ "Stream Error Code",
+ "Generate Key Frame",
+ "Update Frame Segment",
+ "Sync Delay",
+};
+
+#endif
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
/** Get interface number from the interface descriptor
*
* @param[in] desc interface descriptor
*
* @return bInterfaceNumber */
-static inline uint8_t _desc_itfnum(void const *desc)
-{
+static inline uint8_t _desc_itfnum(void const *desc) {
return ((uint8_t const*)desc)[2];
}
@@ -146,8 +212,7 @@ static inline uint8_t _desc_itfnum(void const *desc)
* @param[in] desc endpoint descriptor
*
* @return bEndpointAddress */
-static inline uint8_t _desc_ep_addr(void const *desc)
-{
+static inline uint8_t _desc_ep_addr(void const *desc) {
return ((uint8_t const*)desc)[2];
}
@@ -157,8 +222,7 @@ static inline uint8_t _desc_ep_addr(void const *desc)
* @param[in] stm_idx index number of streaming interface
*
* @return instance */
-static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx)
-{
+static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) {
videod_interface_t *ctl = &_videod_itf[ctl_idx];
if (!ctl->beg) return NULL;
videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]];
@@ -166,13 +230,11 @@ static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_id
return stm;
}
-static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self)
-{
+static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) {
return (tusb_desc_vc_itf_t const *)(self->beg + self->cur);
}
-static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self)
-{
+static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) {
if (!self->desc.cur) return NULL;
uint8_t const *desc = _videod_itf[self->index_vc].beg;
return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur);
@@ -186,8 +248,7 @@ static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const
*
* @return The pointer for interface descriptor.
* @retval end did not found interface descriptor */
-static void const* _find_desc(void const *beg, void const *end, uint_fast8_t desc_type)
-{
+static void const* _find_desc(void const *beg, void const *end, uint_fast8_t desc_type) {
void const *cur = beg;
while ((cur < end) && (desc_type != tu_desc_type(cur))) {
cur = tu_desc_next(cur);
@@ -195,6 +256,24 @@ static void const* _find_desc(void const *beg, void const *end, uint_fast8_t des
return cur;
}
+/** Find the first descriptor of two given types
+ *
+ * @param[in] beg The head of descriptor byte array.
+ * @param[in] end The tail of descriptor byte array.
+ * @param[in] desc_type_0 The first target descriptor type.
+ * @param[in] desc_type_1 The second target descriptor type.
+ *
+ * @return The pointer for interface descriptor.
+ * @retval end did not found interface descriptor */
+static void const* _find_desc_2_type(void const *beg, void const *end, uint_fast8_t desc_type_0, uint_fast8_t desc_type_1)
+{
+ void const *cur = beg;
+ while ((cur < end) && (desc_type_0 != tu_desc_type(cur)) && (desc_type_1 != tu_desc_type(cur))) {
+ cur = tu_desc_next(cur);
+ }
+ return cur;
+}
+
/** Find the first descriptor specified by the arguments
*
* @param[in] beg The head of descriptor byte array.
@@ -208,8 +287,7 @@ static void const* _find_desc(void const *beg, void const *end, uint_fast8_t des
static void const* _find_desc_3(void const *beg, void const *end,
uint_fast8_t desc_type,
uint_fast8_t element_0,
- uint_fast8_t element_1)
-{
+ uint_fast8_t element_1) {
for (void const *cur = beg; cur < end; cur = _find_desc(cur, end, desc_type)) {
uint8_t const *p = (uint8_t const *)cur;
if ((p[2] == element_0) && (p[3] == element_1)) {
@@ -221,19 +299,22 @@ static void const* _find_desc_3(void const *beg, void const *end,
}
/** Return the next interface descriptor which has another interface number.
+ * If there are multiple VC interfaces, there will be an IAD descriptor before
+ * the next interface descriptor. Check both the IAD descriptor and the interface
+ * descriptor.
+ * 3.1 Descriptor Layout Overview
*
* @param[in] beg The head of descriptor byte array.
* @param[in] end The tail of descriptor byte array.
*
* @return The pointer for interface descriptor.
* @retval end did not found interface descriptor */
-static void const* _next_desc_itf(void const *beg, void const *end)
-{
+static void const* _next_desc_itf(void const *beg, void const *end) {
void const *cur = beg;
uint_fast8_t itfnum = ((tusb_desc_interface_t const*)cur)->bInterfaceNumber;
while ((cur < end) &&
(itfnum == ((tusb_desc_interface_t const*)cur)->bInterfaceNumber)) {
- cur = _find_desc(tu_desc_next(cur), end, TUSB_DESC_INTERFACE);
+ cur = _find_desc_2_type(tu_desc_next(cur), end, TUSB_DESC_INTERFACE, TUSB_DESC_INTERFACE_ASSOCIATION);
}
return cur;
}
@@ -379,8 +460,10 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm
case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED:
param->wCompQuality = 1; /* 1 to 10000 */
break;
- case VIDEO_CS_ITF_VS_FORMAT_MJPEG:
+
+ case VIDEO_CS_ITF_VS_FORMAT_MJPEG:
break;
+
default: return false;
}
@@ -401,9 +484,11 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm
case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED:
frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->uncompressed.bBitsPerPixel / 8;
break;
+
case VIDEO_CS_ITF_VS_FORMAT_MJPEG:
frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * 16 / 8; /* YUV422 */
break;
+
default: break;
}
param->dwMaxVideoFrameSize = frame_size;
@@ -422,8 +507,9 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm
uint_fast32_t interval_ms = interval / 10000;
TU_ASSERT(interval_ms);
uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2;
- if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size)
+ if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) {
payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE;
+ }
param->dwMaxPayloadTransferSize = payload_size;
return true;
}
@@ -443,10 +529,12 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *
if (_get_desc_vs(stm))
param->bFormatIndex = _get_desc_vs(stm)->stm.bNumFormats;
break;
+
case VIDEO_REQUEST_GET_MIN:
case VIDEO_REQUEST_GET_DEF:
param->bFormatIndex = 1;
break;
+
default: return false;
}
/* Set the parameters determined by the format */
@@ -475,18 +563,22 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *
case VIDEO_REQUEST_GET_MAX:
frmnum = fmt->bNumFrameDescriptors;
break;
+
case VIDEO_REQUEST_GET_MIN:
frmnum = 1;
break;
+
case VIDEO_REQUEST_GET_DEF:
switch (fmt->bDescriptorSubType) {
- case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED:
- frmnum = fmt->uncompressed.bDefaultFrameIndex;
- break;
- case VIDEO_CS_ITF_VS_FORMAT_MJPEG:
- frmnum = fmt->mjpeg.bDefaultFrameIndex;
- break;
- default: return false;
+ case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED:
+ frmnum = fmt->uncompressed.bDefaultFrameIndex;
+ break;
+
+ case VIDEO_CS_ITF_VS_FORMAT_MJPEG:
+ frmnum = fmt->mjpeg.bDefaultFrameIndex;
+ break;
+
+ default: return false;
}
break;
default: return false;
@@ -499,9 +591,11 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *
case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED:
frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->uncompressed.bBitsPerPixel / 8;
break;
+
case VIDEO_CS_ITF_VS_FORMAT_MJPEG:
frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * 16 / 8; /* YUV422 */
break;
+
default: return false;
}
param->dwMaxVideoFrameSize = frame_size;
@@ -517,41 +611,43 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *
uint_fast32_t interval, interval_ms;
switch (request) {
- case VIDEO_REQUEST_GET_MAX:
- {
- uint_fast32_t min_interval, max_interval;
- uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType;
- max_interval = num_intervals ? frm->uncompressed.dwFrameInterval[num_intervals - 1]: frm->uncompressed.dwFrameInterval[1];
- min_interval = frm->uncompressed.dwFrameInterval[0];
- interval = max_interval;
- interval_ms = min_interval / 10000;
- }
+ case VIDEO_REQUEST_GET_MAX: {
+ uint_fast32_t min_interval, max_interval;
+ uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType;
+ max_interval = num_intervals ? frm->uncompressed.dwFrameInterval[num_intervals - 1]: frm->uncompressed.dwFrameInterval[1];
+ min_interval = frm->uncompressed.dwFrameInterval[0];
+ interval = max_interval;
+ interval_ms = min_interval / 10000;
break;
- case VIDEO_REQUEST_GET_MIN:
- {
- uint_fast32_t min_interval, max_interval;
- uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType;
- max_interval = num_intervals ? frm->uncompressed.dwFrameInterval[num_intervals - 1]: frm->uncompressed.dwFrameInterval[1];
- min_interval = frm->uncompressed.dwFrameInterval[0];
- interval = min_interval;
- interval_ms = max_interval / 10000;
- }
+ }
+
+ case VIDEO_REQUEST_GET_MIN: {
+ uint_fast32_t min_interval, max_interval;
+ uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType;
+ max_interval = num_intervals ? frm->uncompressed.dwFrameInterval[num_intervals - 1]: frm->uncompressed.dwFrameInterval[1];
+ min_interval = frm->uncompressed.dwFrameInterval[0];
+ interval = min_interval;
+ interval_ms = max_interval / 10000;
break;
+ }
+
case VIDEO_REQUEST_GET_DEF:
interval = frm->uncompressed.dwDefaultFrameInterval;
interval_ms = interval / 10000;
break;
- case VIDEO_REQUEST_GET_RES:
- {
- uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType;
- if (num_intervals) {
- interval = 0;
- } else {
- interval = frm->uncompressed.dwFrameInterval[2];
- interval_ms = interval / 10000;
- }
+
+ case VIDEO_REQUEST_GET_RES: {
+ uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType;
+ if (num_intervals) {
+ interval = 0;
+ interval_ms = 0;
+ } else {
+ interval = frm->uncompressed.dwFrameInterval[2];
+ interval_ms = interval / 10000;
}
break;
+ }
+
default: return false;
}
param->dwFrameInterval = interval;
@@ -565,8 +661,9 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const *
} else {
payload_size = (frame_size + interval_ms - 1) / interval_ms + 2;
}
- if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size)
+ if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) {
payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE;
+ }
param->dwMaxPayloadTransferSize = payload_size;
}
return true;
@@ -604,17 +701,17 @@ static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self)
* @param[in] altnum The target alternate setting number. */
static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t altnum)
{
- TU_LOG2(" open VC %d\n", altnum);
+ TU_LOG_DRV(" open VC %d\r\n", altnum);
uint8_t const *beg = self->beg;
uint8_t const *end = beg + self->len;
/* The first descriptor is a video control interface descriptor. */
uint8_t const *cur = _find_desc_itf(beg, end, _desc_itfnum(beg), altnum);
- TU_LOG2(" cur %d\n", cur - beg);
+ TU_LOG_DRV(" cur %d\r\n", cur - beg);
TU_VERIFY(cur < end);
tusb_desc_vc_itf_t const *vc = (tusb_desc_vc_itf_t const *)cur;
- TU_LOG2(" bInCollection %d\n", vc->ctl.bInCollection);
+ TU_LOG_DRV(" bInCollection %d\r\n", vc->ctl.bInCollection);
/* Support for up to 2 streaming interfaces only. */
TU_ASSERT(vc->ctl.bInCollection <= CFG_TUD_VIDEO_STREAMING);
@@ -623,7 +720,7 @@ static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t
/* Advance to the next descriptor after the class-specific VC interface header descriptor. */
cur += vc->std.bLength + vc->ctl.bLength;
- TU_LOG2(" bNumEndpoints %d\n", vc->std.bNumEndpoints);
+ TU_LOG_DRV(" bNumEndpoints %d\r\n", vc->std.bNumEndpoints);
/* Open the notification endpoint if it exist. */
if (vc->std.bNumEndpoints) {
/* Support for 1 endpoint only. */
@@ -639,6 +736,15 @@ static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t
return true;
}
+static bool _init_vs_configuration(videod_streaming_interface_t *stm) {
+ /* initialize streaming settings */
+ stm->state = VS_STATE_PROBING;
+ stm->max_payload_transfer_size = 0;
+ video_probe_and_commit_control_t *param = &stm->probe_commit_payload;
+ tu_memclr(param, sizeof(*param));
+ return _update_streaming_parameters(stm, param);
+}
+
/** Set the alternate setting to own video streaming interface.
*
* @param[in,out] stm Streaming interface context.
@@ -646,18 +752,23 @@ static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t
static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint_fast8_t altnum)
{
uint_fast8_t i;
- TU_LOG2(" reopen VS %d\n", altnum);
+ TU_LOG_DRV(" reopen VS %d\r\n", altnum);
uint8_t const *desc = _videod_itf[stm->index_vc].beg;
+#ifndef TUP_DCD_EDPT_ISO_ALLOC
/* Close endpoints of previous settings. */
for (i = 0; i < TU_ARRAY_SIZE(stm->desc.ep); ++i) {
uint_fast16_t ofs_ep = stm->desc.ep[i];
if (!ofs_ep) break;
- uint8_t ep_adr = _desc_ep_addr(desc + ofs_ep);
- usbd_edpt_close(rhport, ep_adr);
- stm->desc.ep[i] = 0;
- TU_LOG2(" close EP%02x\n", ep_adr);
+ tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)(desc + ofs_ep);
+ /* Only ISO endpoints needs to be closed */
+ if(ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
+ stm->desc.ep[i] = 0;
+ usbd_edpt_close(rhport, ep->bEndpointAddress);
+ TU_LOG_DRV(" close EP%02x\r\n", ep->bEndpointAddress);
+ }
}
+#endif
/* clear transfer management information */
stm->buffer = NULL;
@@ -672,43 +783,35 @@ static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint
uint_fast8_t numeps = ((tusb_desc_interface_t const *)cur)->bNumEndpoints;
TU_ASSERT(numeps <= TU_ARRAY_SIZE(stm->desc.ep));
- stm->desc.cur = (uint16_t) (cur - desc); /* Save the offset of the new settings */
- if (!altnum) {
- /* initialize streaming settings */
- stm->max_payload_transfer_size = 0;
- video_probe_and_commit_control_t *param =
- (video_probe_and_commit_control_t *)&stm->ep_buf;
- tu_memclr(param, sizeof(*param));
- TU_LOG2(" done 0\n");
- return _update_streaming_parameters(stm, param);
+ stm->desc.cur = (uint16_t)(cur - desc); /* Save the offset of the new settings */
+ if (!altnum && (VS_STATE_COMMITTED != stm->state)) {
+ TU_VERIFY(_init_vs_configuration(stm));
}
- /* Open endpoints of the new settings. */
+ /* Open bulk or isochronous endpoints of the new settings. */
for (i = 0, cur = tu_desc_next(cur); i < numeps; ++i, cur = tu_desc_next(cur)) {
cur = _find_desc_ep(cur, end);
TU_ASSERT(cur < end);
tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)cur;
- if (!stm->max_payload_transfer_size) {
- video_probe_and_commit_control_t const *param = (video_probe_and_commit_control_t const*)&stm->ep_buf;
- uint_fast32_t max_size = param->dwMaxPayloadTransferSize;
- if ((TUSB_XFER_ISOCHRONOUS == ep->bmAttributes.xfer) &&
- (tu_edpt_packet_size(ep) < max_size))
- {
- /* FS must be less than or equal to max packet size */
- return false;
- }
- /* Set the negotiated value */
- stm->max_payload_transfer_size = max_size;
+ uint_fast32_t max_size = stm->max_payload_transfer_size;
+ if (altnum && (TUSB_XFER_ISOCHRONOUS == ep->bmAttributes.xfer)) {
+ /* FS must be less than or equal to max packet size */
+ TU_VERIFY (tu_edpt_packet_size(ep) >= max_size);
+#ifdef TUP_DCD_EDPT_ISO_ALLOC
+ usbd_edpt_iso_activate(rhport, ep);
+#else
+ TU_ASSERT(usbd_edpt_open(rhport, ep));
+#endif
+ } else {
+ TU_VERIFY(TUSB_XFER_BULK == ep->bmAttributes.xfer);
+ TU_ASSERT(usbd_edpt_open(rhport, ep));
}
- TU_ASSERT(usbd_edpt_open(rhport, ep));
stm->desc.ep[i] = (uint16_t) (cur - desc);
- TU_LOG2(" open EP%02x\n", _desc_ep_addr(cur));
+ TU_LOG_DRV(" open EP%02x\r\n", _desc_ep_addr(cur));
}
- /* initialize payload header */
- tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm->ep_buf;
- hdr->bHeaderLength = sizeof(*hdr);
- hdr->bmHeaderInfo = 0;
-
- TU_LOG2(" done\n");
+ if (altnum) {
+ stm->state = VS_STATE_STREAMING;
+ }
+ TU_LOG_DRV(" done\r\n");
return true;
}
@@ -721,6 +824,7 @@ static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm)
if (hdr_len + remaining < pkt_len) {
pkt_len = hdr_len + remaining;
}
+ TU_ASSERT(pkt_len >= hdr_len);
uint_fast16_t data_len = pkt_len - hdr_len;
memcpy(&stm->ep_buf[hdr_len], stm->buffer + stm->offset, data_len);
stm->offset += data_len;
@@ -737,6 +841,7 @@ static int handle_video_ctl_std_req(uint8_t rhport, uint8_t stage,
tusb_control_request_t const *request,
uint_fast8_t ctl_idx)
{
+ TU_LOG_DRV("\r\n");
switch (request->bRequest) {
case TUSB_REQ_GET_INTERFACE:
if (stage == CONTROL_STAGE_SETUP)
@@ -774,7 +879,10 @@ static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage,
videod_interface_t *self = &_videod_itf[ctl_idx];
/* 4.2.1 Interface Control Request */
- switch (TU_U16_HIGH(request->wValue)) {
+ uint8_t const ctrl_sel = TU_U16_HIGH(request->wValue);
+ TU_LOG_DRV("%s_Control(%s)\r\n", tu_str_video_vc_control_selector[ctrl_sel], tu_lookup_find(&tu_table_video_request, request->bRequest));
+
+ switch (ctrl_sel) {
case VIDEO_VC_CTL_VIDEO_POWER_MODE:
switch (request->bRequest) {
case VIDEO_REQUEST_SET_CUR:
@@ -838,19 +946,19 @@ static int handle_video_ctl_req(uint8_t rhport, uint8_t stage,
tusb_control_request_t const *request,
uint_fast8_t ctl_idx)
{
- uint_fast8_t entity_id;
switch (request->bmRequestType_bit.type) {
case TUSB_REQ_TYPE_STANDARD:
return handle_video_ctl_std_req(rhport, stage, request, ctl_idx);
- case TUSB_REQ_TYPE_CLASS:
- entity_id = TU_U16_HIGH(request->wIndex);
+ case TUSB_REQ_TYPE_CLASS: {
+ uint_fast8_t entity_id = TU_U16_HIGH(request->wIndex);
if (!entity_id) {
return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx);
} else {
TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST);
return VIDEO_ERROR_NONE;
}
+ }
default:
return VIDEO_ERROR_INVALID_REQUEST;
@@ -861,6 +969,7 @@ static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage,
tusb_control_request_t const *request,
uint_fast8_t stm_idx)
{
+ TU_LOG_DRV("\r\n");
videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx];
switch (request->bRequest) {
case TUSB_REQ_GET_INTERFACE:
@@ -876,8 +985,7 @@ static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage,
return VIDEO_ERROR_NONE;
case TUSB_REQ_SET_INTERFACE:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(_open_vs_itf(rhport, self, request->wValue), VIDEO_ERROR_UNKNOWN);
tud_control_status(rhport, request);
}
@@ -891,26 +999,26 @@ static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage,
static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
tusb_control_request_t const *request,
- uint_fast8_t stm_idx)
-{
+ uint_fast8_t stm_idx) {
(void)rhport;
videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx];
+ uint8_t const ctrl_sel = TU_U16_HIGH(request->wValue);
+ TU_LOG_DRV("%s_Control(%s)\r\n", tu_str_video_vs_control_selector[ctrl_sel], tu_lookup_find(&tu_table_video_request, request->bRequest));
+
/* 4.2.1 Interface Control Request */
- switch (TU_U16_HIGH(request->wValue)) {
+ switch (ctrl_sel) {
case VIDEO_VS_CTL_STREAM_ERROR_CODE:
switch (request->bRequest) {
case VIDEO_REQUEST_GET_CUR:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
/* TODO */
TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
case VIDEO_REQUEST_GET_INFO:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
@@ -920,23 +1028,25 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
break;
case VIDEO_VS_CTL_PROBE:
+ if (self->state != VS_STATE_PROBING) {
+ self->state = VS_STATE_PROBING;
+ }
+
switch (request->bRequest) {
case VIDEO_REQUEST_SET_CUR:
if (stage == CONTROL_STAGE_SETUP) {
- TU_VERIFY(sizeof(video_probe_and_commit_control_t) >= request->wLength, VIDEO_ERROR_UNKNOWN);
- TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)),
+ TU_VERIFY(tud_control_xfer(rhport, request, &self->probe_commit_payload, sizeof(video_probe_and_commit_control_t)),
VIDEO_ERROR_UNKNOWN);
} else if (stage == CONTROL_STAGE_DATA) {
- TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf),
+ TU_VERIFY(_update_streaming_parameters(self, &self->probe_commit_payload),
VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
}
return VIDEO_ERROR_NONE;
case VIDEO_REQUEST_GET_CUR:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN);
- TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
+ TU_VERIFY(tud_control_xfer(rhport, request, &self->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
@@ -944,19 +1054,16 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
case VIDEO_REQUEST_GET_MAX:
case VIDEO_REQUEST_GET_RES:
case VIDEO_REQUEST_GET_DEF:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN);
- video_probe_and_commit_control_t tmp;
- tmp = *(video_probe_and_commit_control_t*)&self->ep_buf;
+ video_probe_and_commit_control_t tmp = self->probe_commit_payload;
TU_VERIFY(_negotiate_streaming_parameters(self, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
TU_VERIFY(tud_control_xfer(rhport, request, &tmp, sizeof(tmp)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
case VIDEO_REQUEST_GET_LEN:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN);
uint16_t len = sizeof(video_probe_and_commit_control_t);
TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN);
@@ -964,8 +1071,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
return VIDEO_ERROR_NONE;
case VIDEO_REQUEST_GET_INFO:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN);
TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t)&_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN);
}
@@ -979,27 +1085,38 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
switch (request->bRequest) {
case VIDEO_REQUEST_SET_CUR:
if (stage == CONTROL_STAGE_SETUP) {
- TU_VERIFY(sizeof(video_probe_and_commit_control_t) >= request->wLength, VIDEO_ERROR_UNKNOWN);
- TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
+ TU_VERIFY(tud_control_xfer(rhport, request, &self->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
} else if (stage == CONTROL_STAGE_DATA) {
- TU_VERIFY(_update_streaming_parameters(self, (video_probe_and_commit_control_t*)self->ep_buf), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
+ video_probe_and_commit_control_t *param = &self->probe_commit_payload;
+ TU_VERIFY(_update_streaming_parameters(self, param), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE);
+ /* Set the negotiated value */
+ self->max_payload_transfer_size = param->dwMaxPayloadTransferSize;
+ int ret = VIDEO_ERROR_NONE;
if (tud_video_commit_cb) {
- return tud_video_commit_cb(self->index_vc, self->index_vs, (video_probe_and_commit_control_t*)self->ep_buf);
+ ret = tud_video_commit_cb(self->index_vc, self->index_vs, param);
+ }
+ if (VIDEO_ERROR_NONE == ret) {
+ self->state = VS_STATE_COMMITTED;
+ self->buffer = NULL;
+ self->bufsize = 0;
+ self->offset = 0;
+ /* initialize payload header */
+ tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)self->ep_buf;
+ hdr->bHeaderLength = sizeof(*hdr);
+ hdr->bmHeaderInfo = 0;
}
}
return VIDEO_ERROR_NONE;
case VIDEO_REQUEST_GET_CUR:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN);
- TU_VERIFY(tud_control_xfer(rhport, request, self->ep_buf, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
+ TU_VERIFY(tud_control_xfer(rhport, request, &self->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN);
}
return VIDEO_ERROR_NONE;
case VIDEO_REQUEST_GET_LEN:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(2 == request->wLength, VIDEO_ERROR_UNKNOWN);
uint16_t len = sizeof(video_probe_and_commit_control_t);
TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)&len, sizeof(len)), VIDEO_ERROR_UNKNOWN);
@@ -1007,8 +1124,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
return VIDEO_ERROR_NONE;
case VIDEO_REQUEST_GET_INFO:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN);
TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN);
}
@@ -1069,6 +1185,17 @@ bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx)
TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING);
videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx);
if (!stm || !stm->desc.ep[0]) return false;
+ if (stm->state == VS_STATE_PROBING) return false;
+
+#ifdef TUP_DCD_EDPT_ISO_ALLOC
+ uint8_t const *desc = _videod_itf[stm->index_vc].beg;
+ uint_fast16_t ofs_ep = stm->desc.ep[0];
+ tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)(desc + ofs_ep);
+ if (ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
+ if (stm->state == VS_STATE_COMMITTED) return false;
+ }
+#endif
+
return true;
}
@@ -1079,6 +1206,7 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu
if (!buffer || !bufsize) return false;
videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx);
if (!stm || !stm->desc.ep[0] || stm->buffer) return false;
+ if (stm->state == VS_STATE_PROBING) return false;
/* Find EP address */
uint8_t const *desc = _videod_itf[stm->index_vc].beg;
@@ -1107,8 +1235,7 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void videod_init(void)
-{
+void videod_init(void) {
for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) {
videod_interface_t* ctl = &_videod_itf[i];
tu_memclr(ctl, sizeof(*ctl));
@@ -1119,8 +1246,11 @@ void videod_init(void)
}
}
-void videod_reset(uint8_t rhport)
-{
+bool videod_deinit(void) {
+ return true;
+}
+
+void videod_reset(uint8_t rhport) {
(void) rhport;
for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO; ++i) {
videod_interface_t* ctl = &_videod_itf[i];
@@ -1132,8 +1262,7 @@ void videod_reset(uint8_t rhport)
}
}
-uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
-{
+uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
TU_VERIFY((TUSB_CLASS_VIDEO == itf_desc->bInterfaceClass) &&
(VIDEO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass) &&
(VIDEO_ITF_PROTOCOL_15 == itf_desc->bInterfaceProtocol), 0);
@@ -1174,6 +1303,34 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
stm->desc.beg = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc);
cur = _next_desc_itf(cur, end);
stm->desc.end = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc);
+ stm->state = VS_STATE_PROBING;
+#ifdef TUP_DCD_EDPT_ISO_ALLOC
+ /* Allocate ISO endpoints */
+ uint16_t ep_size = 0;
+ uint16_t ep_addr = 0;
+ uint8_t const *p_desc = (uint8_t const*)itf_desc + stm->desc.beg;
+ uint8_t const *p_desc_end = (uint8_t const*)itf_desc + stm->desc.end;
+ while (p_desc < p_desc_end) {
+ if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
+ tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
+ ep_addr = desc_ep->bEndpointAddress;
+ ep_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_size);
+ }
+ }
+ p_desc = tu_desc_next(p_desc);
+ }
+ if(ep_addr > 0 && ep_size > 0) usbd_edpt_iso_alloc(rhport, ep_addr, ep_size);
+#endif
+ if (0 == stm_idx && 1 == bInCollection) {
+ /* If there is only one streaming interface and no alternate settings,
+ * host may not issue set_interface so open the streaming interface here. */
+ uint8_t const *sbeg = (uint8_t const*)itf_desc + stm->desc.beg;
+ uint8_t const *send = (uint8_t const*)itf_desc + stm->desc.end;
+ if (send == _find_desc_itf(sbeg, send, _desc_itfnum(sbeg), 1)) {
+ TU_VERIFY(_open_vs_itf(rhport, stm, 0), 0);
+ }
+ }
}
self->len = (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc);
return (uint16_t) ((uintptr_t)cur - (uintptr_t)itf_desc);
@@ -1182,12 +1339,10 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
+bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) {
int err;
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
uint_fast8_t itfnum = tu_u16_low(request->wIndex);
-
/* Identify which control interface to use */
uint_fast8_t itf;
for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) {
@@ -1197,6 +1352,7 @@ bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_
}
if (itf < CFG_TUD_VIDEO) {
+ TU_LOG_DRV(" VC[%d]: ", itf);
err = handle_video_ctl_req(rhport, stage, request, itf);
_videod_itf[itf].error_code = (uint8_t)err;
if (err) return false;
@@ -1212,6 +1368,7 @@ bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_
}
if (itf < CFG_TUD_VIDEO_STREAMING) {
+ TU_LOG_DRV(" VS[%d]: ", itf);
err = handle_video_stm_req(rhport, stage, request, itf);
_videod_streaming_itf[itf].error_code = (uint8_t)err;
if (err) return false;
@@ -1220,8 +1377,7 @@ bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_
return false;
}
-bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
+bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void)result; (void)xferred_bytes;
/* find streaming handle */
diff --git a/src/class/video/video_device.h b/src/class/video/video_device.h
index ee2fcb9d5..92930c013 100644
--- a/src/class/video/video_device.h
+++ b/src/class/video/video_device.h
@@ -85,6 +85,7 @@ TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx,
// INTERNAL USBD-CLASS DRIVER API
//--------------------------------------------------------------------+
void videod_init (void);
+bool videod_deinit (void);
void videod_reset (uint8_t rhport);
uint16_t videod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h
index 957491aa9..1f08ce4ed 100644
--- a/src/common/tusb_common.h
+++ b/src/common/tusb_common.h
@@ -37,6 +37,7 @@
#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) )
#define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) )
#define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) )
+#define TU_DIV_CEIL(n, d) (((n) + (d) - 1) / (d))
#define TU_U16(_high, _low) ((uint16_t) (((_high) << 8) | (_low)))
#define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff))
@@ -53,6 +54,8 @@
#define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32)
#define TU_BIT(n) (1UL << (n))
+
+// Generate a mask with bit from high (31) to low (0) set, e.g TU_GENMASK(3, 0) = 0b1111
#define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) )
//--------------------------------------------------------------------+
@@ -73,8 +76,6 @@
#include "tusb_types.h"
#include "tusb_debug.h"
-#include "tusb_timeout.h" // TODO remove
-
//--------------------------------------------------------------------+
// Optional API implemented by application if needed
// TODO move to a more ovious place/file
@@ -99,10 +100,9 @@ TU_ATTR_WEAK extern void* tusb_app_phys_to_virt(void *phys_addr);
#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var)))
// This is a backport of memset_s from c11
-TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, int ch, size_t count)
-{
+TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, int ch, size_t count) {
// TODO may check if desst and src is not NULL
- if (count > destsz) {
+ if ( count > destsz ) {
return -1;
}
memset(dest, ch, count);
@@ -110,10 +110,9 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, i
}
// This is a backport of memcpy_s from c11
-TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void * src, size_t count )
-{
+TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count) {
// TODO may check if desst and src is not NULL
- if (count > destsz) {
+ if ( count > destsz ) {
return -1;
}
memcpy(dest, src, count);
@@ -122,13 +121,11 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, c
//------------- Bytes -------------//
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) {
return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0;
}
-TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) {
return (uint16_t) ((((uint16_t) high) << 8) | low);
}
@@ -159,16 +156,20 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_max16 (uint16_t x, uint16_t y) {
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_max32 (uint32_t x, uint32_t y) { return (x > y) ? x : y; }
//------------- Align -------------//
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align(uint32_t value, uint32_t alignment) {
return value & ((uint32_t) ~(alignment-1));
}
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4 (uint32_t value) { return (value & 0xFFFFFFFCUL); }
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align8 (uint32_t value) { return (value & 0xFFFFFFF8UL); }
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); }
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); }
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); }
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); }
+TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned32(uint32_t value) { return (value & 0x1FUL) == 0; }
+TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned64(uint64_t value) { return (value & 0x3FUL) == 0; }
+
//------------- Mathematics -------------//
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; }
@@ -260,11 +261,21 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_
#else
// MCU that could access unaligned memory natively
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32 (const void* mem) { return *((uint32_t const *) mem); }
-TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16 (const void* mem) { return *((uint16_t const *) mem); }
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void *mem) {
+ return *((uint32_t const *) mem);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void *mem) {
+ return *((uint16_t const *) mem);
+}
-TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32 (void* mem, uint32_t value ) { *((uint32_t*) mem) = value; }
-TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16 (void* mem, uint16_t value ) { *((uint16_t*) mem) = value; }
+TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void *mem, uint32_t value) {
+ *((uint32_t *) mem) = value;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_t value) {
+ *((uint16_t *) mem) = value;
+}
#endif
diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h
index 5ab56e145..0d5570b1c 100644
--- a/src/common/tusb_compiler.h
+++ b/src/common/tusb_compiler.h
@@ -56,7 +56,7 @@
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define TU_VERIFY_STATIC _Static_assert
#elif defined(__CCRX__)
- #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0];
+ #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(_verify_static_, _TU_COUNTER_)[(const_expr) ? 1 : 0];
#else
#define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) }
#endif
@@ -128,7 +128,9 @@
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
#define TU_ATTR_PACKED __attribute__ ((packed))
#define TU_ATTR_WEAK __attribute__ ((weak))
- #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
+ #ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug
+ #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
+ #endif
#define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
#define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used
@@ -205,7 +207,9 @@
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
#define TU_ATTR_PACKED __attribute__ ((packed))
#define TU_ATTR_WEAK __attribute__ ((weak))
- #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
+ #ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug
+ #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
+ #endif
#define TU_ATTR_DEPRECATED(mess) __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
#define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used
diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h
index 82f682043..2e9f1d9cd 100644
--- a/src/common/tusb_debug.h
+++ b/src/common/tusb_debug.h
@@ -43,9 +43,10 @@
#if CFG_TUSB_DEBUG
// Enum to String for debugging purposes
-#if CFG_TUSB_DEBUG >= 2
+#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL || CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
extern char const* const tu_str_speed[];
extern char const* const tu_str_std_request[];
+extern char const* const tu_str_xfer_result[];
#endif
void tu_print_mem(void const *buf, uint32_t count, uint8_t indent);
@@ -57,16 +58,15 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent);
#define tu_printf printf
#endif
-static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize)
-{
+static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) {
for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]);
+ tu_printf("\r\n");
}
// Log with Level
#define TU_LOG(n, ...) TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__)
#define TU_LOG_MEM(n, ...) TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__)
-#define TU_LOG_ARR(n, ...) TU_XSTRCAT3(TU_LOG, n, _ARR)(__VA_ARGS__)
-#define TU_LOG_PTR(n, ...) TU_XSTRCAT3(TU_LOG, n, _PTR)(__VA_ARGS__)
+#define TU_LOG_BUF(n, ...) TU_XSTRCAT3(TU_LOG, n, _BUF)(__VA_ARGS__)
#define TU_LOG_INT(n, ...) TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__)
#define TU_LOG_HEX(n, ...) TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__)
#define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
@@ -75,17 +75,15 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize)
// Log Level 1: Error
#define TU_LOG1 tu_printf
#define TU_LOG1_MEM tu_print_mem
-#define TU_LOG1_ARR(_x, _n) tu_print_arr((uint8_t const*)(_x), _n)
-#define TU_LOG1_PTR(_x) tu_print_arr((uint8_t const*)(_x), sizeof(*(_x)))
+#define TU_LOG1_BUF(_x, _n) tu_print_buf((uint8_t const*)(_x), _n)
#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (unsigned long) (_x) )
-#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (unsigned long) (_x) )
+#define TU_LOG1_HEX(_x) tu_printf(#_x " = 0x%lX\r\n", (unsigned long) (_x) )
// Log Level 2: Warn
#if CFG_TUSB_DEBUG >= 2
#define TU_LOG2 TU_LOG1
#define TU_LOG2_MEM TU_LOG1_MEM
- #define TU_LOG2_ARR TU_LOG1_ARR
- #define TU_LOG2_PTR TU_LOG1_PTR
+ #define TU_LOG2_BUF TU_LOG1_BUF
#define TU_LOG2_INT TU_LOG1_INT
#define TU_LOG2_HEX TU_LOG1_HEX
#endif
@@ -94,30 +92,25 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize)
#if CFG_TUSB_DEBUG >= 3
#define TU_LOG3 TU_LOG1
#define TU_LOG3_MEM TU_LOG1_MEM
- #define TU_LOG3_ARR TU_LOG1_ARR
- #define TU_LOG3_PTR TU_LOG1_PTR
+ #define TU_LOG3_BUF TU_LOG1_BUF
#define TU_LOG3_INT TU_LOG1_INT
#define TU_LOG3_HEX TU_LOG1_HEX
#endif
-typedef struct
-{
+typedef struct {
uint32_t key;
const char* data;
} tu_lookup_entry_t;
-typedef struct
-{
+typedef struct {
uint16_t count;
tu_lookup_entry_t const* items;
} tu_lookup_table_t;
-static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key)
-{
+static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) {
tu_static char not_found[11];
- for(uint16_t i=0; i<p_table->count; i++)
- {
+ for(uint16_t i=0; i<p_table->count; i++) {
if (p_table->items[i].key == key) return p_table->items[i].data;
}
@@ -132,7 +125,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
#ifndef TU_LOG
#define TU_LOG(n, ...)
#define TU_LOG_MEM(n, ...)
- #define TU_LOG_PTR(n, ...)
+ #define TU_LOG_BUF(n, ...)
#define TU_LOG_INT(n, ...)
#define TU_LOG_HEX(n, ...)
#define TU_LOG_LOCATION()
@@ -143,14 +136,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
#define TU_LOG0(...)
#define TU_LOG0_MEM(...)
-#define TU_LOG0_PTR(...)
+#define TU_LOG0_BUF(...)
#define TU_LOG0_INT(...)
#define TU_LOG0_HEX(...)
#ifndef TU_LOG1
#define TU_LOG1(...)
#define TU_LOG1_MEM(...)
- #define TU_LOG1_PTR(...)
+ #define TU_LOG1_BUF(...)
#define TU_LOG1_INT(...)
#define TU_LOG1_HEX(...)
#endif
@@ -158,7 +151,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
#ifndef TU_LOG2
#define TU_LOG2(...)
#define TU_LOG2_MEM(...)
- #define TU_LOG2_PTR(...)
+ #define TU_LOG2_BUF(...)
#define TU_LOG2_INT(...)
#define TU_LOG2_HEX(...)
#endif
@@ -166,7 +159,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
#ifndef TU_LOG3
#define TU_LOG3(...)
#define TU_LOG3_MEM(...)
- #define TU_LOG3_PTR(...)
+ #define TU_LOG3_BUF(...)
#define TU_LOG3_INT(...)
#define TU_LOG3_HEX(...)
#endif
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index a52c92267..76696396b 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -224,6 +224,7 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t
if (wrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, wrap_bytes);
}
break;
+ default: break;
}
}
@@ -539,7 +540,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu
// Advance index
f->wr_idx = advance_index(f->depth, wr_idx, n);
- TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\n", f->wr_idx);
+ TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx);
}
_ff_unlock(f->mutex_wr);
diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h
index 2f60ec2f4..2d9f5e667 100644
--- a/src/common/tusb_fifo.h
+++ b/src/common/tusb_fifo.h
@@ -102,10 +102,8 @@ extern "C" {
* |
* -------------------------
* | R | 1 | 2 | W | 4 | 5 |
-
*/
-typedef struct
-{
+typedef struct {
uint8_t* buffer ; // buffer pointer
uint16_t depth ; // max items
@@ -124,16 +122,14 @@ typedef struct
} tu_fifo_t;
-typedef struct
-{
+typedef struct {
uint16_t len_lin ; ///< linear length in item size
uint16_t len_wrap ; ///< wrapped length in item size
void * ptr_lin ; ///< linear part start pointer
void * ptr_wrap ; ///< wrapped part start pointer
} tu_fifo_buffer_info_t;
-#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \
-{ \
+#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable){\
.buffer = _buffer, \
.depth = _depth, \
.item_size = sizeof(_type), \
@@ -144,23 +140,18 @@ typedef struct
uint8_t _name##_buf[_depth*sizeof(_type)]; \
tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable)
-
bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable);
bool tu_fifo_clear(tu_fifo_t *f);
bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable);
#if OSAL_MUTEX_REQUIRED
-TU_ATTR_ALWAYS_INLINE static inline
-void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_mutex)
-{
- f->mutex_wr = wr_mutex;
- f->mutex_rd = rd_mutex;
-}
-
+ TU_ATTR_ALWAYS_INLINE static inline
+ void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_mutex) {
+ f->mutex_wr = wr_mutex;
+ f->mutex_rd = rd_mutex;
+ }
#else
-
-#define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex)
-
+ #define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex)
#endif
bool tu_fifo_write (tu_fifo_t* f, void const * p_data);
@@ -182,8 +173,7 @@ bool tu_fifo_overflowed (tu_fifo_t* f);
void tu_fifo_correct_read_pointer (tu_fifo_t* f);
TU_ATTR_ALWAYS_INLINE static inline
-uint16_t tu_fifo_depth(tu_fifo_t* f)
-{
+uint16_t tu_fifo_depth(tu_fifo_t* f) {
return f->depth;
}
@@ -198,7 +188,6 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n);
void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info);
void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
-
#ifdef __cplusplus
}
#endif
diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h
index ba8976a8c..0ae2573cd 100644
--- a/src/common/tusb_mcu.h
+++ b/src/common/tusb_mcu.h
@@ -34,10 +34,16 @@
//------------- Unaligned Memory Access -------------//
-// ARMv7+ (M3-M7, M23-M33) can access unaligned memory
-#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7))
- #define TUP_ARCH_STRICT_ALIGN 0
+#ifdef __ARM_ARCH
+ // ARM Architecture set __ARM_FEATURE_UNALIGNED to 1 for mcu supports unaligned access
+ #if defined(__ARM_FEATURE_UNALIGNED) && __ARM_FEATURE_UNALIGNED == 1
+ #define TUP_ARCH_STRICT_ALIGN 0
+ #else
+ #define TUP_ARCH_STRICT_ALIGN 1
+ #endif
#else
+ // TODO default to strict align for others
+ // Should investigate other architecture such as risv, xtensa, mips for optimal setting
#define TUP_ARCH_STRICT_ALIGN 1
#endif
@@ -52,6 +58,7 @@
// NXP
//--------------------------------------------------------------------+
#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX)
+ #define TUP_USBIP_IP3511
#define TUP_DCD_ENDPOINT_MAX 5
#elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX)
@@ -59,33 +66,55 @@
#define TUP_USBIP_OHCI
#define TUP_OHCI_RHPORTS 2
-#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
- // TODO USB0 has 6, USB1 has 4
- #define TUP_USBIP_CHIPIDEA_HS
- #define TUP_USBIP_EHCI
-
- #define TUP_DCD_ENDPOINT_MAX 6
- #define TUP_RHPORT_HIGHSPEED 1 // Port0 HS, Port1 FS
-
#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX)
+ #define TUP_USBIP_IP3511
#define TUP_DCD_ENDPOINT_MAX 5
-#elif TU_CHECK_MCU(OPT_MCU_LPC54XXX)
+#elif TU_CHECK_MCU(OPT_MCU_LPC54)
// TODO USB0 has 5, USB1 has 6
+ #define TUP_USBIP_IP3511
#define TUP_DCD_ENDPOINT_MAX 6
-#elif TU_CHECK_MCU(OPT_MCU_LPC55XX)
+#elif TU_CHECK_MCU(OPT_MCU_LPC55)
// TODO USB0 has 5, USB1 has 6
+ #define TUP_USBIP_IP3511
+ #define TUP_DCD_ENDPOINT_MAX 6
+
+#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
+ // USB0 has 6 with HS PHY, USB1 has 4 only FS
+ #define TUP_USBIP_CHIPIDEA_HS
+ #define TUP_USBIP_EHCI
+
#define TUP_DCD_ENDPOINT_MAX 6
+ #define TUP_RHPORT_HIGHSPEED 1
+
+#elif TU_CHECK_MCU(OPT_MCU_MCXN9)
+ // USB0 is chipidea FS
+ #define TUP_USBIP_CHIPIDEA_FS
+ #define TUP_USBIP_CHIPIDEA_FS_MCX
+
+ // USB1 is chipidea HS
+ #define TUP_USBIP_CHIPIDEA_HS
+ #define TUP_USBIP_EHCI
+
+ #define TUP_DCD_ENDPOINT_MAX 8
+ #define TUP_RHPORT_HIGHSPEED 1
+
+#elif TU_CHECK_MCU(OPT_MCU_MCXA15)
+ // USB0 is chipidea FS
+ #define TUP_USBIP_CHIPIDEA_FS
+ #define TUP_USBIP_CHIPIDEA_FS_MCX
-#elif TU_CHECK_MCU(OPT_MCU_MIMXRT)
+ #define TUP_DCD_ENDPOINT_MAX 16
+
+#elif TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX)
#define TUP_USBIP_CHIPIDEA_HS
#define TUP_USBIP_EHCI
#define TUP_DCD_ENDPOINT_MAX 8
- #define TUP_RHPORT_HIGHSPEED 1 // Port0 HS, Port1 HS
+ #define TUP_RHPORT_HIGHSPEED 1
-#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32)
+#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32L, OPT_MCU_KINETIS_K)
#define TUP_USBIP_CHIPIDEA_FS
#define TUP_USBIP_CHIPIDEA_FS_KINETIS
#define TUP_DCD_ENDPOINT_MAX 16
@@ -188,7 +217,22 @@
#define TUP_DCD_ENDPOINT_MAX 9
+#elif TU_CHECK_MCU(OPT_MCU_STM32H5)
+ #define TUP_USBIP_FSDEV
+ #define TUP_USBIP_FSDEV_STM32
+ #define TUP_DCD_ENDPOINT_MAX 8
+
#elif TU_CHECK_MCU(OPT_MCU_STM32G4)
+ // Device controller
+ #define TUP_USBIP_FSDEV
+ #define TUP_USBIP_FSDEV_STM32
+
+ // TypeC controller
+ #define TUP_USBIP_TYPEC_STM32
+ #define TUP_DCD_ENDPOINT_MAX 8
+ #define TUP_TYPEC_RHPORTS_NUM 1
+
+#elif TU_CHECK_MCU(OPT_MCU_STM32G0)
#define TUP_USBIP_FSDEV
#define TUP_USBIP_FSDEV_STM32
#define TUP_DCD_ENDPOINT_MAX 8
@@ -227,14 +271,21 @@
#elif TU_CHECK_MCU(OPT_MCU_STM32U5)
#define TUP_USBIP_DWC2
#define TUP_USBIP_DWC2_STM32
- #define TUP_DCD_ENDPOINT_MAX 6
+
+ // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY
+ #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \
+ defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx)
+ #define TUP_DCD_ENDPOINT_MAX 9
+ #define TUP_RHPORT_HIGHSPEED 1
+ #else
+ #define TUP_DCD_ENDPOINT_MAX 6
+ #endif
#elif TU_CHECK_MCU(OPT_MCU_STM32L5)
#define TUP_USBIP_FSDEV
#define TUP_USBIP_FSDEV_STM32
#define TUP_DCD_ENDPOINT_MAX 8
-
//--------------------------------------------------------------------+
// Sony
//--------------------------------------------------------------------+
@@ -303,6 +354,7 @@
// Renesas
//--------------------------------------------------------------------+
#elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N, OPT_MCU_RAXXX)
+ #define TUP_USBIP_RUSB2
#define TUP_DCD_ENDPOINT_MAX 10
//--------------------------------------------------------------------+
@@ -348,8 +400,24 @@
#elif TU_CHECK_MCU(OPT_MCU_CH32V307)
#define TUP_DCD_ENDPOINT_MAX 16
#define TUP_RHPORT_HIGHSPEED 1
+
+#elif TU_CHECK_MCU(OPT_MCU_CH32F20X)
+ #define TUP_DCD_ENDPOINT_MAX 16
+ #define TUP_RHPORT_HIGHSPEED 1
+#endif
+
+
+//--------------------------------------------------------------------+
+// External USB controller
+//--------------------------------------------------------------------+
+
+#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
+ #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL
+ #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1))
+ #endif
#endif
+
//--------------------------------------------------------------------+
// Default Values
//--------------------------------------------------------------------+
@@ -373,4 +441,8 @@
#define TU_ATTR_FAST_FUNC
#endif
+#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV)
+ #define TUP_DCD_EDPT_ISO_ALLOC
+#endif
+
#endif
diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h
index d5541856c..373a50256 100644
--- a/src/common/tusb_private.h
+++ b/src/common/tusb_private.h
@@ -60,7 +60,7 @@ typedef struct {
tu_fifo_t ff;
// mutex: read if ep rx, write if e tx
- OSAL_MUTEX_DEF(ff_mutex);
+ OSAL_MUTEX_DEF(ff_mutexdef);
}tu_edpt_stream_t;
@@ -87,15 +87,17 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex);
// Endpoint Stream
//--------------------------------------------------------------------+
-// Init an stream, should only be called once
+// Init an endpoint stream
bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable,
void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize);
+// Deinit an endpoint stream
+bool tu_edpt_stream_deinit(tu_edpt_stream_t* s);
+
// Open an stream for an endpoint
// hwid is either device address (host mode) or rhport (device mode)
TU_ATTR_ALWAYS_INLINE static inline
-void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep)
-{
+void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep) {
tu_fifo_clear(&s->ff);
s->hwid = hwid;
s->ep_addr = desc_ep->bEndpointAddress;
@@ -103,16 +105,14 @@ void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t
}
TU_ATTR_ALWAYS_INLINE static inline
-void tu_edpt_stream_close(tu_edpt_stream_t* s)
-{
+void tu_edpt_stream_close(tu_edpt_stream_t* s) {
s->hwid = 0;
s->ep_addr = 0;
}
// Clear fifo
TU_ATTR_ALWAYS_INLINE static inline
-bool tu_edpt_stream_clear(tu_edpt_stream_t* s)
-{
+bool tu_edpt_stream_clear(tu_edpt_stream_t* s) {
return tu_fifo_clear(&s->ff);
}
@@ -131,8 +131,7 @@ bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferr
// Get the number of bytes available for writing
TU_ATTR_ALWAYS_INLINE static inline
-uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s)
-{
+uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s) {
return (uint32_t) tu_fifo_remaining(&s->ff);
}
@@ -148,21 +147,26 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s);
// Must be called in the transfer complete callback
TU_ATTR_ALWAYS_INLINE static inline
-void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes)
-{
+void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) {
tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes);
}
+// Same as tu_edpt_stream_read_xfer_complete but skip the first n bytes
+TU_ATTR_ALWAYS_INLINE static inline
+void tu_edpt_stream_read_xfer_complete_offset(tu_edpt_stream_t* s, uint32_t xferred_bytes, uint32_t skip_offset) {
+ if (skip_offset < xferred_bytes) {
+ tu_fifo_write_n(&s->ff, s->ep_buf + skip_offset, (uint16_t) (xferred_bytes - skip_offset));
+ }
+}
+
// Get the number of bytes available for reading
TU_ATTR_ALWAYS_INLINE static inline
-uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s)
-{
+uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) {
return (uint32_t) tu_fifo_count(&s->ff);
}
TU_ATTR_ALWAYS_INLINE static inline
-bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch)
-{
+bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) {
return tu_fifo_peek(&s->ff, ch);
}
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index 39a2d4564..2c5dce723 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -44,43 +44,38 @@
*------------------------------------------------------------------*/
/// defined base on EHCI specs value for Endpoint Speed
-typedef enum
-{
+typedef enum {
TUSB_SPEED_FULL = 0,
TUSB_SPEED_LOW = 1,
TUSB_SPEED_HIGH = 2,
TUSB_SPEED_INVALID = 0xff,
-}tusb_speed_t;
+} tusb_speed_t;
/// defined base on USB Specs Endpoint's bmAttributes
-typedef enum
-{
+typedef enum {
TUSB_XFER_CONTROL = 0 ,
TUSB_XFER_ISOCHRONOUS ,
TUSB_XFER_BULK ,
TUSB_XFER_INTERRUPT
-}tusb_xfer_type_t;
+} tusb_xfer_type_t;
-typedef enum
-{
+typedef enum {
TUSB_DIR_OUT = 0,
TUSB_DIR_IN = 1,
TUSB_DIR_IN_MASK = 0x80
-}tusb_dir_t;
+} tusb_dir_t;
-enum
-{
+enum {
TUSB_EPSIZE_BULK_FS = 64,
- TUSB_EPSIZE_BULK_HS= 512,
+ TUSB_EPSIZE_BULK_HS = 512,
TUSB_EPSIZE_ISO_FS_MAX = 1023,
TUSB_EPSIZE_ISO_HS_MAX = 1024,
};
-/// Isochronous End Point Attributes
-typedef enum
-{
+/// Isochronous Endpoint Attributes
+typedef enum {
TUSB_ISO_EP_ATT_NO_SYNC = 0x00,
TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04,
TUSB_ISO_EP_ATT_ADAPTIVE = 0x08,
@@ -88,11 +83,10 @@ typedef enum
TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point
TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point
TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback
-}tusb_iso_ep_attribute_t;
+} tusb_iso_ep_attribute_t;
/// USB Descriptor Types
-typedef enum
-{
+typedef enum {
TUSB_DESC_DEVICE = 0x01,
TUSB_DESC_CONFIGURATION = 0x02,
TUSB_DESC_STRING = 0x03,
@@ -119,10 +113,9 @@ typedef enum
TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30,
TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31
-}tusb_desc_type_t;
+} tusb_desc_type_t;
-typedef enum
-{
+typedef enum {
TUSB_REQ_GET_STATUS = 0 ,
TUSB_REQ_CLEAR_FEATURE = 1 ,
TUSB_REQ_RESERVED = 2 ,
@@ -136,25 +129,22 @@ typedef enum
TUSB_REQ_GET_INTERFACE = 10 ,
TUSB_REQ_SET_INTERFACE = 11 ,
TUSB_REQ_SYNCH_FRAME = 12
-}tusb_request_code_t;
+} tusb_request_code_t;
-typedef enum
-{
+typedef enum {
TUSB_REQ_FEATURE_EDPT_HALT = 0,
TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1,
TUSB_REQ_FEATURE_TEST_MODE = 2
-}tusb_request_feature_selector_t;
+} tusb_request_feature_selector_t;
-typedef enum
-{
+typedef enum {
TUSB_REQ_TYPE_STANDARD = 0,
TUSB_REQ_TYPE_CLASS,
TUSB_REQ_TYPE_VENDOR,
TUSB_REQ_TYPE_INVALID
} tusb_request_type_t;
-typedef enum
-{
+typedef enum {
TUSB_REQ_RCPT_DEVICE =0,
TUSB_REQ_RCPT_INTERFACE,
TUSB_REQ_RCPT_ENDPOINT,
@@ -162,8 +152,7 @@ typedef enum
} tusb_request_recipient_t;
// https://www.usb.org/defined-class-codes
-typedef enum
-{
+typedef enum {
TUSB_CLASS_UNSPECIFIED = 0 ,
TUSB_CLASS_AUDIO = 1 ,
TUSB_CLASS_CDC = 2 ,
@@ -187,26 +176,23 @@ typedef enum
TUSB_CLASS_MISC = 0xEF ,
TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE ,
TUSB_CLASS_VENDOR_SPECIFIC = 0xFF
-}tusb_class_code_t;
+} tusb_class_code_t;
typedef enum
{
MISC_SUBCLASS_COMMON = 2
}misc_subclass_type_t;
-typedef enum
-{
+typedef enum {
MISC_PROTOCOL_IAD = 1
-}misc_protocol_type_t;
+} misc_protocol_type_t;
-typedef enum
-{
+typedef enum {
APP_SUBCLASS_USBTMC = 0x03,
APP_SUBCLASS_DFU_RUNTIME = 0x01
} app_subclass_type_t;
-typedef enum
-{
+typedef enum {
DEVICE_CAPABILITY_WIRELESS_USB = 0x01,
DEVICE_CAPABILITY_USB20_EXTENSION = 0x02,
DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03,
@@ -223,7 +209,7 @@ typedef enum
DEVICE_CAPABILITY_AUTHENTICATION = 0x0E,
DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F,
DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10
-}device_capability_type_t;
+} device_capability_type_t;
enum {
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5),
@@ -232,28 +218,28 @@ enum {
#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2)
-typedef enum
-{
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+typedef enum {
XFER_RESULT_SUCCESS = 0,
XFER_RESULT_FAILED,
XFER_RESULT_STALLED,
XFER_RESULT_TIMEOUT,
XFER_RESULT_INVALID
-}xfer_result_t;
+} xfer_result_t;
-enum // TODO remove
-{
+// TODO remove
+enum {
DESC_OFFSET_LEN = 0,
DESC_OFFSET_TYPE = 1
};
-enum
-{
+enum {
INTERFACE_INVALID_NUMBER = 0xff
};
-typedef enum
-{
+typedef enum {
MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00,
MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01,
MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02,
@@ -265,16 +251,14 @@ typedef enum
MS_OS_20_FEATURE_VENDOR_REVISION = 0x08
} microsoft_os_20_type_t;
-enum
-{
+enum {
CONTROL_STAGE_IDLE,
CONTROL_STAGE_SETUP,
CONTROL_STAGE_DATA,
CONTROL_STAGE_ACK
};
-enum
-{
+enum {
TUSB_INDEX_INVALID_8 = 0xFFu
};
@@ -287,8 +271,7 @@ TU_ATTR_PACKED_BEGIN
TU_ATTR_BIT_FIELD_ORDER_BEGIN
/// USB Device Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of this descriptor in bytes.
uint8_t bDescriptorType ; ///< DEVICE Descriptor Type.
uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant.
@@ -311,8 +294,7 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct");
// USB Binary Device Object Store (BOS) Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of this descriptor in bytes
uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type
uint16_t wTotalLength ; ///< Total length of data returned for this descriptor
@@ -322,8 +304,7 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct");
/// USB Configuration Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of this descriptor in bytes
uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type
uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration.
@@ -338,8 +319,7 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct");
/// USB Interface Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of this descriptor in bytes
uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type
@@ -355,8 +335,7 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct");
/// USB Endpoint Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; // Size of this descriptor in bytes
uint8_t bDescriptorType ; // ENDPOINT Descriptor Type
@@ -376,8 +355,7 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct");
/// USB Other Speed Configuration Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of descriptor
uint8_t bDescriptorType ; ///< Other_speed_Configuration Type
uint16_t wTotalLength ; ///< Total length of data returned
@@ -390,8 +368,7 @@ typedef struct TU_ATTR_PACKED
} tusb_desc_other_speed_t;
/// USB Device Qualifier Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of descriptor
uint8_t bDescriptorType ; ///< Device Qualifier Type
uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00)
@@ -408,8 +385,7 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct");
/// USB Interface Association Descriptor (IAD ECN)
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of descriptor
uint8_t bDescriptorType ; ///< Other_speed_Configuration Type
@@ -423,17 +399,17 @@ typedef struct TU_ATTR_PACKED
uint8_t iFunction ; ///< Index of the string descriptor describing the interface association.
} tusb_desc_interface_assoc_t;
+TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct");
+
// USB String Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of this descriptor in bytes
uint8_t bDescriptorType ; ///< Descriptor Type
uint16_t unicode_string[];
} tusb_desc_string_t;
// USB Binary Device Object Store (BOS)
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType ;
uint8_t bDevCapabilityType;
@@ -442,9 +418,8 @@ typedef struct TU_ATTR_PACKED
uint8_t CapabilityData[];
} tusb_desc_bos_platform_t;
-// USB WebuSB URL Descriptor
-typedef struct TU_ATTR_PACKED
-{
+// USB WebUSB URL Descriptor
+typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bScheme;
@@ -452,8 +427,7 @@ typedef struct TU_ATTR_PACKED
} tusb_desc_webusb_url_t;
// DFU Functional Descriptor
-typedef struct TU_ATTR_PACKED
-{
+typedef struct TU_ATTR_PACKED {
uint8_t bLength;
uint8_t bDescriptorType;
@@ -474,10 +448,11 @@ typedef struct TU_ATTR_PACKED
uint16_t bcdDFUVersion;
} tusb_desc_dfu_functional_t;
-/*------------------------------------------------------------------*/
-/* Types
- *------------------------------------------------------------------*/
-typedef struct TU_ATTR_PACKED{
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+typedef struct TU_ATTR_PACKED {
union {
struct TU_ATTR_PACKED {
uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t.
@@ -496,7 +471,6 @@ typedef struct TU_ATTR_PACKED{
TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct");
-
TU_ATTR_PACKED_END // End of all packed definitions
TU_ATTR_BIT_FIELD_ORDER_END
@@ -505,36 +479,30 @@ TU_ATTR_BIT_FIELD_ORDER_END
//--------------------------------------------------------------------+
// Get direction from Endpoint address
-TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr)
-{
+TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) {
return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
}
// Get Endpoint number from address
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) {
return (uint8_t)(addr & (~TUSB_DIR_IN_MASK));
}
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) {
return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0));
}
-TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) {
return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0);
}
#if CFG_TUSB_DEBUG
-TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir)
-{
+TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir) {
tu_static const char *str[] = {"out", "in"};
return str[dir];
}
-TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t)
-{
+TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) {
tu_static const char *str[] = {"control", "isochronous", "bulk", "interrupt"};
return str[t];
}
@@ -545,21 +513,18 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_
//--------------------------------------------------------------------+
// return next descriptor
-TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
uint8_t const* desc8 = (uint8_t const*) desc;
return desc8 + desc8[DESC_OFFSET_LEN];
}
// get descriptor type
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
}
// get descriptor length
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
}
diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h
index 12355e8be..8aa66b4df 100644
--- a/src/common/tusb_verify.h
+++ b/src/common/tusb_verify.h
@@ -56,12 +56,8 @@
* #define TU_VERIFY(cond) if(cond) return false;
* #define TU_VERIFY(cond,ret) if(cond) return ret;
*
- * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;}
- * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;}
- *
* #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;}
* #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;}
- *
*------------------------------------------------------------------*/
#ifdef __cplusplus
@@ -79,8 +75,8 @@
#define _MESS_FAILED() do {} while (0)
#endif
-// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33
-#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)
+// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33. M55
+#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__)
#define TU_BREAKPOINT() do \
{ \
volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \
@@ -97,40 +93,23 @@
#define TU_BREAKPOINT() do {} while (0)
#endif
-/*------------------------------------------------------------------*/
-/* Macro Generator
- *------------------------------------------------------------------*/
-
// Helper to implement optional parameter for TU_VERIFY Macro family
#define _GET_3RD_ARG(arg1, arg2, arg3, ...) arg3
-#define _GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
-
-/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/
-#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \
-{ \
- if ( !(_cond) ) { _handler; return _ret; } \
-} while(0)
/*------------------------------------------------------------------*/
/* TU_VERIFY
* - TU_VERIFY_1ARGS : return false if failed
* - TU_VERIFY_2ARGS : return provided value if failed
*------------------------------------------------------------------*/
-#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false)
-#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret)
+#define TU_VERIFY_DEFINE(_cond, _ret) \
+ do { \
+ if ( !(_cond) ) { return _ret; } \
+ } while(0)
-#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__)
+#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false)
+#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret)
-
-/*------------------------------------------------------------------*/
-/* TU_VERIFY WITH HANDLER
- * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed
- * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed
- *------------------------------------------------------------------*/
-#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false)
-#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret)
-
-#define TU_VERIFY_HDLR(...) _GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__)
+#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
/*------------------------------------------------------------------*/
/* ASSERT
@@ -138,19 +117,20 @@
* - 1 arg : return false if failed
* - 2 arg : return error if failed
*------------------------------------------------------------------*/
-#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false)
-#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret)
+#define TU_ASSERT_DEFINE(_cond, _ret) \
+ do { \
+ if ( !(_cond) ) { _MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
+ } while(0)
+
+#define TU_ASSERT_1ARGS(_cond) TU_ASSERT_DEFINE(_cond, false)
+#define TU_ASSERT_2ARGS(_cond, _ret) TU_ASSERT_DEFINE(_cond, _ret)
#ifndef TU_ASSERT
-#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__)
+#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
#endif
-/*------------------------------------------------------------------*/
-/* ASSERT HDLR
- *------------------------------------------------------------------*/
-
#ifdef __cplusplus
}
#endif
-#endif /* TUSB_VERIFY_H_ */
+#endif
diff --git a/src/device/dcd.h b/src/device/dcd.h
index 00419ff05..d4f105aa3 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -47,8 +47,7 @@
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
-typedef enum
-{
+typedef enum {
DCD_EVENT_INVALID = 0,
DCD_EVENT_BUS_RESET,
DCD_EVENT_UNPLUGGED,
@@ -65,13 +64,11 @@ typedef enum
DCD_EVENT_COUNT
} dcd_eventid_t;
-typedef struct TU_ATTR_ALIGNED(4)
-{
+typedef struct TU_ATTR_ALIGNED(4) {
uint8_t rhport;
uint8_t event_id;
- union
- {
+ union {
// BUS RESET
struct {
tusb_speed_t speed;
@@ -103,11 +100,30 @@ typedef struct TU_ATTR_ALIGNED(4)
//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct");
//--------------------------------------------------------------------+
+// Memory API
+//--------------------------------------------------------------------+
+
+// clean/flush data cache: write cache -> memory.
+// Required before an DMA TX transfer to make sure data is in memory
+void dcd_dcache_clean(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+
+// invalidate data cache: mark cache as invalid, next read will read from memory
+// Required BOTH before and after an DMA RX transfer
+void dcd_dcache_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+
+// clean and invalidate data cache
+// Required before an DMA transfer where memory is both read/write by DMA
+void dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+
+//--------------------------------------------------------------------+
// Controller API
//--------------------------------------------------------------------+
// Initialize controller to device mode
-void dcd_init (uint8_t rhport);
+void dcd_init(uint8_t rhport);
+
+// Deinitialize controller, unset device mode.
+bool dcd_deinit(uint8_t rhport);
// Interrupt Handler
void dcd_int_handler(uint8_t rhport);
@@ -139,7 +155,7 @@ void dcd_sof_enable(uint8_t rhport, bool en);
// Invoked when a control transfer's status stage is complete.
// May help DCD to prepare for next control transfer, this API is optional.
-void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) TU_ATTR_WEAK;
+void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request);
// Configure endpoint's registers according to descriptor
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep);
@@ -168,11 +184,12 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr);
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr);
// Allocate packet buffer used by ISO endpoints
-// Some MCU need manual packet buffer allocation, we allocation largest size to avoid clustering
+// Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering
TU_ATTR_WEAK bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size);
// Configure and enable an ISO endpoint according to descriptor
-TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
+TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc);
+
//--------------------------------------------------------------------+
// Event API (implemented by stack)
//--------------------------------------------------------------------+
@@ -181,23 +198,20 @@ TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t co
extern void dcd_event_handler(dcd_event_t const * event, bool in_isr);
// helper to send bus signal event
-TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) {
dcd_event_t event = { .rhport = rhport, .event_id = eid };
dcd_event_handler(&event, in_isr);
}
// helper to send bus reset event
-TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) {
dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_BUS_RESET };
event.bus_reset.speed = speed;
dcd_event_handler(&event, in_isr);
}
// helper to send setup received
-TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) {
dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED };
memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t));
@@ -205,8 +219,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport
}
// helper to send transfer complete event
-TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) {
dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE };
event.xfer_complete.ep_addr = ep_addr;
@@ -216,8 +229,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_xfer_complete (uint8_t rhport
dcd_event_handler(&event, in_isr);
}
-static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr) {
dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SOF };
event.sof.frame_count = frame_count;
dcd_event_handler(&event, in_isr);
diff --git a/src/device/usbd.c b/src/device/usbd.c
index cee56af60..96982c30b 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -38,13 +38,23 @@
//--------------------------------------------------------------------+
// USBD Configuration
//--------------------------------------------------------------------+
-
#ifndef CFG_TUD_TASK_QUEUE_SZ
#define CFG_TUD_TASK_QUEUE_SZ 16
#endif
-// Debug level of USBD
-#define USBD_DBG 2
+//--------------------------------------------------------------------+
+// Weak stubs: invoked if no strong implementation is available
+//--------------------------------------------------------------------+
+TU_ATTR_WEAK bool dcd_deinit(uint8_t rhport) {
+ (void) rhport;
+ return false;
+}
+
+TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) {
+ (void)rhport;
+ (void)eventid;
+ (void)in_isr;
+}
//--------------------------------------------------------------------+
// Device Data
@@ -53,10 +63,8 @@
// Invalid driver ID in itf2drv[] ep2drv[][] mapping
enum { DRVID_INVALID = 0xFFu };
-typedef struct
-{
- struct TU_ATTR_PACKED
- {
+typedef struct {
+ struct TU_ATTR_PACKED {
volatile uint8_t connected : 1;
volatile uint8_t addressed : 1;
volatile uint8_t suspended : 1;
@@ -65,9 +73,9 @@ typedef struct
uint8_t remote_wakeup_support : 1; // configuration descriptor's attribute
uint8_t self_powered : 1; // configuration descriptor's attribute
};
-
volatile uint8_t cfg_num; // current active configuration (0x00 is not configured)
uint8_t speed;
+ volatile uint8_t setup_count;
uint8_t itf2drv[CFG_TUD_INTERFACE_MAX]; // map interface number to driver (0xff is invalid)
uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each
@@ -81,158 +89,169 @@ tu_static usbd_device_t _usbd_dev;
//--------------------------------------------------------------------+
// Class Driver
//--------------------------------------------------------------------+
-#if CFG_TUSB_DEBUG >= 2
+#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
#define DRIVER_NAME(_name) .name = _name,
#else
#define DRIVER_NAME(_name)
#endif
// Built-in class drivers
-tu_static usbd_class_driver_t const _usbd_driver[] =
-{
- #if CFG_TUD_CDC
- {
- DRIVER_NAME("CDC")
- .init = cdcd_init,
- .reset = cdcd_reset,
- .open = cdcd_open,
- .control_xfer_cb = cdcd_control_xfer_cb,
- .xfer_cb = cdcd_xfer_cb,
- .sof = NULL
- },
- #endif
+tu_static usbd_class_driver_t const _usbd_driver[] = {
+ #if CFG_TUD_CDC
+ {
+ DRIVER_NAME("CDC")
+ .init = cdcd_init,
+ .deinit = cdcd_deinit,
+ .reset = cdcd_reset,
+ .open = cdcd_open,
+ .control_xfer_cb = cdcd_control_xfer_cb,
+ .xfer_cb = cdcd_xfer_cb,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_MSC
- {
- DRIVER_NAME("MSC")
- .init = mscd_init,
- .reset = mscd_reset,
- .open = mscd_open,
- .control_xfer_cb = mscd_control_xfer_cb,
- .xfer_cb = mscd_xfer_cb,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_MSC
+ {
+ DRIVER_NAME("MSC")
+ .init = mscd_init,
+ .deinit = NULL,
+ .reset = mscd_reset,
+ .open = mscd_open,
+ .control_xfer_cb = mscd_control_xfer_cb,
+ .xfer_cb = mscd_xfer_cb,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_HID
- {
- DRIVER_NAME("HID")
- .init = hidd_init,
- .reset = hidd_reset,
- .open = hidd_open,
- .control_xfer_cb = hidd_control_xfer_cb,
- .xfer_cb = hidd_xfer_cb,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_HID
+ {
+ DRIVER_NAME("HID")
+ .init = hidd_init,
+ .deinit = hidd_deinit,
+ .reset = hidd_reset,
+ .open = hidd_open,
+ .control_xfer_cb = hidd_control_xfer_cb,
+ .xfer_cb = hidd_xfer_cb,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_AUDIO
- {
- DRIVER_NAME("AUDIO")
- .init = audiod_init,
- .reset = audiod_reset,
- .open = audiod_open,
- .control_xfer_cb = audiod_control_xfer_cb,
- .xfer_cb = audiod_xfer_cb,
- .sof = audiod_sof_isr
- },
- #endif
+ #if CFG_TUD_AUDIO
+ {
+ DRIVER_NAME("AUDIO")
+ .init = audiod_init,
+ .deinit = audiod_deinit,
+ .reset = audiod_reset,
+ .open = audiod_open,
+ .control_xfer_cb = audiod_control_xfer_cb,
+ .xfer_cb = audiod_xfer_cb,
+ .sof = audiod_sof_isr
+ },
+ #endif
- #if CFG_TUD_VIDEO
- {
- DRIVER_NAME("VIDEO")
- .init = videod_init,
- .reset = videod_reset,
- .open = videod_open,
- .control_xfer_cb = videod_control_xfer_cb,
- .xfer_cb = videod_xfer_cb,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_VIDEO
+ {
+ DRIVER_NAME("VIDEO")
+ .init = videod_init,
+ .deinit = videod_deinit,
+ .reset = videod_reset,
+ .open = videod_open,
+ .control_xfer_cb = videod_control_xfer_cb,
+ .xfer_cb = videod_xfer_cb,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_MIDI
- {
- DRIVER_NAME("MIDI")
- .init = midid_init,
- .open = midid_open,
- .reset = midid_reset,
- .control_xfer_cb = midid_control_xfer_cb,
- .xfer_cb = midid_xfer_cb,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_MIDI
+ {
+ DRIVER_NAME("MIDI")
+ .init = midid_init,
+ .deinit = midid_deinit,
+ .open = midid_open,
+ .reset = midid_reset,
+ .control_xfer_cb = midid_control_xfer_cb,
+ .xfer_cb = midid_xfer_cb,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_VENDOR
- {
- DRIVER_NAME("VENDOR")
- .init = vendord_init,
- .reset = vendord_reset,
- .open = vendord_open,
- .control_xfer_cb = tud_vendor_control_xfer_cb,
- .xfer_cb = vendord_xfer_cb,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_VENDOR
+ {
+ DRIVER_NAME("VENDOR")
+ .init = vendord_init,
+ .deinit = vendord_deinit,
+ .reset = vendord_reset,
+ .open = vendord_open,
+ .control_xfer_cb = tud_vendor_control_xfer_cb,
+ .xfer_cb = vendord_xfer_cb,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_USBTMC
- {
- DRIVER_NAME("TMC")
- .init = usbtmcd_init_cb,
- .reset = usbtmcd_reset_cb,
- .open = usbtmcd_open_cb,
- .control_xfer_cb = usbtmcd_control_xfer_cb,
- .xfer_cb = usbtmcd_xfer_cb,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_USBTMC
+ {
+ DRIVER_NAME("TMC")
+ .init = usbtmcd_init_cb,
+ .deinit = usbtmcd_deinit,
+ .reset = usbtmcd_reset_cb,
+ .open = usbtmcd_open_cb,
+ .control_xfer_cb = usbtmcd_control_xfer_cb,
+ .xfer_cb = usbtmcd_xfer_cb,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_DFU_RUNTIME
- {
- DRIVER_NAME("DFU-RUNTIME")
- .init = dfu_rtd_init,
- .reset = dfu_rtd_reset,
- .open = dfu_rtd_open,
- .control_xfer_cb = dfu_rtd_control_xfer_cb,
- .xfer_cb = NULL,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_DFU_RUNTIME
+ {
+ DRIVER_NAME("DFU-RUNTIME")
+ .init = dfu_rtd_init,
+ .deinit = dfu_rtd_deinit,
+ .reset = dfu_rtd_reset,
+ .open = dfu_rtd_open,
+ .control_xfer_cb = dfu_rtd_control_xfer_cb,
+ .xfer_cb = NULL,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_DFU
- {
- DRIVER_NAME("DFU")
- .init = dfu_moded_init,
- .reset = dfu_moded_reset,
- .open = dfu_moded_open,
- .control_xfer_cb = dfu_moded_control_xfer_cb,
- .xfer_cb = NULL,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_DFU
+ {
+ DRIVER_NAME("DFU")
+ .init = dfu_moded_init,
+ .deinit = dfu_moded_deinit,
+ .reset = dfu_moded_reset,
+ .open = dfu_moded_open,
+ .control_xfer_cb = dfu_moded_control_xfer_cb,
+ .xfer_cb = NULL,
+ .sof = NULL
+ },
+ #endif
- #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM
- {
- DRIVER_NAME("NET")
- .init = netd_init,
- .reset = netd_reset,
- .open = netd_open,
- .control_xfer_cb = netd_control_xfer_cb,
- .xfer_cb = netd_xfer_cb,
- .sof = NULL,
- },
- #endif
+ #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM
+ {
+ DRIVER_NAME("NET")
+ .init = netd_init,
+ .deinit = netd_deinit,
+ .reset = netd_reset,
+ .open = netd_open,
+ .control_xfer_cb = netd_control_xfer_cb,
+ .xfer_cb = netd_xfer_cb,
+ .sof = NULL,
+ },
+ #endif
- #if CFG_TUD_BTH
- {
- DRIVER_NAME("BTH")
- .init = btd_init,
- .reset = btd_reset,
- .open = btd_open,
- .control_xfer_cb = btd_control_xfer_cb,
- .xfer_cb = btd_xfer_cb,
- .sof = NULL
- },
- #endif
+ #if CFG_TUD_BTH
+ {
+ DRIVER_NAME("BTH")
+ .init = btd_init,
+ .deinit = btd_deinit,
+ .reset = btd_reset,
+ .open = btd_open,
+ .control_xfer_cb = btd_control_xfer_cb,
+ .xfer_cb = btd_xfer_cb,
+ .sof = NULL
+ },
+ #endif
};
enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
@@ -241,25 +260,21 @@ enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
tu_static usbd_class_driver_t const * _app_driver = NULL;
tu_static uint8_t _app_driver_count = 0;
+#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT)
+
// virtually joins built-in and application drivers together.
// Application is positioned first to allow overwriting built-in ones.
-static inline usbd_class_driver_t const * get_driver(uint8_t drvid)
-{
- // Application drivers
- if ( usbd_app_driver_get_cb )
- {
- if ( drvid < _app_driver_count ) return &_app_driver[drvid];
- drvid -= _app_driver_count;
+TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8_t drvid) {
+ usbd_class_driver_t const * driver = NULL;
+ if ( drvid < _app_driver_count ) {
+ // Application drivers
+ driver = &_app_driver[drvid];
+ } else if ( drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0 ){
+ driver = &_usbd_driver[drvid - _app_driver_count];
}
-
- // Built-in drivers
- if (drvid < BUILTIN_DRIVER_COUNT) return &_usbd_driver[drvid];
-
- return NULL;
+ return driver;
}
-#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT)
-
//--------------------------------------------------------------------+
// DCD Event
//--------------------------------------------------------------------+
@@ -280,6 +295,11 @@ tu_static osal_queue_t _usbd_q;
#define _usbd_mutex NULL
#endif
+TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event, bool in_isr) {
+ bool ret = osal_queue_send(_usbd_q, event, in_isr);
+ tud_event_hook_cb(event->rhport, event->event_id, in_isr);
+ return ret;
+}
//--------------------------------------------------------------------+
// Prototypes
@@ -298,29 +318,25 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event,
//--------------------------------------------------------------------+
// Debug
//--------------------------------------------------------------------+
-#if CFG_TUSB_DEBUG >= 2
-tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] =
-{
- "Invalid" ,
- "Bus Reset" ,
- "Unplugged" ,
- "SOF" ,
- "Suspend" ,
- "Resume" ,
- "Setup Received" ,
- "Xfer Complete" ,
- "Func Call"
+#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
+tu_static char const* const _usbd_event_str[DCD_EVENT_COUNT] = {
+ "Invalid",
+ "Bus Reset",
+ "Unplugged",
+ "SOF",
+ "Suspend",
+ "Resume",
+ "Setup Received",
+ "Xfer Complete",
+ "Func Call"
};
// for usbd_control to print the name of control complete driver
-void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback)
-{
- for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++)
- {
- usbd_class_driver_t const * driver = get_driver(i);
- if ( driver && driver->control_xfer_cb == callback )
- {
- TU_LOG(USBD_DBG, " %s control complete\r\n", driver->name);
+void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback) {
+ for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
+ usbd_class_driver_t const* driver = get_driver(i);
+ if (driver && driver->control_xfer_cb == callback) {
+ TU_LOG_USBD("%s control complete\r\n", driver->name);
return;
}
}
@@ -331,43 +347,36 @@ void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback)
//--------------------------------------------------------------------+
// Application API
//--------------------------------------------------------------------+
-tusb_speed_t tud_speed_get(void)
-{
+tusb_speed_t tud_speed_get(void) {
return (tusb_speed_t) _usbd_dev.speed;
}
-bool tud_connected(void)
-{
+bool tud_connected(void) {
return _usbd_dev.connected;
}
-bool tud_mounted(void)
-{
+bool tud_mounted(void) {
return _usbd_dev.cfg_num ? true : false;
}
-bool tud_suspended(void)
-{
+bool tud_suspended(void) {
return _usbd_dev.suspended;
}
-bool tud_remote_wakeup(void)
-{
+bool tud_remote_wakeup(void) {
// only wake up host if this feature is supported and enabled and we are suspended
- TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en );
+ TU_VERIFY (_usbd_dev.suspended && _usbd_dev.remote_wakeup_support && _usbd_dev.remote_wakeup_en);
dcd_remote_wakeup(_usbd_rhport);
return true;
}
-bool tud_disconnect(void)
-{
+bool tud_disconnect(void) {
TU_VERIFY(dcd_disconnect);
dcd_disconnect(_usbd_rhport);
return true;
}
-bool tud_connect(void)
-{
+bool tud_connect(void) {
TU_VERIFY(dcd_connect);
dcd_connect(_usbd_rhport);
return true;
@@ -376,20 +385,19 @@ bool tud_connect(void)
//--------------------------------------------------------------------+
// USBD Task
//--------------------------------------------------------------------+
-bool tud_inited(void)
-{
+bool tud_inited(void) {
return _usbd_rhport != RHPORT_INVALID;
}
-bool tud_init (uint8_t rhport)
-{
+bool tud_init(uint8_t rhport) {
// skip if already initialized
- if ( tud_inited() ) return true;
+ if (tud_inited()) return true;
- TU_LOG(USBD_DBG, "USBD init on controller %u\r\n", rhport);
- TU_LOG_INT(USBD_DBG, sizeof(usbd_device_t));
- TU_LOG_INT(USBD_DBG, sizeof(tu_fifo_t));
- TU_LOG_INT(USBD_DBG, sizeof(tu_edpt_stream_t));
+ TU_LOG_USBD("USBD init on controller %u\r\n", rhport);
+ TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t));
+ TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t));
+ TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t));
+ TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t));
tu_varclr(&_usbd_dev);
@@ -404,17 +412,15 @@ bool tud_init (uint8_t rhport)
TU_ASSERT(_usbd_q);
// Get application driver if available
- if ( usbd_app_driver_get_cb )
- {
+ if (usbd_app_driver_get_cb) {
_app_driver = usbd_app_driver_get_cb(&_app_driver_count);
}
// Init class drivers
- for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++)
- {
- usbd_class_driver_t const * driver = get_driver(i);
- TU_ASSERT(driver);
- TU_LOG(USBD_DBG, "%s init\r\n", driver->name);
+ for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
+ usbd_class_driver_t const* driver = get_driver(i);
+ TU_ASSERT(driver && driver->init);
+ TU_LOG_USBD("%s init\r\n", driver->name);
driver->init();
}
@@ -427,31 +433,61 @@ bool tud_init (uint8_t rhport)
return true;
}
-static void configuration_reset(uint8_t rhport)
-{
- for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ )
- {
- usbd_class_driver_t const * driver = get_driver(i);
- TU_ASSERT(driver, );
+bool tud_deinit(uint8_t rhport) {
+ // skip if not initialized
+ if (!tud_inited()) return true;
+
+ TU_LOG_USBD("USBD deinit on controller %u\r\n", rhport);
+
+ // Deinit device controller driver
+ dcd_int_disable(rhport);
+ dcd_disconnect(rhport);
+ dcd_deinit(rhport);
+
+ // Deinit class drivers
+ for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
+ usbd_class_driver_t const* driver = get_driver(i);
+ if(driver && driver->deinit) {
+ TU_LOG_USBD("%s deinit\r\n", driver->name);
+ driver->deinit();
+ }
+ }
+
+ // Deinit device queue & task
+ osal_queue_delete(_usbd_q);
+ _usbd_q = NULL;
+
+#if OSAL_MUTEX_REQUIRED
+ // TODO make sure there is no task waiting on this mutex
+ osal_mutex_delete(_usbd_mutex);
+ _usbd_mutex = NULL;
+#endif
+
+ _usbd_rhport = RHPORT_INVALID;
+
+ return true;
+}
+
+static void configuration_reset(uint8_t rhport) {
+ for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
+ usbd_class_driver_t const* driver = get_driver(i);
+ TU_ASSERT(driver,);
driver->reset(rhport);
}
tu_varclr(&_usbd_dev);
memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping
- memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping
+ memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping
}
-static void usbd_reset(uint8_t rhport)
-{
+static void usbd_reset(uint8_t rhport) {
configuration_reset(rhport);
usbd_control_reset();
}
-bool tud_task_event_ready(void)
-{
+bool tud_task_event_ready(void) {
// Skip if stack is not initialized
- if ( !tud_inited() ) return false;
-
+ if (!tud_inited()) return false;
return !osal_queue_empty(_usbd_q);
}
@@ -459,139 +495,126 @@ bool tud_task_event_ready(void)
* This top level thread manages all device controller event and delegates events to class-specific drivers.
* This should be called periodically within the mainloop or rtos thread.
*
- @code
- int main(void)
- {
+ int main(void) {
application_init();
tusb_init();
- while(1) // the mainloop
- {
+ while(1) { // the mainloop
application_code();
tud_task(); // tinyusb device task
}
}
- @endcode
*/
-void tud_task_ext(uint32_t timeout_ms, bool in_isr)
-{
+void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
(void) in_isr; // not implemented yet
// Skip if stack is not initialized
- if ( !tud_inited() ) return;
+ if (!tud_inited()) return;
// Loop until there is no more events in the queue
- while (1)
- {
+ while (1) {
dcd_event_t event;
- if ( !osal_queue_receive(_usbd_q, &event, timeout_ms) ) return;
+ if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) return;
-#if CFG_TUSB_DEBUG >= 2
- if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG(USBD_DBG, "\r\n"); // extra line for setup
- TU_LOG(USBD_DBG, "USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED");
+#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
+ if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG_USBD("\r\n"); // extra line for setup
+ TU_LOG_USBD("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED");
#endif
- switch ( event.event_id )
- {
+ switch (event.event_id) {
case DCD_EVENT_BUS_RESET:
- TU_LOG(USBD_DBG, ": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]);
+ TU_LOG_USBD(": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]);
usbd_reset(event.rhport);
_usbd_dev.speed = event.bus_reset.speed;
- break;
+ break;
case DCD_EVENT_UNPLUGGED:
- TU_LOG(USBD_DBG, "\r\n");
+ TU_LOG_USBD("\r\n");
usbd_reset(event.rhport);
-
- // invoke callback
if (tud_umount_cb) tud_umount_cb();
- break;
+ break;
case DCD_EVENT_SETUP_RECEIVED:
- TU_LOG_PTR(USBD_DBG, &event.setup_received);
- TU_LOG(USBD_DBG, "\r\n");
+ _usbd_dev.setup_count--;
+ TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8);
+ if (_usbd_dev.setup_count) {
+ TU_LOG_USBD(" Skipped since there is other SETUP in queue\r\n");
+ break;
+ }
// Mark as connected after receiving 1st setup packet.
// But it is easier to set it every time instead of wasting time to check then set
_usbd_dev.connected = 1;
// mark both in & out control as free
- _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = false;
+ _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = 0;
_usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0;
- _usbd_dev.ep_status[0][TUSB_DIR_IN ].busy = false;
- _usbd_dev.ep_status[0][TUSB_DIR_IN ].claimed = 0;
+ _usbd_dev.ep_status[0][TUSB_DIR_IN].busy = 0;
+ _usbd_dev.ep_status[0][TUSB_DIR_IN].claimed = 0;
// Process control request
- if ( !process_control_request(event.rhport, &event.setup_received) )
- {
- TU_LOG(USBD_DBG, " Stall EP0\r\n");
+ if (!process_control_request(event.rhport, &event.setup_received)) {
+ TU_LOG_USBD(" Stall EP0\r\n");
// Failed -> stall both control endpoint IN and OUT
dcd_edpt_stall(event.rhport, 0);
dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK);
}
- break;
+ break;
- case DCD_EVENT_XFER_COMPLETE:
- {
+ case DCD_EVENT_XFER_COMPLETE: {
// Invoke the class callback associated with the endpoint address
uint8_t const ep_addr = event.xfer_complete.ep_addr;
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const ep_dir = tu_edpt_dir(ep_addr);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const ep_dir = tu_edpt_dir(ep_addr);
- TU_LOG(USBD_DBG, "on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
+ TU_LOG_USBD("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
- _usbd_dev.ep_status[epnum][ep_dir].busy = false;
+ _usbd_dev.ep_status[epnum][ep_dir].busy = 0;
_usbd_dev.ep_status[epnum][ep_dir].claimed = 0;
- if ( 0 == epnum )
- {
- usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len);
- }
- else
- {
- usbd_class_driver_t const * driver = get_driver( _usbd_dev.ep2drv[epnum][ep_dir] );
- TU_ASSERT(driver, );
+ if (0 == epnum) {
+ usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result,
+ event.xfer_complete.len);
+ } else {
+ usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]);
+ TU_ASSERT(driver,);
- TU_LOG(USBD_DBG, " %s xfer callback\r\n", driver->name);
- driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t)event.xfer_complete.result, event.xfer_complete.len);
+ TU_LOG_USBD(" %s xfer callback\r\n", driver->name);
+ driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
}
+ break;
}
- break;
case DCD_EVENT_SUSPEND:
// NOTE: When plugging/unplugging device, the D+/D- state are unstable and
// can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event
// e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected
- if ( _usbd_dev.connected )
- {
- TU_LOG(USBD_DBG, ": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en);
+ if (_usbd_dev.connected) {
+ TU_LOG_USBD(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en);
if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en);
- }else
- {
- TU_LOG(USBD_DBG, " Skipped\r\n");
+ } else {
+ TU_LOG_USBD(" Skipped\r\n");
}
- break;
+ break;
case DCD_EVENT_RESUME:
- if ( _usbd_dev.connected )
- {
- TU_LOG(USBD_DBG, "\r\n");
+ if (_usbd_dev.connected) {
+ TU_LOG_USBD("\r\n");
if (tud_resume_cb) tud_resume_cb();
- }else
- {
- TU_LOG(USBD_DBG, " Skipped\r\n");
+ } else {
+ TU_LOG_USBD(" Skipped\r\n");
}
- break;
+ break;
case USBD_EVENT_FUNC_CALL:
- TU_LOG(USBD_DBG, "\r\n");
- if ( event.func_call.func ) event.func_call.func(event.func_call.param);
- break;
+ TU_LOG_USBD("\r\n");
+ if (event.func_call.func) event.func_call.func(event.func_call.param);
+ break;
case DCD_EVENT_SOF:
default:
TU_BREAKPOINT();
- break;
+ break;
}
#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO
@@ -606,44 +629,37 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr)
//--------------------------------------------------------------------+
// Helper to invoke class driver control request handler
-static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request)
-{
+static bool invoke_class_control(uint8_t rhport, usbd_class_driver_t const * driver, tusb_control_request_t const * request) {
usbd_control_set_complete_callback(driver->control_xfer_cb);
- TU_LOG(USBD_DBG, " %s control request\r\n", driver->name);
+ TU_LOG_USBD(" %s control request\r\n", driver->name);
return driver->control_xfer_cb(rhport, CONTROL_STAGE_SETUP, request);
}
// This handles the actual request and its response.
// return false will cause its caller to stall control endpoint
-static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
-{
+static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) {
usbd_control_set_complete_callback(NULL);
-
TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID);
// Vendor request
- if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR )
- {
+ if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) {
TU_VERIFY(tud_vendor_control_xfer_cb);
usbd_control_set_complete_callback(tud_vendor_control_xfer_cb);
return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request);
}
-#if CFG_TUSB_DEBUG >= 2
- if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME)
- {
- TU_LOG(USBD_DBG, " %s", tu_str_std_request[p_request->bRequest]);
- if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG(USBD_DBG, "\r\n");
+#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
+ if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) {
+ TU_LOG_USBD(" %s", tu_str_std_request[p_request->bRequest]);
+ if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) TU_LOG_USBD("\r\n");
}
#endif
- switch ( p_request->bmRequestType_bit.recipient )
- {
+ switch ( p_request->bmRequestType_bit.recipient ) {
//------------- Device Requests e.g in enumeration -------------//
case TUSB_REQ_RCPT_DEVICE:
- if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type )
- {
+ if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) {
uint8_t const itf = tu_u16_low(p_request->wIndex);
TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
@@ -654,15 +670,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
return invoke_class_control(rhport, driver, p_request);
}
- if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
- {
+ if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) {
// Non standard request is not supported
TU_BREAKPOINT();
return false;
}
- switch ( p_request->bRequest )
- {
+ switch ( p_request->bRequest ) {
case TUSB_REQ_SET_ADDRESS:
// Depending on mcu, status phase could be sent either before or after changing device address,
// or even require stack to not response with status at all
@@ -673,24 +687,20 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
_usbd_dev.addressed = 1;
break;
- case TUSB_REQ_GET_CONFIGURATION:
- {
+ case TUSB_REQ_GET_CONFIGURATION: {
uint8_t cfg_num = _usbd_dev.cfg_num;
tud_control_xfer(rhport, p_request, &cfg_num, 1);
}
break;
- case TUSB_REQ_SET_CONFIGURATION:
- {
+ case TUSB_REQ_SET_CONFIGURATION: {
uint8_t const cfg_num = (uint8_t) p_request->wValue;
// Only process if new configure is different
- if (_usbd_dev.cfg_num != cfg_num)
- {
- if ( _usbd_dev.cfg_num )
- {
+ if (_usbd_dev.cfg_num != cfg_num) {
+ if ( _usbd_dev.cfg_num ) {
// already configured: need to clear all endpoints and driver first
- TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
+ TU_LOG_USBD(" Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
// close all non-control endpoints, cancel all pending transfers if any
dcd_edpt_close_all(rhport);
@@ -702,8 +712,14 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
_usbd_dev.speed = speed; // restore speed
}
- // switch to new configuration if not zero
- if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) );
+ // Handle the new configuration and execute the corresponding callback
+ if ( cfg_num ) {
+ // switch to new configuration if not zero
+ TU_ASSERT( process_set_config(rhport, cfg_num) );
+ if ( tud_mount_cb ) tud_mount_cb();
+ } else {
+ if ( tud_umount_cb ) tud_umount_cb();
+ }
}
_usbd_dev.cfg_num = cfg_num;
@@ -719,7 +735,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Only support remote wakeup for device feature
TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
- TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n");
+ TU_LOG_USBD(" Enable Remote Wakeup\r\n");
// Host may enable remote wake up before suspending especially HID device
_usbd_dev.remote_wakeup_en = true;
@@ -730,22 +746,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Only support remote wakeup for device feature
TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
- TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n");
+ TU_LOG_USBD(" Disable Remote Wakeup\r\n");
// Host may disable remote wake up after resuming
_usbd_dev.remote_wakeup_en = false;
tud_control_status(rhport, p_request);
break;
- case TUSB_REQ_GET_STATUS:
- {
+ case TUSB_REQ_GET_STATUS: {
// Device status bit mask
// - Bit 0: Self Powered
// - Bit 1: Remote Wakeup enabled
uint16_t status = (uint16_t) ((_usbd_dev.self_powered ? 1u : 0u) | (_usbd_dev.remote_wakeup_en ? 2u : 0u));
tud_control_xfer(rhport, p_request, &status, 2);
+ break;
}
- break;
// Unknown/Unsupported request
default: TU_BREAKPOINT(); return false;
@@ -753,8 +768,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
break;
//------------- Class/Interface Specific Request -------------//
- case TUSB_REQ_RCPT_INTERFACE:
- {
+ case TUSB_REQ_RCPT_INTERFACE: {
uint8_t const itf = tu_u16_low(p_request->wIndex);
TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
@@ -763,25 +777,21 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// all requests to Interface (STD or Class) is forwarded to class driver.
// notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE
- if ( !invoke_class_control(rhport, driver, p_request) )
- {
+ if ( !invoke_class_control(rhport, driver, p_request) ) {
// For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class
// driver doesn't use alternate settings or implement this
TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type);
- switch(p_request->bRequest)
- {
+ switch(p_request->bRequest) {
case TUSB_REQ_GET_INTERFACE:
case TUSB_REQ_SET_INTERFACE:
// Clear complete callback if driver set since it can also stall the request.
usbd_control_set_complete_callback(NULL);
- if (TUSB_REQ_GET_INTERFACE == p_request->bRequest)
- {
+ if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) {
uint8_t alternate = 0;
tud_control_xfer(rhport, p_request, &alternate, 1);
- }else
- {
+ }else {
tud_control_status(rhport, p_request);
}
break;
@@ -789,54 +799,42 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
default: return false;
}
}
+ break;
}
- break;
//------------- Endpoint Request -------------//
- case TUSB_REQ_RCPT_ENDPOINT:
- {
+ case TUSB_REQ_RCPT_ENDPOINT: {
uint8_t const ep_addr = tu_u16_low(p_request->wIndex);
uint8_t const ep_num = tu_edpt_number(ep_addr);
uint8_t const ep_dir = tu_edpt_dir(ep_addr);
TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) );
-
usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]);
- if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type )
- {
+ if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) {
// Forward class request to its driver
TU_VERIFY(driver);
return invoke_class_control(rhport, driver, p_request);
- }
- else
- {
+ } else {
// Handle STD request to endpoint
- switch ( p_request->bRequest )
- {
- case TUSB_REQ_GET_STATUS:
- {
+ switch ( p_request->bRequest ) {
+ case TUSB_REQ_GET_STATUS: {
uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000;
tud_control_xfer(rhport, p_request, &status, 2);
}
break;
case TUSB_REQ_CLEAR_FEATURE:
- case TUSB_REQ_SET_FEATURE:
- {
- if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue )
- {
- if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest )
- {
+ case TUSB_REQ_SET_FEATURE: {
+ if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) {
+ if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) {
usbd_edpt_clear_stall(rhport, ep_addr);
- }else
- {
+ }else {
usbd_edpt_stall(rhport, ep_addr);
}
}
- if (driver)
- {
+ if (driver) {
// Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request
// We will also forward std request targeted endpoint to class drivers as well
@@ -852,14 +850,18 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
break;
// Unknown/Unsupported request
- default: TU_BREAKPOINT(); return false;
+ default:
+ TU_BREAKPOINT();
+ return false;
}
}
}
break;
// Unknown recipient
- default: TU_BREAKPOINT(); return false;
+ default:
+ TU_BREAKPOINT();
+ return false;
}
return true;
@@ -913,7 +915,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
if ( (sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len) )
{
// Open successfully
- TU_LOG(USBD_DBG, " %s opened\r\n", driver->name);
+ TU_LOG_USBD(" %s opened\r\n", driver->name);
// Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or
// BTH (even CDC) with class in device descriptor (single interface)
@@ -956,9 +958,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT);
}
- // invoke callback
- if (tud_mount_cb) tud_mount_cb();
-
return true;
}
@@ -972,7 +971,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
{
case TUSB_DESC_DEVICE:
{
- TU_LOG(USBD_DBG, " Device\r\n");
+ TU_LOG_USBD(" Device\r\n");
void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb();
@@ -996,7 +995,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
case TUSB_DESC_BOS:
{
- TU_LOG(USBD_DBG, " BOS\r\n");
+ TU_LOG_USBD(" BOS\r\n");
// requested by host if USB > 2.0 ( i.e 2.1 or 3.x )
if (!tud_descriptor_bos_cb) return false;
@@ -1018,12 +1017,12 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
if ( desc_type == TUSB_DESC_CONFIGURATION )
{
- TU_LOG(USBD_DBG, " Configuration[%u]\r\n", desc_index);
+ TU_LOG_USBD(" Configuration[%u]\r\n", desc_index);
desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index);
}else
{
// Host only request this after getting Device Qualifier descriptor
- TU_LOG(USBD_DBG, " Other Speed Configuration\r\n");
+ TU_LOG_USBD(" Other Speed Configuration\r\n");
TU_VERIFY( tud_descriptor_other_speed_configuration_cb );
desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index);
}
@@ -1039,7 +1038,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
case TUSB_DESC_STRING:
{
- TU_LOG(USBD_DBG, " String[%u]\r\n", desc_index);
+ TU_LOG_USBD(" String[%u]\r\n", desc_index);
// String Descriptor always uses the desc set from user
uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex));
@@ -1052,7 +1051,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
case TUSB_DESC_DEVICE_QUALIFIER:
{
- TU_LOG(USBD_DBG, " Device Qualifier\r\n");
+ TU_LOG_USBD(" Device Qualifier\r\n");
TU_VERIFY( tud_descriptor_device_qualifier_cb );
@@ -1071,66 +1070,69 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
//--------------------------------------------------------------------+
// DCD Event Handler
//--------------------------------------------------------------------+
-TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const * event, bool in_isr)
-{
- switch (event->event_id)
- {
+TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) {
+ bool send = false;
+ switch (event->event_id) {
case DCD_EVENT_UNPLUGGED:
- _usbd_dev.connected = 0;
- _usbd_dev.addressed = 0;
- _usbd_dev.cfg_num = 0;
- _usbd_dev.suspended = 0;
- osal_queue_send(_usbd_q, event, in_isr);
- break;
+ _usbd_dev.connected = 0;
+ _usbd_dev.addressed = 0;
+ _usbd_dev.cfg_num = 0;
+ _usbd_dev.suspended = 0;
+ send = true;
+ break;
case DCD_EVENT_SUSPEND:
// NOTE: When plugging/unplugging device, the D+/D- state are unstable and
// can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ).
// In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish
// suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected
- if ( _usbd_dev.connected )
- {
+ if (_usbd_dev.connected) {
_usbd_dev.suspended = 1;
- osal_queue_send(_usbd_q, event, in_isr);
+ send = true;
}
- break;
+ break;
case DCD_EVENT_RESUME:
// skip event if not connected (especially required for SAMD)
- if ( _usbd_dev.connected )
- {
+ if (_usbd_dev.connected) {
_usbd_dev.suspended = 0;
- osal_queue_send(_usbd_q, event, in_isr);
+ send = true;
}
- break;
+ break;
case DCD_EVENT_SOF:
- // SOF driver handler in ISR context
- for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++)
- {
- usbd_class_driver_t const * driver = get_driver(i);
- if (driver && driver->sof)
- {
- driver->sof(event->rhport, event->sof.frame_count);
- }
- }
-
// Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup
// which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational
- if ( _usbd_dev.suspended )
- {
+ if (_usbd_dev.suspended) {
_usbd_dev.suspended = 0;
- dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME };
- osal_queue_send(_usbd_q, &event_resume, in_isr);
+ dcd_event_t const event_resume = {.rhport = event->rhport, .event_id = DCD_EVENT_RESUME};
+ queue_event(&event_resume, in_isr);
+ }
+
+ // SOF driver handler in ISR context
+ for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
+ usbd_class_driver_t const* driver = get_driver(i);
+ if (driver && driver->sof) {
+ driver->sof(event->rhport, event->sof.frame_count);
+ }
}
// skip osal queue for SOF in usbd task
- break;
+ break;
+
+ case DCD_EVENT_SETUP_RECEIVED:
+ _usbd_dev.setup_count++;
+ send = true;
+ break;
default:
- osal_queue_send(_usbd_q, event, in_isr);
- break;
+ send = true;
+ break;
+ }
+
+ if (send) {
+ queue_event(event, in_isr);
}
}
@@ -1174,26 +1176,22 @@ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count
}
// Helper to defer an isr function
-void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr)
-{
- dcd_event_t event =
- {
+void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) {
+ dcd_event_t event = {
.rhport = 0,
.event_id = USBD_EVENT_FUNC_CALL,
};
-
event.func_call.func = func;
event.func_call.param = param;
- dcd_event_handler(&event, in_isr);
+ queue_event(&event, in_isr);
}
//--------------------------------------------------------------------+
// USBD Endpoint API
//--------------------------------------------------------------------+
-bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep)
-{
+bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
rhport = _usbd_rhport;
TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX);
@@ -1202,59 +1200,59 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep)
return dcd_edpt_open(rhport, desc_ep);
}
-bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr)
-{
+bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) {
(void) rhport;
// TODO add this check later, also make sure we don't starve an out endpoint while suspending
// TU_VERIFY(tud_ready());
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir];
return tu_edpt_claim(ep_state, _usbd_mutex);
}
-bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr)
-{
+bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) {
(void) rhport;
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir];
return tu_edpt_release(ep_state, _usbd_mutex);
}
-bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
-{
+bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
rhport = _usbd_rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
// TODO skip ready() check for now since enumeration also use this API
// TU_VERIFY(tud_ready());
- TU_LOG(USBD_DBG, " Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes);
+ TU_LOG_USBD(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes);
+#if CFG_TUD_LOG_LEVEL >= 3
+ if(dir == TUSB_DIR_IN) {
+ TU_LOG_MEM(CFG_TUD_LOG_LEVEL, buffer, total_bytes, 2);
+ }
+#endif
// Attempt to transfer on a busy endpoint, sound like an race condition !
TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);
// Set busy first since the actual transfer can be complete before dcd_edpt_xfer()
// could return and USBD task can preempt and clear the busy
- _usbd_dev.ep_status[epnum][dir].busy = true;
+ _usbd_dev.ep_status[epnum][dir].busy = 1;
- if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) )
- {
+ if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes)) {
return true;
- }else
- {
+ } else {
// DCD error, mark endpoint as ready to allow next transfer
- _usbd_dev.ep_status[epnum][dir].busy = false;
+ _usbd_dev.ep_status[epnum][dir].busy = 0;
_usbd_dev.ep_status[epnum][dir].claimed = 0;
- TU_LOG(USBD_DBG, "FAILED\r\n");
+ TU_LOG_USBD("FAILED\r\n");
TU_BREAKPOINT();
return false;
}
@@ -1264,117 +1262,104 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
// bytes should be written and second to keep the return value free to give back a boolean
// success message. If total_bytes is too big, the FIFO will copy only what is available
// into the USB buffer!
-bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
-{
+bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) {
rhport = _usbd_rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
- TU_LOG(USBD_DBG, " Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes);
+ TU_LOG_USBD(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes);
// Attempt to transfer on a busy endpoint, sound like an race condition !
TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);
// Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return
// and usbd task can preempt and clear the busy
- _usbd_dev.ep_status[epnum][dir].busy = true;
+ _usbd_dev.ep_status[epnum][dir].busy = 1;
- if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes))
- {
- TU_LOG(USBD_DBG, "OK\r\n");
+ if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) {
+ TU_LOG_USBD("OK\r\n");
return true;
- }else
- {
+ } else {
// DCD error, mark endpoint as ready to allow next transfer
- _usbd_dev.ep_status[epnum][dir].busy = false;
+ _usbd_dev.ep_status[epnum][dir].busy = 0;
_usbd_dev.ep_status[epnum][dir].claimed = 0;
- TU_LOG(USBD_DBG, "failed\r\n");
+ TU_LOG_USBD("failed\r\n");
TU_BREAKPOINT();
return false;
}
}
-bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
-{
+bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) {
(void) rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
return _usbd_dev.ep_status[epnum][dir].busy;
}
-void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
-{
+void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
rhport = _usbd_rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
// only stalled if currently cleared
- if ( !_usbd_dev.ep_status[epnum][dir].stalled )
- {
- TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr);
+ if (!_usbd_dev.ep_status[epnum][dir].stalled) {
+ TU_LOG_USBD(" Stall EP %02X\r\n", ep_addr);
dcd_edpt_stall(rhport, ep_addr);
- _usbd_dev.ep_status[epnum][dir].stalled = true;
- _usbd_dev.ep_status[epnum][dir].busy = true;
+ _usbd_dev.ep_status[epnum][dir].stalled = 1;
+ _usbd_dev.ep_status[epnum][dir].busy = 1;
}
}
-void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
-{
+void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
rhport = _usbd_rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
// only clear if currently stalled
- if ( _usbd_dev.ep_status[epnum][dir].stalled )
- {
- TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr);
+ if (_usbd_dev.ep_status[epnum][dir].stalled) {
+ TU_LOG_USBD(" Clear Stall EP %02X\r\n", ep_addr);
dcd_edpt_clear_stall(rhport, ep_addr);
- _usbd_dev.ep_status[epnum][dir].stalled = false;
- _usbd_dev.ep_status[epnum][dir].busy = false;
+ _usbd_dev.ep_status[epnum][dir].stalled = 0;
+ _usbd_dev.ep_status[epnum][dir].busy = 0;
}
}
-bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr)
-{
+bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) {
(void) rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
return _usbd_dev.ep_status[epnum][dir].stalled;
}
/**
* usbd_edpt_close will disable an endpoint.
- *
* In progress transfers on this EP may be delivered after this call.
- *
*/
-void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr)
-{
+void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
rhport = _usbd_rhport;
TU_ASSERT(dcd_edpt_close, /**/);
- TU_LOG(USBD_DBG, " CLOSING Endpoint: 0x%02X\r\n", ep_addr);
+ TU_LOG_USBD(" CLOSING Endpoint: 0x%02X\r\n", ep_addr);
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
dcd_edpt_close(rhport, ep_addr);
- _usbd_dev.ep_status[epnum][dir].stalled = false;
- _usbd_dev.ep_status[epnum][dir].busy = false;
- _usbd_dev.ep_status[epnum][dir].claimed = false;
+ _usbd_dev.ep_status[epnum][dir].stalled = 0;
+ _usbd_dev.ep_status[epnum][dir].busy = 0;
+ _usbd_dev.ep_status[epnum][dir].claimed = 0;
return;
}
-void usbd_sof_enable(uint8_t rhport, bool en)
-{
+void usbd_sof_enable(uint8_t rhport, bool en) {
rhport = _usbd_rhport;
// TODO: Check needed if all drivers including the user sof_cb does not need an active SOF ISR any more.
@@ -1382,8 +1367,7 @@ void usbd_sof_enable(uint8_t rhport, bool en)
dcd_sof_enable(rhport, en);
}
-bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size)
-{
+bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
rhport = _usbd_rhport;
TU_ASSERT(dcd_edpt_iso_alloc);
@@ -1392,20 +1376,19 @@ bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packe
return dcd_edpt_iso_alloc(rhport, ep_addr, largest_packet_size);
}
-bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep)
-{
+bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
rhport = _usbd_rhport;
uint8_t const epnum = tu_edpt_number(desc_ep->bEndpointAddress);
- uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress);
+ uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress);
TU_ASSERT(dcd_edpt_iso_activate);
TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX);
TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed));
- _usbd_dev.ep_status[epnum][dir].stalled = false;
- _usbd_dev.ep_status[epnum][dir].busy = false;
- _usbd_dev.ep_status[epnum][dir].claimed = false;
+ _usbd_dev.ep_status[epnum][dir].stalled = 0;
+ _usbd_dev.ep_status[epnum][dir].busy = 0;
+ _usbd_dev.ep_status[epnum][dir].claimed = 0;
return dcd_edpt_iso_activate(rhport, desc_ep);
}
diff --git a/src/device/usbd.h b/src/device/usbd.h
index 255e5a844..0197628e2 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -37,9 +37,12 @@ extern "C" {
// Application API
//--------------------------------------------------------------------+
-// Init device stack
+// Init device stack on roothub port
bool tud_init (uint8_t rhport);
+// Deinit device stack on roothub port
+bool tud_deinit(uint8_t rhport);
+
// Check if device stack is already initialized
bool tud_inited(void);
@@ -50,8 +53,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr);
// Task function should be called in main/rtos loop
TU_ATTR_ALWAYS_INLINE static inline
-void tud_task (void)
-{
+void tud_task (void) {
tud_task_ext(UINT32_MAX, false);
}
@@ -80,8 +82,7 @@ bool tud_suspended(void);
// Check if device is ready to transfer
TU_ATTR_ALWAYS_INLINE static inline
-bool tud_ready(void)
-{
+bool tud_ready(void) {
return tud_mounted() && !tud_suspended();
}
@@ -148,6 +149,9 @@ TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en);
// Invoked when usb bus is resumed
TU_ATTR_WEAK void tud_resume_cb(void);
+// Invoked when there is a new usb event, which need to be processed by tud_task()/tud_task_ext()
+void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr);
+
// Invoked when received control request with VENDOR TYPE
TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
@@ -347,8 +351,8 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Standard Interface Association Descriptor (IAD) */
#define TUD_AUDIO_DESC_IAD_LEN 8
-#define TUD_AUDIO_DESC_IAD(_firstitfs, _nitfs, _stridx) \
- TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitfs, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx
+#define TUD_AUDIO_DESC_IAD(_firstitf, _nitfs, _stridx) \
+ TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitf, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx
/* Standard AC Interface Descriptor(4.7.1) */
#define TUD_AUDIO_DESC_STD_AC_LEN 9
@@ -392,6 +396,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
// For more channels, add definitions here
+/* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */
+#define TUD_AUDIO_DESC_STD_AC_INT_EP_LEN 7
+#define TUD_AUDIO_DESC_STD_AC_INT_EP(_ep, _interval) \
+ TUD_AUDIO_DESC_STD_AC_INT_EP_LEN, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(6), _interval
+
/* Standard AS Interface Descriptor(4.9.1) */
#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9
#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \
@@ -420,7 +429,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */
#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7
#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \
- TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_NO_SYNC | TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval
+ TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval
// AUDIO simple descriptor (UAC2) for 1 microphone input
// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source
@@ -443,7 +452,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
#define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \
/* Standard Interface Association Descriptor (IAD) */\
- TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
+ TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
/* Standard AC Interface Descriptor(4.7.1) */\
TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
/* Class-Specific AC Interface Header Descriptor(4.7.2) */\
@@ -467,7 +476,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
- TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\
+ TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
@@ -492,7 +501,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
#define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \
/* Standard Interface Association Descriptor (IAD) */\
- TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
+ TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
/* Standard AC Interface Descriptor(4.7.1) */\
TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
/* Class-Specific AC Interface Header Descriptor(4.7.2) */\
@@ -516,7 +525,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
- TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\
+ TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000)
@@ -540,7 +549,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \
/* Standard Interface Association Descriptor (IAD) */\
- TUD_AUDIO_DESC_IAD(/*_firstitfs*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
+ TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\
/* Standard AC Interface Descriptor(4.7.1) */\
TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\
/* Class-Specific AC Interface Header Descriptor(4.7.2) */\
@@ -564,7 +573,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\
TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\
/* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\
- TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 0x04 : 0x01),\
+ TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\
TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\
/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\
@@ -773,10 +782,6 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
#define TUD_BT_PROTOCOL_PRIMARY_CONTROLLER 0x01
#define TUD_BT_PROTOCOL_AMP_CONTROLLER 0x02
-#ifndef CFG_TUD_BTH_ISO_ALT_COUNT
-#define CFG_TUD_BTH_ISO_ALT_COUNT 0
-#endif
-
// Length of template descriptor: 38 bytes + number of ISO alternatives * 23
#define TUD_BTH_DESC_LEN (8 + 9 + 7 + 7 + 7 + (CFG_TUD_BTH_ISO_ALT_COUNT) * (9 + 7 + 7))
diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c
index ea8eef285..35cce1f7e 100644
--- a/src/device/usbd_control.c
+++ b/src/device/usbd_control.c
@@ -32,30 +32,38 @@
#include "tusb.h"
#include "device/usbd_pvt.h"
-#if CFG_TUSB_DEBUG >= 2
+//--------------------------------------------------------------------+
+// Callback weak stubs (called if application does not provide)
+//--------------------------------------------------------------------+
+TU_ATTR_WEAK void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) {
+ (void) rhport;
+ (void) request;
+}
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
extern void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback);
#endif
-enum
-{
+enum {
EDPT_CTRL_OUT = 0x00,
- EDPT_CTRL_IN = 0x80
+ EDPT_CTRL_IN = 0x80
};
-typedef struct
-{
+typedef struct {
tusb_control_request_t request;
-
uint8_t* buffer;
uint16_t data_len;
uint16_t total_xferred;
-
usbd_control_xfer_cb_t complete_cb;
} usbd_control_xfer_t;
tu_static usbd_control_xfer_t _ctrl_xfer;
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN
tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE];
//--------------------------------------------------------------------+
@@ -63,20 +71,18 @@ tu_static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE];
//--------------------------------------------------------------------+
// Queue ZLP status transaction
-static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const * request)
-{
+static inline bool _status_stage_xact(uint8_t rhport, tusb_control_request_t const* request) {
// Opposite to endpoint in Data Phase
uint8_t const ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN;
return usbd_edpt_xfer(rhport, ep_addr, NULL, 0);
}
// Status phase
-bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request)
-{
- _ctrl_xfer.request = (*request);
- _ctrl_xfer.buffer = NULL;
+bool tud_control_status(uint8_t rhport, tusb_control_request_t const* request) {
+ _ctrl_xfer.request = (*request);
+ _ctrl_xfer.buffer = NULL;
_ctrl_xfer.total_xferred = 0;
- _ctrl_xfer.data_len = 0;
+ _ctrl_xfer.data_len = 0;
return _status_stage_xact(rhport, request);
}
@@ -84,16 +90,15 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request)
// Queue a transaction in Data Stage
// Each transaction has up to Endpoint0's max packet size.
// This function can also transfer an zero-length packet
-static bool _data_stage_xact(uint8_t rhport)
-{
- uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE);
+static bool _data_stage_xact(uint8_t rhport) {
+ uint16_t const xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred,
+ CFG_TUD_ENDPOINT0_SIZE);
uint8_t ep_addr = EDPT_CTRL_OUT;
- if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN )
- {
+ if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) {
ep_addr = EDPT_CTRL_IN;
- if ( xact_len ) {
+ if (xact_len) {
TU_VERIFY(0 == tu_memcpy_s(_usbd_ctrl_buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len));
}
}
@@ -103,29 +108,24 @@ static bool _data_stage_xact(uint8_t rhport)
// Transmit data to/from the control endpoint.
// If the request's wLength is zero, a status packet is sent instead.
-bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, void* buffer, uint16_t len)
-{
- _ctrl_xfer.request = (*request);
- _ctrl_xfer.buffer = (uint8_t*) buffer;
+bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const* request, void* buffer, uint16_t len) {
+ _ctrl_xfer.request = (*request);
+ _ctrl_xfer.buffer = (uint8_t*) buffer;
_ctrl_xfer.total_xferred = 0U;
- _ctrl_xfer.data_len = tu_min16(len, request->wLength);
+ _ctrl_xfer.data_len = tu_min16(len, request->wLength);
- if (request->wLength > 0U)
- {
- if(_ctrl_xfer.data_len > 0U)
- {
+ if (request->wLength > 0U) {
+ if (_ctrl_xfer.data_len > 0U) {
TU_ASSERT(buffer);
}
// TU_LOG2(" Control total data length is %u bytes\r\n", _ctrl_xfer.data_len);
// Data stage
- TU_ASSERT( _data_stage_xact(rhport) );
- }
- else
- {
+ TU_ASSERT(_data_stage_xact(rhport));
+ } else {
// Status stage
- TU_ASSERT( _status_stage_xact(rhport, request) );
+ TU_ASSERT(_status_stage_xact(rhport, request));
}
return true;
@@ -134,49 +134,42 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo
//--------------------------------------------------------------------+
// USBD API
//--------------------------------------------------------------------+
-
void usbd_control_reset(void);
-void usbd_control_set_request(tusb_control_request_t const *request);
-void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp );
-bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
+void usbd_control_set_request(tusb_control_request_t const* request);
+void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp);
+bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
-void usbd_control_reset(void)
-{
+void usbd_control_reset(void) {
tu_varclr(&_ctrl_xfer);
}
// Set complete callback
-void usbd_control_set_complete_callback( usbd_control_xfer_cb_t fp )
-{
+void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp) {
_ctrl_xfer.complete_cb = fp;
}
// for dcd_set_address where DCD is responsible for status response
-void usbd_control_set_request(tusb_control_request_t const *request)
-{
- _ctrl_xfer.request = (*request);
- _ctrl_xfer.buffer = NULL;
+void usbd_control_set_request(tusb_control_request_t const* request) {
+ _ctrl_xfer.request = (*request);
+ _ctrl_xfer.buffer = NULL;
_ctrl_xfer.total_xferred = 0;
- _ctrl_xfer.data_len = 0;
+ _ctrl_xfer.data_len = 0;
}
// callback when a transaction complete on
// - DATA stage of control endpoint or
// - Status stage
-bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
+bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) result;
// Endpoint Address is opposite to direction bit, this is Status Stage complete event
- if ( tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction )
- {
+ if (tu_edpt_dir(ep_addr) != _ctrl_xfer.request.bmRequestType_bit.direction) {
TU_ASSERT(0 == xferred_bytes);
// invoke optional dcd hook if available
- if (dcd_edpt0_status_complete) dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request);
+ dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request);
- if (_ctrl_xfer.complete_cb)
- {
+ if (_ctrl_xfer.complete_cb) {
// TODO refactor with usbd_driver_print_control_complete_name
_ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request);
}
@@ -184,11 +177,10 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result
return true;
}
- if ( _ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT )
- {
+ if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_OUT) {
TU_VERIFY(_ctrl_xfer.buffer);
memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes);
- TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2);
+ TU_LOG_MEM(CFG_TUD_LOG_LEVEL, _usbd_ctrl_buf, xferred_bytes, 2);
}
_ctrl_xfer.total_xferred += (uint16_t) xferred_bytes;
@@ -196,37 +188,32 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result
// Data Stage is complete when all request's length are transferred or
// a short packet is sent including zero-length packet.
- if ( (_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE) )
- {
+ if ((_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) ||
+ (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE)) {
// DATA stage is complete
bool is_ok = true;
// invoke complete callback if set
// callback can still stall control in status phase e.g out data does not make sense
- if ( _ctrl_xfer.complete_cb )
- {
- #if CFG_TUSB_DEBUG >= 2
+ if (_ctrl_xfer.complete_cb) {
+ #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb);
#endif
is_ok = _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_DATA, &_ctrl_xfer.request);
}
- if ( is_ok )
- {
+ if (is_ok) {
// Send status
- TU_ASSERT( _status_stage_xact(rhport, &_ctrl_xfer.request) );
- }else
- {
+ TU_ASSERT(_status_stage_xact(rhport, &_ctrl_xfer.request));
+ } else {
// Stall both IN and OUT control endpoint
dcd_edpt_stall(rhport, EDPT_CTRL_OUT);
dcd_edpt_stall(rhport, EDPT_CTRL_IN);
}
- }
- else
- {
+ } else {
// More data to transfer
- TU_ASSERT( _data_stage_xact(rhport) );
+ TU_ASSERT(_data_stage_xact(rhport));
}
return true;
diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h
index 8393d3469..47752f32c 100644
--- a/src/device/usbd_pvt.h
+++ b/src/device/usbd_pvt.h
@@ -23,8 +23,8 @@
*
* This file is part of the TinyUSB stack.
*/
-#ifndef USBD_PVT_H_
-#define USBD_PVT_H_
+#ifndef _TUSB_USBD_PVT_H_
+#define _TUSB_USBD_PVT_H_
#include "osal/osal.h"
#include "common/tusb_fifo.h"
@@ -33,17 +33,19 @@
extern "C" {
#endif
+#define TU_LOG_USBD(...) TU_LOG(CFG_TUD_LOG_LEVEL, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// Class Driver API
//--------------------------------------------------------------------+
-typedef struct
-{
- #if CFG_TUSB_DEBUG >= 2
+typedef struct {
+ #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
char const* name;
#endif
void (* init ) (void);
+ bool (* deinit ) (void);
void (* reset ) (uint8_t rhport);
uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len);
bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
@@ -52,7 +54,7 @@ typedef struct
} usbd_class_driver_t;
// Invoked when initializing device stack to get additional class drivers.
-// Can optionally implemented by application to extend/overwrite class driver support.
+// Can be implemented by application to extend/overwrite class driver support.
// Note: The drivers array must be accessible at all time when stack is active
usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK;
@@ -104,8 +106,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endp
// Check if endpoint is ready (not busy and not stalled)
TU_ATTR_ALWAYS_INLINE static inline
-bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr)
-{
+bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) {
return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr);
}
@@ -117,11 +118,10 @@ void usbd_sof_enable(uint8_t rhport, bool en);
*------------------------------------------------------------------*/
bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in);
-void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr );
-
+void usbd_defer_func(osal_task_func_t func, void *param, bool in_isr);
#ifdef __cplusplus
}
#endif
-#endif /* USBD_PVT_H_ */
+#endif
diff --git a/src/host/hcd.h b/src/host/hcd.h
index 623c12a12..5547c7cc5 100644
--- a/src/host/hcd.h
+++ b/src/host/hcd.h
@@ -39,8 +39,10 @@
// Configuration
//--------------------------------------------------------------------+
+// Max number of endpoints pair per device
+// TODO optimize memory usage
#ifndef CFG_TUH_ENDPOINT_MAX
- #define CFG_TUH_ENDPOINT_MAX (CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3)
+ #define CFG_TUH_ENDPOINT_MAX 16
// #ifdef TUP_HCD_ENDPOINT_MAX
// #define CFG_TUH_ENDPPOINT_MAX TUP_HCD_ENDPOINT_MAX
// #else
@@ -103,17 +105,36 @@ typedef struct
} hcd_devtree_info_t;
//--------------------------------------------------------------------+
+// Memory API
+//--------------------------------------------------------------------+
+
+// clean/flush data cache: write cache -> memory.
+// Required before an DMA TX transfer to make sure data is in memory
+bool hcd_dcache_clean(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+
+// invalidate data cache: mark cache as invalid, next read will read from memory
+// Required BOTH before and after an DMA RX transfer
+bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+
+// clean and invalidate data cache
+// Required before an DMA transfer where memory is both read/write by DMA
+bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+
+//--------------------------------------------------------------------+
// Controller API
//--------------------------------------------------------------------+
// optional hcd configuration, called by tuh_configure()
-bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) TU_ATTR_WEAK;
+bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);
// Initialize controller to host mode
bool hcd_init(uint8_t rhport);
+// De-initialize controller
+bool hcd_deinit(uint8_t rhport);
+
// Interrupt Handler
-void hcd_int_handler(uint8_t rhport);
+void hcd_int_handler(uint8_t rhport, bool in_isr);
// Enable USB interrupt
void hcd_int_enable (uint8_t rhport);
@@ -131,10 +152,11 @@ uint32_t hcd_frame_number(uint8_t rhport);
// Get the current connect status of roothub port
bool hcd_port_connect_status(uint8_t rhport);
-// Reset USB bus on the port
+// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete.
+// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence.
void hcd_port_reset(uint8_t rhport);
-// TODO implement later
+// Complete bus reset sequence, may be required by some controllers
void hcd_port_reset_end(uint8_t rhport);
// Get port link speed
@@ -148,16 +170,20 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr);
//--------------------------------------------------------------------+
// Open an endpoint
-bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
+bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc);
// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked
-bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
+
+// Abort a queued transfer. Note: it can only abort transfer that has not been started
+// Return true if a queued transfer is aborted, false if there is no transfer to abort
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked
-bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]);
+bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]);
// clear stall, data toggle is also reset to DATA0
-bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr);
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
//--------------------------------------------------------------------+
// USBH implemented API
@@ -175,20 +201,19 @@ extern void hcd_event_handler(hcd_event_t const* event, bool in_isr);
// Helper to send device attach event
TU_ATTR_ALWAYS_INLINE static inline
-void hcd_event_device_attach(uint8_t rhport, bool in_isr)
-{
+void hcd_event_device_attach(uint8_t rhport, bool in_isr) {
hcd_event_t event;
event.rhport = rhport;
event.event_id = HCD_EVENT_DEVICE_ATTACH;
event.connection.hub_addr = 0;
event.connection.hub_port = 0;
+
hcd_event_handler(&event, in_isr);
}
// Helper to send device removal event
TU_ATTR_ALWAYS_INLINE static inline
-void hcd_event_device_remove(uint8_t rhport, bool in_isr)
-{
+void hcd_event_device_remove(uint8_t rhport, bool in_isr) {
hcd_event_t event;
event.rhport = rhport;
event.event_id = HCD_EVENT_DEVICE_REMOVE;
@@ -200,10 +225,8 @@ void hcd_event_device_remove(uint8_t rhport, bool in_isr)
// Helper to send USB transfer event
TU_ATTR_ALWAYS_INLINE static inline
-void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr)
-{
- hcd_event_t event =
- {
+void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) {
+ hcd_event_t event = {
.rhport = 0, // TODO correct rhport
.event_id = HCD_EVENT_XFER_COMPLETE,
.dev_addr = dev_addr,
@@ -212,7 +235,6 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred
event.xfer_complete.result = result;
event.xfer_complete.len = xferred_bytes;
-
hcd_event_handler(&event, in_isr);
}
diff --git a/src/host/hub.c b/src/host/hub.c
index 386ad6aae..e97014443 100644
--- a/src/host/hub.c
+++ b/src/host/hub.c
@@ -30,9 +30,13 @@
#include "hcd.h"
#include "usbh.h"
-#include "usbh_classdriver.h"
+#include "usbh_pvt.h"
#include "hub.h"
+// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message
+#define HUB_DEBUG 2
+#define TU_LOG_DRV(...) TU_LOG(HUB_DEBUG, __VA_ARGS__)
+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
@@ -41,8 +45,8 @@ typedef struct
uint8_t itf_num;
uint8_t ep_in;
uint8_t port_count;
- uint8_t status_change; // data from status change interrupt endpoint
+ CFG_TUH_MEM_ALIGN uint8_t status_change;
CFG_TUH_MEM_ALIGN hub_port_status_response_t port_status;
CFG_TUH_MEM_ALIGN hub_status_response_t hub_status;
} hub_interface_t;
@@ -178,9 +182,13 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
//--------------------------------------------------------------------+
// CLASS-USBH API (don't require to verify parameters)
//--------------------------------------------------------------------+
-void hub_init(void)
-{
+bool hub_init(void) {
tu_memclr(hub_data, sizeof(hub_data));
+ return true;
+}
+
+bool hub_deinit(void) {
+ return true;
}
bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
@@ -218,7 +226,10 @@ void hub_close(uint8_t dev_addr)
TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, );
hub_interface_t* p_hub = get_itf(dev_addr);
- if (p_hub->ep_in) tu_memclr(p_hub, sizeof( hub_interface_t));
+ if (p_hub->ep_in) {
+ TU_LOG_DRV(" HUB close addr = %d\r\n", dev_addr);
+ tu_memclr(p_hub, sizeof( hub_interface_t));
+ }
}
bool hub_edpt_status_xfer(uint8_t dev_addr)
@@ -320,34 +331,35 @@ static void connection_clear_conn_change_complete (tuh_xfer_t* xfer);
static void connection_port_reset_complete (tuh_xfer_t* xfer);
// callback as response of interrupt endpoint polling
-bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
+bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports
(void) ep_addr;
- TU_ASSERT(result == XFER_RESULT_SUCCESS);
+ TU_VERIFY(result == XFER_RESULT_SUCCESS);
hub_interface_t* p_hub = get_itf(dev_addr);
- TU_LOG2(" Hub Status Change = 0x%02X\r\n", p_hub->status_change);
+ uint8_t const status_change = p_hub->status_change;
+ TU_LOG2(" Hub Status Change = 0x%02X\r\n", status_change);
- // Hub bit 0 is for the hub device events
- if (tu_bit_test(p_hub->status_change, 0))
- {
- if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false)
- {
+ if ( status_change == 0 ) {
+ // The status change event was neither for the hub, nor for any of its ports.
+ // This shouldn't happen, but it does with some devices.
+ // Initiate the next interrupt poll here.
+ return hub_edpt_status_xfer(dev_addr);
+ }
+
+ if (tu_bit_test(status_change, 0)) {
+ // Hub bit 0 is for the hub device events
+ if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) {
//Hub status control transfer failed, retry
hub_edpt_status_xfer(dev_addr);
}
}
- else
- {
+ else {
// Hub bits 1 to n are hub port events
- for (uint8_t port=1; port <= p_hub->port_count; port++)
- {
- if ( tu_bit_test(p_hub->status_change, port) )
- {
- if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false)
- {
+ for (uint8_t port=1; port <= p_hub->port_count; port++) {
+ if ( tu_bit_test(status_change, port) ) {
+ if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) {
//Hub status control transfer failed, retry
hub_edpt_status_xfer(dev_addr);
}
@@ -357,7 +369,6 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
}
// NOTE: next status transfer is queued by usbh.c after handling this request
-
return true;
}
@@ -428,9 +439,12 @@ static void hub_port_get_status_complete (tuh_xfer_t* xfer)
// Other changes are: L1 state
// TODO clear change
- // prepare for next hub status
- // TODO continue with status_change, or maybe we can do it again with status
- hub_edpt_status_xfer(daddr);
+ else
+ {
+ // prepare for next hub status
+ // TODO continue with status_change, or maybe we can do it again with status
+ hub_edpt_status_xfer(daddr);
+ }
}
}
diff --git a/src/host/hub.h b/src/host/hub.h
index 390740e1f..385efe6b2 100644
--- a/src/host/hub.h
+++ b/src/host/hub.h
@@ -187,16 +187,14 @@ bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp,
bool hub_edpt_status_xfer(uint8_t dev_addr);
// Reset a port
-static inline bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+TU_ATTR_ALWAYS_INLINE static inline
+bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_data);
}
// Clear Reset Change
-static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+TU_ATTR_ALWAYS_INLINE static inline
+bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data);
}
@@ -204,7 +202,8 @@ static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_por
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
-void hub_init (void);
+bool hub_init (void);
+bool hub_deinit (void);
bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
bool hub_set_config (uint8_t dev_addr, uint8_t itf_num);
bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
diff --git a/src/host/usbh.c b/src/host/usbh.c
index 3953d5b21..6a5491998 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -30,44 +30,55 @@
#include "host/hcd.h"
#include "tusb.h"
-#include "host/usbh_classdriver.h"
+#include "host/usbh_pvt.h"
#include "hub.h"
//--------------------------------------------------------------------+
// USBH Configuration
//--------------------------------------------------------------------+
-
#ifndef CFG_TUH_TASK_QUEUE_SZ
-#define CFG_TUH_TASK_QUEUE_SZ 16
+ #define CFG_TUH_TASK_QUEUE_SZ 16
#endif
#ifndef CFG_TUH_INTERFACE_MAX
-#define CFG_TUH_INTERFACE_MAX 8
+ #define CFG_TUH_INTERFACE_MAX 8
#endif
-// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message
-#define USBH_DEBUG 2
+//--------------------------------------------------------------------+
+// Weak stubs: invoked if no strong implementation is available
+//--------------------------------------------------------------------+
+TU_ATTR_WEAK bool hcd_deinit(uint8_t rhport) {
+ (void) rhport;
+ return false;
+}
+
+TU_ATTR_WEAK bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
+ (void) rhport;
+ (void) cfg_id;
+ (void) cfg_param;
+ return false;
+}
-#define TU_LOG_USBH(...) TU_LOG(USBH_DEBUG, __VA_ARGS__)
+TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) {
+ (void) rhport;
+ (void) eventid;
+ (void) in_isr;
+}
//--------------------------------------------------------------------+
// USBH-HCD common data structure
//--------------------------------------------------------------------+
-
-typedef struct
-{
+typedef struct {
// port
uint8_t rhport;
uint8_t hub_addr;
uint8_t hub_port;
- uint8_t speed;
- volatile uint8_t enumerating;
-// struct TU_ATTR_PACKED {
-// uint8_t speed : 4; // packed speed to save footprint
-// volatile uint8_t enumerating : 1;
-// uint8_t TU_RESERVED : 3;
-// };
+ struct TU_ATTR_PACKED {
+ uint8_t speed : 4; // packed speed to save footprint
+ volatile uint8_t enumerating : 1; // enumeration is in progress, false if not connected or all interfaces are configured
+ uint8_t TU_RESERVED : 3;
+ };
} usbh_dev0_t;
typedef struct {
@@ -79,10 +90,12 @@ typedef struct {
// Device State
struct TU_ATTR_PACKED {
- volatile uint8_t connected : 1;
- volatile uint8_t addressed : 1;
- volatile uint8_t configured : 1;
- volatile uint8_t suspended : 1;
+ volatile uint8_t connected : 1; // After 1st transfer
+ volatile uint8_t addressed : 1; // After SET_ADDR
+ volatile uint8_t configured : 1; // After SET_CONFIG and all drivers are configured
+ volatile uint8_t suspended : 1; // Bus suspended
+
+ // volatile uint8_t removing : 1; // Physically disconnected, waiting to be processed by usbh
};
// Device Descriptor
@@ -117,76 +130,94 @@ typedef struct {
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-
-#if CFG_TUSB_DEBUG >= 2
- #define DRIVER_NAME(_name) .name = _name,
+#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL
+ #define DRIVER_NAME(_name) _name
#else
- #define DRIVER_NAME(_name)
+ #define DRIVER_NAME(_name) NULL
#endif
-static usbh_class_driver_t const usbh_class_drivers[] =
-{
- #if CFG_TUH_CDC
+static usbh_class_driver_t const usbh_class_drivers[] = {
+ #if CFG_TUH_CDC
{
- DRIVER_NAME("CDC")
- .init = cdch_init,
- .open = cdch_open,
- .set_config = cdch_set_config,
- .xfer_cb = cdch_xfer_cb,
- .close = cdch_close
+ .name = DRIVER_NAME("CDC"),
+ .init = cdch_init,
+ .deinit = cdch_deinit,
+ .open = cdch_open,
+ .set_config = cdch_set_config,
+ .xfer_cb = cdch_xfer_cb,
+ .close = cdch_close
},
- #endif
+ #endif
- #if CFG_TUH_MSC
+ #if CFG_TUH_MSC
{
- DRIVER_NAME("MSC")
- .init = msch_init,
- .open = msch_open,
- .set_config = msch_set_config,
- .xfer_cb = msch_xfer_cb,
- .close = msch_close
+ .name = DRIVER_NAME("MSC"),
+ .init = msch_init,
+ .deinit = msch_deinit,
+ .open = msch_open,
+ .set_config = msch_set_config,
+ .xfer_cb = msch_xfer_cb,
+ .close = msch_close
},
- #endif
+ #endif
- #if CFG_TUH_HID
+ #if CFG_TUH_HID
{
- DRIVER_NAME("HID")
- .init = hidh_init,
- .open = hidh_open,
- .set_config = hidh_set_config,
- .xfer_cb = hidh_xfer_cb,
- .close = hidh_close
+ .name = DRIVER_NAME("HID"),
+ .init = hidh_init,
+ .deinit = hidh_deinit,
+ .open = hidh_open,
+ .set_config = hidh_set_config,
+ .xfer_cb = hidh_xfer_cb,
+ .close = hidh_close
},
- #endif
+ #endif
- #if CFG_TUH_HUB
+ #if CFG_TUH_HUB
{
- DRIVER_NAME("HUB")
- .init = hub_init,
- .open = hub_open,
- .set_config = hub_set_config,
- .xfer_cb = hub_xfer_cb,
- .close = hub_close
+ .name = DRIVER_NAME("HUB"),
+ .init = hub_init,
+ .deinit = hub_deinit,
+ .open = hub_open,
+ .set_config = hub_set_config,
+ .xfer_cb = hub_xfer_cb,
+ .close = hub_close
},
- #endif
+ #endif
- #if CFG_TUH_VENDOR
+ #if CFG_TUH_VENDOR
{
- DRIVER_NAME("VENDOR")
+ .name = DRIVER_NAME("VENDOR"),
.init = cush_init,
- .open = cush_open_subtask,
+ .deinit = cush_deinit,
+ .open = cush_open,
+ .set_config = cush_set_config,
.xfer_cb = cush_isr,
.close = cush_close
}
- #endif
+ #endif
};
-enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) };
+enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) };
+enum { CONFIG_NUM = 1 }; // default to use configuration 1
-enum { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer
+// Additional class drivers implemented by application
+tu_static usbh_class_driver_t const * _app_driver = NULL;
+tu_static uint8_t _app_driver_count = 0;
-enum { CONFIG_NUM = 1 }; // default to use configuration 1
+#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT)
+static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) {
+ usbh_class_driver_t const *driver = NULL;
+
+ if ( drv_id < _app_driver_count ) {
+ driver = &_app_driver[drv_id];
+ } else if ( drv_id < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0) {
+ driver = &usbh_class_drivers[drv_id - _app_driver_count];
+ }
+
+ return driver;
+}
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
@@ -224,8 +255,7 @@ static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE];
// Control transfers: since most controllers do not support multiple control transfers
// on multiple devices concurrently and control transfers are not used much except for
// enumeration, we will only execute control transfers one at a time.
-CFG_TUH_MEM_SECTION struct
-{
+CFG_TUH_MEM_SECTION struct {
CFG_TUH_MEM_ALIGN tusb_control_request_t request;
uint8_t* buffer;
tuh_xfer_cb_t complete_cb;
@@ -238,54 +268,45 @@ CFG_TUH_MEM_SECTION struct
//------------- Helper Function -------------//
-TU_ATTR_ALWAYS_INLINE
-static inline usbh_device_t* get_device(uint8_t dev_addr)
-{
+TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) {
TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL);
return &_usbh_devices[dev_addr-1];
}
static bool enum_new_device(hcd_event_t* event);
-static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port);
+static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port);
static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size);
static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
#if CFG_TUSB_OS == OPT_OS_NONE
// TODO rework time-related function later
-void osal_task_delay(uint32_t msec)
-{
+// weak and overridable
+TU_ATTR_WEAK void osal_task_delay(uint32_t msec) {
const uint32_t start = hcd_frame_number(_usbh_controller);
while ( ( hcd_frame_number(_usbh_controller) - start ) < msec ) {}
}
#endif
+TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event, bool in_isr) {
+ bool ret = osal_queue_send(_usbh_q, event, in_isr);
+ tuh_event_hook_cb(event->rhport, event->event_id, in_isr);
+ return ret;
+}
+
//--------------------------------------------------------------------+
-// PUBLIC API (Parameter Verification is required)
+// Device API
//--------------------------------------------------------------------+
-bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param)
-{
- if (hcd_configure)
- {
- return hcd_configure(rhport, cfg_id, cfg_param);
- }else
- {
- return false;
- }
-}
-
-bool tuh_mounted(uint8_t dev_addr)
-{
- usbh_device_t* dev = get_device(dev_addr);
+bool tuh_mounted(uint8_t dev_addr) {
+ usbh_device_t *dev = get_device(dev_addr);
TU_VERIFY(dev);
return dev->configured;
}
-bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid)
-{
+bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) {
*vid = *pid = 0;
- usbh_device_t const* dev = get_device(dev_addr);
+ usbh_device_t const *dev = get_device(dev_addr);
TU_VERIFY(dev && dev->addressed && dev->vid != 0);
*vid = dev->vid;
@@ -294,74 +315,136 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid)
return true;
}
-tusb_speed_t tuh_speed_get (uint8_t dev_addr)
-{
- usbh_device_t* dev = get_device(dev_addr);
+tusb_speed_t tuh_speed_get(uint8_t dev_addr) {
+ usbh_device_t *dev = get_device(dev_addr);
return (tusb_speed_t) (dev ? get_device(dev_addr)->speed : _dev0.speed);
}
-static void clear_device(usbh_device_t* dev)
-{
+bool tuh_rhport_is_active(uint8_t rhport) {
+ return _usbh_controller == rhport;
+}
+
+bool tuh_rhport_reset_bus(uint8_t rhport, bool active) {
+ TU_VERIFY(tuh_rhport_is_active(rhport));
+ if ( active ) {
+ hcd_port_reset(rhport);
+ } else {
+ hcd_port_reset_end(rhport);
+ }
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// PUBLIC API (Parameter Verification is required)
+//--------------------------------------------------------------------+
+
+bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param) {
+ return hcd_configure(rhport, cfg_id, cfg_param);
+}
+
+static void clear_device(usbh_device_t* dev) {
tu_memclr(dev, sizeof(usbh_device_t));
memset(dev->itf2drv, TUSB_INDEX_INVALID_8, sizeof(dev->itf2drv)); // invalid mapping
memset(dev->ep2drv , TUSB_INDEX_INVALID_8, sizeof(dev->ep2drv )); // invalid mapping
}
-bool tuh_inited(void)
-{
+bool tuh_inited(void) {
return _usbh_controller != TUSB_INDEX_INVALID_8;
}
-bool tuh_init(uint8_t controller_id)
-{
+bool tuh_init(uint8_t rhport) {
// skip if already initialized
- if ( tuh_inited() ) return true;
+ if (tuh_rhport_is_active(rhport)) return true;
+
+ TU_LOG_USBH("USBH init on controller %u\r\n", rhport);
- TU_LOG_USBH("USBH init on controller %u\r\n", controller_id);
- TU_LOG_INT(USBH_DEBUG, sizeof(usbh_device_t));
- TU_LOG_INT(USBH_DEBUG, sizeof(hcd_event_t));
- TU_LOG_INT(USBH_DEBUG, sizeof(_ctrl_xfer));
- TU_LOG_INT(USBH_DEBUG, sizeof(tuh_xfer_t));
- TU_LOG_INT(USBH_DEBUG, sizeof(tu_fifo_t));
- TU_LOG_INT(USBH_DEBUG, sizeof(tu_edpt_stream_t));
+ // Init host stack if not already
+ if (!tuh_inited()) {
+ TU_LOG_INT_USBH(sizeof(usbh_device_t));
+ TU_LOG_INT_USBH(sizeof(hcd_event_t));
+ TU_LOG_INT_USBH(sizeof(_ctrl_xfer));
+ TU_LOG_INT_USBH(sizeof(tuh_xfer_t));
+ TU_LOG_INT_USBH(sizeof(tu_fifo_t));
+ TU_LOG_INT_USBH(sizeof(tu_edpt_stream_t));
- // Event queue
- _usbh_q = osal_queue_create( &_usbh_qdef );
- TU_ASSERT(_usbh_q != NULL);
+ // Event queue
+ _usbh_q = osal_queue_create(&_usbh_qdef);
+ TU_ASSERT(_usbh_q != NULL);
#if OSAL_MUTEX_REQUIRED
- // Init mutex
- _usbh_mutex = osal_mutex_create(&_usbh_mutexdef);
- TU_ASSERT(_usbh_mutex);
+ // Init mutex
+ _usbh_mutex = osal_mutex_create(&_usbh_mutexdef);
+ TU_ASSERT(_usbh_mutex);
#endif
- // Device
- tu_memclr(&_dev0, sizeof(_dev0));
- tu_memclr(_usbh_devices, sizeof(_usbh_devices));
- tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer));
+ // Get application driver if available
+ if (usbh_app_driver_get_cb) {
+ _app_driver = usbh_app_driver_get_cb(&_app_driver_count);
+ }
- for(uint8_t i=0; i<TOTAL_DEVICES; i++)
- {
- clear_device(&_usbh_devices[i]);
- }
+ // Device
+ tu_memclr(&_dev0, sizeof(_dev0));
+ tu_memclr(_usbh_devices, sizeof(_usbh_devices));
+ tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer));
- // Class drivers
- for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
- {
- TU_LOG_USBH("%s init\r\n", usbh_class_drivers[drv_id].name);
- usbh_class_drivers[drv_id].init();
+ for (uint8_t i = 0; i < TOTAL_DEVICES; i++) {
+ clear_device(&_usbh_devices[i]);
+ }
+
+ // Class drivers
+ for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
+ usbh_class_driver_t const* driver = get_driver(drv_id);
+ if (driver) {
+ TU_LOG_USBH("%s init\r\n", driver->name);
+ driver->init();
+ }
+ }
}
- _usbh_controller = controller_id;;
+ // Init host controller
+ _usbh_controller = rhport;;
+ TU_ASSERT(hcd_init(rhport));
+ hcd_int_enable(rhport);
+
+ return true;
+}
+
+bool tuh_deinit(uint8_t rhport) {
+ if (!tuh_rhport_is_active(rhport)) return true;
+
+ // deinit host controller
+ hcd_int_disable(rhport);
+ hcd_deinit(rhport);
+ _usbh_controller = TUSB_INDEX_INVALID_8;
+
+ // "unplug" all devices on this rhport (hub_addr = 0, hub_port = 0)
+ process_removing_device(rhport, 0, 0);
+
+ // deinit host stack if no controller is active
+ if (!tuh_inited()) {
+ // Class drivers
+ for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
+ usbh_class_driver_t const* driver = get_driver(drv_id);
+ if (driver && driver->deinit) {
+ TU_LOG_USBH("%s deinit\r\n", driver->name);
+ driver->deinit();
+ }
+ }
+
+ osal_queue_delete(_usbh_q);
+ _usbh_q = NULL;
- TU_ASSERT(hcd_init(controller_id));
- hcd_int_enable(controller_id);
+ #if OSAL_MUTEX_REQUIRED
+ // TODO make sure there is no task waiting on this mutex
+ osal_mutex_delete(_usbh_mutex);
+ _usbh_mutex = NULL;
+ #endif
+ }
return true;
}
-bool tuh_task_event_ready(void)
-{
+bool tuh_task_event_ready(void) {
// Skip if stack is not initialized
if ( !tuh_inited() ) return false;
@@ -386,91 +469,79 @@ bool tuh_task_event_ready(void)
}
@endcode
*/
-void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
-{
+void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
(void) in_isr; // not implemented yet
// Skip if stack is not initialized
- if ( !tuh_inited() ) return;
+ if (!tuh_inited()) return;
// Loop until there is no more events in the queue
- while (1)
- {
+ while (1) {
hcd_event_t event;
- if ( !osal_queue_receive(_usbh_q, &event, timeout_ms) ) return;
+ if (!osal_queue_receive(_usbh_q, &event, timeout_ms)) return;
- switch (event.event_id)
- {
+ switch (event.event_id) {
case HCD_EVENT_DEVICE_ATTACH:
- // due to the shared _usbh_ctrl_buf, we must complete enumerating
- // one device before enumerating another one.
- if ( _dev0.enumerating )
- {
+ // due to the shared _usbh_ctrl_buf, we must complete enumerating one device before enumerating another one.
+ // TODO better to have an separated queue for newly attached devices
+ if (_dev0.enumerating) {
TU_LOG_USBH("[%u:] USBH Defer Attach until current enumeration complete\r\n", event.rhport);
- osal_queue_send(_usbh_q, &event, in_isr);
- }else
- {
+
+ bool is_empty = osal_queue_empty(_usbh_q);
+ queue_event(&event, in_isr);
+
+ if (is_empty) {
+ // Exit if this is the only event in the queue, otherwise we may loop forever
+ return;
+ }
+ } else {
TU_LOG_USBH("[%u:] USBH DEVICE ATTACH\r\n", event.rhport);
_dev0.enumerating = 1;
enum_new_device(&event);
}
- break;
+ break;
case HCD_EVENT_DEVICE_REMOVE:
TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port);
- process_device_unplugged(event.rhport, event.connection.hub_addr, event.connection.hub_port);
+ process_removing_device(event.rhport, event.connection.hub_addr, event.connection.hub_port);
#if CFG_TUH_HUB
// TODO remove
- if ( event.connection.hub_addr != 0)
- {
+ if (event.connection.hub_addr != 0 && event.connection.hub_port != 0) {
// done with hub, waiting for next data on status pipe
- (void) hub_edpt_status_xfer( event.connection.hub_addr );
+ (void) hub_edpt_status_xfer(event.connection.hub_addr);
}
#endif
- break;
+ break;
- case HCD_EVENT_XFER_COMPLETE:
- {
+ case HCD_EVENT_XFER_COMPLETE: {
uint8_t const ep_addr = event.xfer_complete.ep_addr;
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const ep_dir = tu_edpt_dir(ep_addr);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const ep_dir = (uint8_t) tu_edpt_dir(ep_addr);
- TU_LOG_USBH("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
+ TU_LOG_USBH("on EP %02X with %u bytes: %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len, tu_str_xfer_result[event.xfer_complete.result]);
- if (event.dev_addr == 0)
- {
+ if (event.dev_addr == 0) {
// device 0 only has control endpoint
- TU_ASSERT(epnum == 0, );
+ TU_ASSERT(epnum == 0,);
usbh_control_xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
- }
- else
- {
+ } else {
usbh_device_t* dev = get_device(event.dev_addr);
- TU_ASSERT(dev, );
+ TU_VERIFY(dev && dev->connected,);
- dev->ep_status[epnum][ep_dir].busy = 0;
+ dev->ep_status[epnum][ep_dir].busy = 0;
dev->ep_status[epnum][ep_dir].claimed = 0;
- if ( 0 == epnum )
- {
+ if (0 == epnum) {
usbh_control_xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
- }else
- {
- uint8_t drv_id = dev->ep2drv[epnum][ep_dir];
- if(drv_id < USBH_CLASS_DRIVER_COUNT)
- {
- TU_LOG_USBH("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
- usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
- }
- else
- {
-#if CFG_TUH_API_EDPT_XFER
- tuh_xfer_cb_t complete_cb = dev->ep_callback[epnum][ep_dir].complete_cb;
- if ( complete_cb )
- {
- tuh_xfer_t xfer =
- {
+ } else {
+ // Prefer application callback over built-in one if available. This occurs when tuh_edpt_xfer() is used
+ // with enabled driver e.g HID endpoint
+ #if CFG_TUH_API_EDPT_XFER
+ tuh_xfer_cb_t const complete_cb = dev->ep_callback[epnum][ep_dir].complete_cb;
+ if ( complete_cb ) {
+ // re-construct xfer info
+ tuh_xfer_t xfer = {
.daddr = event.dev_addr,
.ep_addr = ep_addr,
.result = event.xfer_complete.result,
@@ -479,27 +550,33 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
.buffer = NULL, // not available
.complete_cb = complete_cb,
.user_data = dev->ep_callback[epnum][ep_dir].user_data
- };
-
- complete_cb(&xfer);
- }else
-#endif
- {
+ };
+ complete_cb(&xfer);
+ }else
+ #endif
+ {
+ uint8_t drv_id = dev->ep2drv[epnum][ep_dir];
+ usbh_class_driver_t const* driver = get_driver(drv_id);
+ if (driver) {
+ TU_LOG_USBH("%s xfer callback\r\n", driver->name);
+ driver->xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result,
+ event.xfer_complete.len);
+ } else {
// no driver/callback responsible for this transfer
- TU_ASSERT(false, );
+ TU_ASSERT(false,);
}
-
}
}
}
+ break;
}
- break;
case USBH_EVENT_FUNC_CALL:
- if ( event.func_call.func ) event.func_call.func(event.func_call.param);
- break;
+ if (event.func_call.func) event.func_call.func(event.func_call.param);
+ break;
- default: break;
+ default:
+ break;
}
#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO
@@ -513,28 +590,31 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
// Control transfer
//--------------------------------------------------------------------+
-static void _control_blocking_complete_cb(tuh_xfer_t* xfer)
-{
+static void _control_blocking_complete_cb(tuh_xfer_t* xfer) {
// update result
*((xfer_result_t*) xfer->user_data) = xfer->result;
}
// TODO timeout_ms is not supported yet
-bool tuh_control_xfer (tuh_xfer_t* xfer)
-{
+bool tuh_control_xfer (tuh_xfer_t* xfer) {
// EP0 with setup packet
TU_VERIFY(xfer->ep_addr == 0 && xfer->setup);
- // pre-check to help reducing mutex lock
- TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
-
+ // Check if device is still connected (enumerating for dev0)
uint8_t const daddr = xfer->daddr;
+ if ( daddr == 0 ) {
+ if (!_dev0.enumerating) return false;
+ } else {
+ usbh_device_t const* dev = get_device(daddr);
+ if (dev && dev->connected == 0) return false;
+ }
+ // pre-check to help reducing mutex lock
+ TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
(void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
- if (is_idle)
- {
+ if (is_idle) {
_ctrl_xfer.stage = CONTROL_STAGE_SETUP;
_ctrl_xfer.daddr = daddr;
_ctrl_xfer.actual_len = 0;
@@ -553,14 +633,11 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr,
(xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ?
tu_str_std_request[xfer->setup->bRequest] : "Class Request");
- TU_LOG_PTR(USBH_DEBUG, xfer->setup);
- TU_LOG_USBH("\r\n");
+ TU_LOG_BUF_USBH(xfer->setup, 8);
- if (xfer->complete_cb)
- {
+ if (xfer->complete_cb) {
TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t const*) &_ctrl_xfer.request) );
- }else
- {
+ }else {
// blocking if complete callback is not provided
// change callback to internal blocking, and result as user argument
volatile xfer_result_t result = XFER_RESULT_INVALID;
@@ -571,19 +648,19 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) );
- while (result == XFER_RESULT_INVALID)
- {
+ while (result == XFER_RESULT_INVALID) {
// Note: this can be called within an callback ie. part of tuh_task()
// therefore event with RTOS tuh_task() still need to be invoked
- if (tuh_task_event_ready())
- {
+ if (tuh_task_event_ready()) {
tuh_task();
}
-
// TODO probably some timeout to prevent hanged
}
- // update transfer result
+ // update transfer result, user_data is expected to point to xfer_result_t
+ if (xfer->user_data != 0) {
+ *((xfer_result_t*) xfer->user_data) = result;
+ }
xfer->result = result;
xfer->actual_len = _ctrl_xfer.actual_len;
}
@@ -591,21 +668,18 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
return true;
}
-TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage)
-{
+TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) {
(void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
_ctrl_xfer.stage = stage;
(void) osal_mutex_unlock(_usbh_mutex);
}
-static void _xfer_complete(uint8_t daddr, xfer_result_t result)
-{
+static void _control_xfer_complete(uint8_t daddr, xfer_result_t result) {
TU_LOG_USBH("\r\n");
// duplicate xfer since user can execute control transfer within callback
tusb_control_request_t const request = _ctrl_xfer.request;
- tuh_xfer_t xfer_temp =
- {
+ tuh_xfer_t xfer_temp = {
.daddr = daddr,
.ep_addr = 0,
.result = result,
@@ -618,60 +692,61 @@ static void _xfer_complete(uint8_t daddr, xfer_result_t result)
_set_control_xfer_stage(CONTROL_STAGE_IDLE);
- if (xfer_temp.complete_cb)
- {
+ if (xfer_temp.complete_cb) {
xfer_temp.complete_cb(&xfer_temp);
}
}
-static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
+static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) ep_addr;
- const uint8_t rhport = usbh_get_rhport(dev_addr);
+ const uint8_t rhport = usbh_get_rhport(daddr);
tusb_control_request_t const * request = &_ctrl_xfer.request;
- if (XFER_RESULT_SUCCESS != result)
- {
- TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes);
- #if CFG_TUSB_DEBUG == 1
- TU_LOG1_PTR(request);
- TU_LOG1("\r\n");
- #endif
+ if (XFER_RESULT_SUCCESS != result) {
+ TU_LOG_USBH("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, daddr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes);
+ TU_LOG_BUF_USBH(request, 8);
// terminate transfer if any stage failed
- _xfer_complete(dev_addr, result);
- }else
- {
- switch(_ctrl_xfer.stage)
- {
+ _control_xfer_complete(daddr, result);
+ }else {
+ switch(_ctrl_xfer.stage) {
case CONTROL_STAGE_SETUP:
- if (request->wLength)
- {
+ if (request->wLength) {
// DATA stage: initial data toggle is always 1
_set_control_xfer_stage(CONTROL_STAGE_DATA);
- TU_ASSERT( hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) );
+ TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) );
return true;
}
TU_ATTR_FALLTHROUGH;
case CONTROL_STAGE_DATA:
- if (request->wLength)
- {
- TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, dev_addr);
- TU_LOG_MEM(USBH_DEBUG, _ctrl_xfer.buffer, xferred_bytes, 2);
+ if (request->wLength) {
+ TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr);
+ TU_LOG_MEM_USBH(_ctrl_xfer.buffer, xferred_bytes, 2);
}
_ctrl_xfer.actual_len = (uint16_t) xferred_bytes;
// ACK stage: toggle is always 1
_set_control_xfer_stage(CONTROL_STAGE_ACK);
- TU_ASSERT( hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0) );
- break;
+ TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction), NULL, 0) );
+ break;
- case CONTROL_STAGE_ACK:
- _xfer_complete(dev_addr, result);
- break;
+ case CONTROL_STAGE_ACK: {
+ // Abort all pending transfers if SET_CONFIGURATION request
+ // NOTE: should we force closing all non-control endpoints in the future?
+ if (request->bRequest == TUSB_REQ_SET_CONFIGURATION && request->bmRequestType == 0x00) {
+ for(uint8_t epnum=1; epnum<CFG_TUH_ENDPOINT_MAX; epnum++) {
+ for(uint8_t dir=0; dir<2; dir++) {
+ tuh_edpt_abort_xfer(daddr, tu_edpt_addr(epnum, dir));
+ }
+ }
+ }
+
+ _control_xfer_complete(daddr, result);
+ break;
+ }
default: return false;
}
@@ -684,17 +759,15 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result
//
//--------------------------------------------------------------------+
-bool tuh_edpt_xfer(tuh_xfer_t* xfer)
-{
- uint8_t const daddr = xfer->daddr;
+bool tuh_edpt_xfer(tuh_xfer_t* xfer) {
+ uint8_t const daddr = xfer->daddr;
uint8_t const ep_addr = xfer->ep_addr;
TU_VERIFY(daddr && ep_addr);
-
TU_VERIFY(usbh_edpt_claim(daddr, ep_addr));
- if ( !usbh_edpt_xfer_with_callback(daddr, ep_addr, xfer->buffer, (uint16_t) xfer->buflen, xfer->complete_cb, xfer->user_data) )
- {
+ if (!usbh_edpt_xfer_with_callback(daddr, ep_addr, xfer->buffer, (uint16_t) xfer->buflen,
+ xfer->complete_cb, xfer->user_data)) {
usbh_edpt_release(daddr, ep_addr);
return false;
}
@@ -702,69 +775,102 @@ bool tuh_edpt_xfer(tuh_xfer_t* xfer)
return true;
}
+bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) {
+ usbh_device_t* dev = get_device(daddr);
+ TU_VERIFY(dev);
+
+ TU_LOG_USBH("[%u] Aborted transfer on EP %02X\r\n", daddr, ep_addr);
+
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ if ( epnum == 0 ) {
+ // control transfer: only 1 control at a time, check if we are aborting the current one
+ TU_VERIFY(daddr == _ctrl_xfer.daddr && _ctrl_xfer.stage != CONTROL_STAGE_IDLE);
+ TU_VERIFY(hcd_edpt_abort_xfer(dev->rhport, daddr, ep_addr));
+ // reset control transfer state to idle
+ _set_control_xfer_stage(CONTROL_STAGE_IDLE);
+ } else {
+ // non-control skip if not busy
+ TU_VERIFY(dev->ep_status[epnum][dir].busy);
+ TU_VERIFY(hcd_edpt_abort_xfer(dev->rhport, daddr, ep_addr));
+ // mark as ready and release endpoint if transfer is aborted
+ dev->ep_status[epnum][dir].busy = false;
+ tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex);
+ }
+
+ return true;
+}
+
//--------------------------------------------------------------------+
// USBH API For Class Driver
//--------------------------------------------------------------------+
-uint8_t usbh_get_rhport(uint8_t dev_addr)
-{
- usbh_device_t* dev = get_device(dev_addr);
+uint8_t usbh_get_rhport(uint8_t dev_addr) {
+ usbh_device_t *dev = get_device(dev_addr);
return dev ? dev->rhport : _dev0.rhport;
}
-uint8_t* usbh_get_enum_buf(void)
-{
+uint8_t *usbh_get_enum_buf(void) {
return _usbh_ctrl_buf;
}
-void usbh_int_set(bool enabled)
-{
- // TODO all host controller if multiple is used
- if (enabled)
- {
+void usbh_int_set(bool enabled) {
+ // TODO all host controller if multiple are used since they shared the same event queue
+ if (enabled) {
hcd_int_enable(_usbh_controller);
- }else
- {
+ } else {
hcd_int_disable(_usbh_controller);
}
}
+void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr) {
+ hcd_event_t event = { 0 };
+ event.event_id = USBH_EVENT_FUNC_CALL;
+ event.func_call.func = func;
+ event.func_call.param = param;
+
+ queue_event(&event, in_isr);
+}
+
//--------------------------------------------------------------------+
// Endpoint API
//--------------------------------------------------------------------+
-// TODO has some duplication code with device, refactor later
-bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
-{
+// Claim an endpoint for transfer
+bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) {
+ // Note: addr0 only use tuh_control_xfer
usbh_device_t* dev = get_device(dev_addr);
-
- // addr0 only use tuh_control_xfer
- TU_ASSERT(dev);
+ TU_ASSERT(dev && dev->connected);
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
- return tu_edpt_claim(&dev->ep_status[epnum][dir], _usbh_mutex);
+ TU_VERIFY(tu_edpt_claim(&dev->ep_status[epnum][dir], _usbh_mutex));
+ TU_LOG_USBH("[%u] Claimed EP 0x%02x\r\n", dev_addr, ep_addr);
+
+ return true;
}
-// TODO has some duplication code with device, refactor later
-bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
-{
+// Release an claimed endpoint due to failed transfer attempt
+bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) {
+ // Note: addr0 only use tuh_control_xfer
usbh_device_t* dev = get_device(dev_addr);
-
- // addr0 only use tuh_control_xfer
- TU_ASSERT(dev);
+ TU_VERIFY(dev && dev->connected);
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
- return tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex);
+ TU_VERIFY(tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex));
+ TU_LOG_USBH("[%u] Released EP 0x%02x\r\n", dev_addr, ep_addr);
+
+ return true;
}
-// TODO has some duplication code with device, refactor later
-bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+// Submit an transfer
+// TODO call usbh_edpt_release if failed
+bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
(void) complete_cb;
(void) user_data;
@@ -772,10 +878,10 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b
TU_VERIFY(dev);
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir];
- TU_LOG_USBH(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
+ TU_LOG_USBH(" Queue EP %02X with %u bytes ... \r\n", ep_addr, total_bytes);
// Attempt to transfer on a busy endpoint, sound like an race condition !
TU_ASSERT(ep_state->busy == 0);
@@ -789,27 +895,22 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b
dev->ep_callback[epnum][dir].user_data = user_data;
#endif
- if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) )
- {
+ if (hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes)) {
TU_LOG_USBH("OK\r\n");
return true;
- }else
- {
+ } else {
// HCD error, mark endpoint as ready to allow next transfer
- ep_state->busy = 0;
+ ep_state->busy = 0;
ep_state->claimed = 0;
TU_LOG1("Failed\r\n");
- TU_BREAKPOINT();
+// TU_BREAKPOINT();
return false;
}
}
-static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
-{
+static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) {
TU_LOG_USBH("[%u:%u] Open EP0 with Size = %u\r\n", usbh_get_rhport(dev_addr), dev_addr, max_packet_size);
-
- tusb_desc_endpoint_t ep0_desc =
- {
+ tusb_desc_endpoint_t ep0_desc = {
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = 0,
@@ -821,21 +922,18 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc);
}
-bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
-{
- TU_ASSERT( tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr)) );
-
+bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const* desc_ep) {
+ TU_ASSERT(tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr)));
return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, desc_ep);
}
-bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
+bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) {
usbh_device_t* dev = get_device(dev_addr);
TU_VERIFY(dev);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
return dev->ep_status[epnum][dir].busy;
}
@@ -843,33 +941,38 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
// HCD Event Handler
//--------------------------------------------------------------------+
-void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info)
-{
+void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) {
usbh_device_t const* dev = get_device(dev_addr);
-
- if (dev)
- {
- devtree_info->rhport = dev->rhport;
+ if (dev) {
+ devtree_info->rhport = dev->rhport;
devtree_info->hub_addr = dev->hub_addr;
devtree_info->hub_port = dev->hub_port;
- devtree_info->speed = dev->speed;
- }else
- {
- devtree_info->rhport = _dev0.rhport;
+ devtree_info->speed = dev->speed;
+ } else {
+ devtree_info->rhport = _dev0.rhport;
devtree_info->hub_addr = _dev0.hub_addr;
devtree_info->hub_port = _dev0.hub_port;
- devtree_info->speed = _dev0.speed;
+ devtree_info->speed = _dev0.speed;
}
}
-TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr)
-{
- switch (event->event_id)
- {
- default:
- osal_queue_send(_usbh_q, event, in_isr);
- break;
+TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) {
+ switch (event->event_id) {
+ case HCD_EVENT_DEVICE_REMOVE:
+ // FIXME device remove from a hub need an HCD API for hcd to free up endpoint
+ // mark device as removing to prevent further xfer before the event is processed in usbh task
+
+ // Check if dev0 is removed
+ if ((event->rhport == _dev0.rhport) && (event->connection.hub_addr == _dev0.hub_addr) &&
+ (event->connection.hub_port == _dev0.hub_port)) {
+ _dev0.enumerating = 0;
+ }
+ break;
+
+ default: break;
}
+
+ queue_event(event, in_isr);
}
//--------------------------------------------------------------------+
@@ -877,14 +980,11 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr)
//--------------------------------------------------------------------+
// generic helper to get a descriptor
-// if blocking, user_data could be pointed to xfer_result
+// if blocking, user_data is pointed to xfer_result
static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
.recipient = TUSB_REQ_RCPT_DEVICE,
.type = TUSB_REQ_TYPE_STANDARD,
.direction = TUSB_DIR_IN
@@ -894,9 +994,7 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t
.wIndex = tu_htole16(language_id),
.wLength = tu_htole16(len)
};
-
- tuh_xfer_t xfer =
- {
+ tuh_xfer_t xfer = {
.daddr = daddr,
.ep_addr = 0,
.setup = &request,
@@ -905,41 +1003,29 @@ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t
.user_data = user_data
};
- bool const ret = tuh_control_xfer(&xfer);
-
- // if blocking, user_data could be pointed to xfer_result
- if ( !complete_cb && user_data )
- {
- *((xfer_result_t*) user_data) = xfer.result;
- }
-
- return ret;
+ return tuh_control_xfer(&xfer);
}
bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return _get_descriptor(daddr, type, index, 0x0000, buffer, len, complete_cb, user_data);
}
bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
len = tu_min16(len, sizeof(tusb_desc_device_t));
return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb, user_data);
}
bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb, user_data);
}
//------------- String Descriptor -------------//
bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_data);
}
@@ -954,8 +1040,7 @@ bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id,
// Get product string descriptor
bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
usbh_device_t const* dev = get_device(daddr);
TU_VERIFY(dev && dev->i_product);
return tuh_descriptor_get_string(daddr, dev->i_product, language_id, buffer, len, complete_cb, user_data);
@@ -963,132 +1048,90 @@ bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void
// Get serial string descriptor
bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
usbh_device_t const* dev = get_device(daddr);
TU_VERIFY(dev && dev->i_serial);
return tuh_descriptor_get_string(daddr, dev->i_serial, language_id, buffer, len, complete_cb, user_data);
}
// Get HID report descriptor
-// if blocking, user_data could be pointed to xfer_result
+// if blocking, user_data is pointed to xfer_result
bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
TU_LOG_USBH("HID Get Report Descriptor\r\n");
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_IN
- },
- .bRequest = TUSB_REQ_GET_DESCRIPTOR,
- .wValue = tu_htole16(TU_U16(desc_type, index)),
- .wIndex = tu_htole16((uint16_t) itf_num),
- .wLength = len
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_IN
+ },
+ .bRequest = TUSB_REQ_GET_DESCRIPTOR,
+ .wValue = tu_htole16(TU_U16(desc_type, index)),
+ .wIndex = tu_htole16((uint16_t) itf_num),
+ .wLength = len
};
-
- tuh_xfer_t xfer =
- {
- .daddr = daddr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = buffer,
- .complete_cb = complete_cb,
- .user_data = user_data
+ tuh_xfer_t xfer = {
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = buffer,
+ .complete_cb = complete_cb,
+ .user_data = user_data
};
- bool const ret = tuh_control_xfer(&xfer);
-
- // if blocking, user_data could be pointed to xfer_result
- if ( !complete_cb && user_data )
- {
- *((xfer_result_t*) user_data) = xfer.result;
- }
-
- return ret;
+ return tuh_control_xfer(&xfer);
}
bool tuh_configuration_set(uint8_t daddr, uint8_t config_num,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
TU_LOG_USBH("Set Configuration = %d\r\n", config_num);
-
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_DEVICE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = TUSB_REQ_SET_CONFIGURATION,
- .wValue = tu_htole16(config_num),
- .wIndex = 0,
- .wLength = 0
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = TUSB_REQ_SET_CONFIGURATION,
+ .wValue = tu_htole16(config_num),
+ .wIndex = 0,
+ .wLength = 0
};
-
- tuh_xfer_t xfer =
- {
- .daddr = daddr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = NULL,
- .complete_cb = complete_cb,
- .user_data = user_data
+ tuh_xfer_t xfer = {
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = NULL,
+ .complete_cb = complete_cb,
+ .user_data = user_data
};
- bool ret = tuh_control_xfer(&xfer);
-
- // if blocking, user_data could be pointed to xfer_result
- if ( !complete_cb && user_data )
- {
- *((xfer_result_t*) user_data) = xfer.result;
- }
-
- return ret;
+ return tuh_control_xfer(&xfer);
}
bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
TU_LOG_USBH("Set Interface %u Alternate %u\r\n", itf_num, itf_alt);
-
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_DEVICE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = TUSB_REQ_SET_INTERFACE,
- .wValue = tu_htole16(itf_alt),
- .wIndex = tu_htole16(itf_num),
- .wLength = 0
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = TUSB_REQ_SET_INTERFACE,
+ .wValue = tu_htole16(itf_alt),
+ .wIndex = tu_htole16(itf_num),
+ .wLength = 0
};
-
- tuh_xfer_t xfer =
- {
- .daddr = daddr,
- .ep_addr = 0,
- .setup = &request,
- .buffer = NULL,
- .complete_cb = complete_cb,
- .user_data = user_data
+ tuh_xfer_t xfer = {
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = NULL,
+ .complete_cb = complete_cb,
+ .user_data = user_data
};
- bool ret = tuh_control_xfer(&xfer);
-
- // if blocking, user_data could be pointed to xfer_result
- if ( !complete_cb && user_data )
- {
- *((xfer_result_t*) user_data) = xfer.result;
- }
-
- return ret;
+ return tuh_control_xfer(&xfer);
}
//--------------------------------------------------------------------+
@@ -1100,99 +1143,131 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt,
TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \
return (uint8_t) result
-uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len);
}
-uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len);
}
-uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len);
}
-uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len);
}
-uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len);
}
-uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len);
}
-uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len);
}
-uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len);
}
//--------------------------------------------------------------------+
-//
+// Detaching
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE
-static inline bool is_hub_addr(uint8_t daddr)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) {
return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX);
}
+//static void mark_removing_device_isr(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) {
+// for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) {
+// usbh_device_t *dev = &_usbh_devices[dev_id];
+// uint8_t const daddr = dev_id + 1;
+//
+// // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub
+// if (dev->rhport == rhport && dev->connected &&
+// (hub_addr == 0 || dev->hub_addr == hub_addr) &&
+// (hub_port == 0 || dev->hub_port == hub_port)) {
+// if (is_hub_addr(daddr)) {
+// // If the device itself is a usb hub, mark all downstream devices.
+// // FIXME recursive calls
+// mark_removing_device_isr(rhport, daddr, 0);
+// }
+//
+// dev->removing = 1;
+// }
+// }
+//}
+
// a device unplugged from rhport:hub_addr:hub_port
-static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port)
-{
+static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) {
//------------- find the all devices (star-network) under port that is unplugged -------------//
// TODO mark as disconnected in ISR, also handle dev0
- for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ )
- {
- usbh_device_t* dev = &_usbh_devices[dev_id];
- uint8_t const dev_addr = dev_id+1;
+ uint32_t removing_hubs = 0;
+ do {
+ for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) {
+ usbh_device_t* dev = &_usbh_devices[dev_id];
+ uint8_t const daddr = dev_id + 1;
- // TODO Hub multiple level
- if (dev->rhport == rhport &&
- (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr = 0 means roothub
- (hub_port == 0 || dev->hub_port == hub_port) && // hub_port = 0 means all devices of downstream hub
- dev->connected)
- {
- TU_LOG_USBH(" Address = %u\r\n", dev_addr);
+ // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub
+ if (dev->rhport == rhport && dev->connected &&
+ (hub_addr == 0 || dev->hub_addr == hub_addr) &&
+ (hub_port == 0 || dev->hub_port == hub_port)) {
+ TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr);
- if (is_hub_addr(dev_addr))
- {
- TU_LOG(USBH_DEBUG, "HUB address = %u is unmounted\r\n", dev_addr);
- // If the device itself is a usb hub, unplug downstream devices.
- // FIXME un-roll recursive calls to prevent potential stack overflow
- process_device_unplugged(rhport, dev_addr, 0);
- }else
- {
- // Invoke callback before closing driver
- if (tuh_umount_cb) tuh_umount_cb(dev_addr);
- }
+ if (is_hub_addr(daddr)) {
+ TU_LOG_USBH(" is a HUB device %u\r\n", daddr);
+ removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX);
+ } else {
+ // Invoke callback before closing driver (maybe call it later ?)
+ if (tuh_umount_cb) tuh_umount_cb(daddr);
+ }
- // Close class driver
- for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
- {
- TU_LOG_USBH("%s close\r\n", usbh_class_drivers[drv_id].name);
- usbh_class_drivers[drv_id].close(dev_addr);
+ // Close class driver
+ for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
+ usbh_class_driver_t const* driver = get_driver(drv_id);
+ if (driver) driver->close(daddr);
+ }
+
+ hcd_device_close(rhport, daddr);
+ clear_device(dev);
+
+ // abort on-going control xfer on this device if any
+ if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE);
}
+ }
- hcd_device_close(rhport, dev_addr);
- clear_device(dev);
- // abort on-going control xfer if any
- if (_ctrl_xfer.daddr == dev_addr) _set_control_xfer_stage(CONTROL_STAGE_IDLE);
+ // if removing a hub, we need to remove its downstream devices
+ #if CFG_TUH_HUB
+ if (removing_hubs == 0) break;
+
+ // find a marked hub to process
+ for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) {
+ if (tu_bit_test(removing_hubs, h_id)) {
+ removing_hubs &= ~TU_BIT(h_id);
+
+ // update hub_addr and hub_port for next loop
+ hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX;
+ hub_port = 0;
+ break;
+ }
}
- }
+ #else
+ (void) removing_hubs;
+ break;
+ #endif
+ } while(1);
}
//--------------------------------------------------------------------+
@@ -1204,6 +1279,12 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h
//--------------------------------------------------------------------+
enum {
+ ENUM_RESET_DELAY = 50, // USB specs: 10 to 50ms
+ ENUM_CONTACT_DEBOUNCING_DELAY = 450, // when plug/unplug a device, physical connection can be bouncing and may
+ // generate a series of attach/detach event. This delay wait for stable connection
+};
+
+enum {
ENUM_IDLE,
ENUM_RESET_1, // 1st reset when attached
//ENUM_HUB_GET_STATUS_1,
@@ -1226,8 +1307,7 @@ static bool _parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configu
static void enum_full_complete(void);
// process device enumeration
-static void process_enumeration(tuh_xfer_t* xfer)
-{
+static void process_enumeration(tuh_xfer_t* xfer) {
// Retry a few times with transfers in enumeration since device can be unstable when starting up
enum {
ATTEMPT_COUNT_MAX = 3,
@@ -1235,18 +1315,20 @@ static void process_enumeration(tuh_xfer_t* xfer)
};
static uint8_t failed_count = 0;
- if (XFER_RESULT_SUCCESS != xfer->result)
- {
+ if (XFER_RESULT_SUCCESS != xfer->result) {
// retry if not reaching max attempt
- if ( failed_count < ATTEMPT_COUNT_MAX )
- {
+ bool retry = _dev0.enumerating && (failed_count < ATTEMPT_COUNT_MAX);
+ if ( retry ) {
failed_count++;
osal_task_delay(ATTEMPT_DELAY_MS); // delay a bit
- TU_ASSERT(tuh_control_xfer(xfer), );
- }else
- {
+ TU_LOG1("Enumeration attempt %u\r\n", failed_count);
+ retry = tuh_control_xfer(xfer);
+ }
+
+ if (!retry) {
enum_full_complete();
}
+
return;
}
failed_count = 0;
@@ -1254,303 +1336,288 @@ static void process_enumeration(tuh_xfer_t* xfer)
uint8_t const daddr = xfer->daddr;
uintptr_t const state = xfer->user_data;
- switch(state)
- {
-#if CFG_TUH_HUB
+ switch (state) {
+ #if CFG_TUH_HUB
//case ENUM_HUB_GET_STATUS_1: break;
- case ENUM_HUB_CLEAR_RESET_1:
- {
+ case ENUM_HUB_CLEAR_RESET_1: {
hub_port_status_response_t port_status;
memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t));
- if ( !port_status.status.connection )
- {
+ if (!port_status.status.connection) {
// device unplugged while delaying, nothing else to do
enum_full_complete();
return;
}
_dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH :
- (port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL;
+ (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL;
// Acknowledge Port Reset Change
- if (port_status.change.reset)
- {
- hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_ADDR0_DEVICE_DESC);
+ if (port_status.change.reset) {
+ hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port,
+ process_enumeration, ENUM_ADDR0_DEVICE_DESC);
}
+ break;
}
- break;
case ENUM_HUB_GET_STATUS_2:
- osal_task_delay(RESET_DELAY);
- TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2), );
- break;
+ osal_task_delay(ENUM_RESET_DELAY);
+ TU_ASSERT(hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf,
+ process_enumeration, ENUM_HUB_CLEAR_RESET_2),);
+ break;
- case ENUM_HUB_CLEAR_RESET_2:
- {
+ case ENUM_HUB_CLEAR_RESET_2: {
hub_port_status_response_t port_status;
memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t));
// Acknowledge Port Reset Change if Reset Successful
- if (port_status.change.reset)
- {
- TU_ASSERT( hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_SET_ADDR), );
+ if (port_status.change.reset) {
+ TU_ASSERT(hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port,
+ process_enumeration, ENUM_SET_ADDR),);
}
+ break;
}
- break;
-#endif
+ #endif
- case ENUM_ADDR0_DEVICE_DESC:
- {
+ case ENUM_ADDR0_DEVICE_DESC: {
// TODO probably doesn't need to open/close each enumeration
uint8_t const addr0 = 0;
- TU_ASSERT( usbh_edpt_control_open(addr0, 8), );
+ TU_ASSERT(usbh_edpt_control_open(addr0, 8),);
// Get first 8 bytes of device descriptor for Control Endpoint size
TU_LOG_USBH("Get 8 byte of Device Descriptor\r\n");
- TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, process_enumeration, ENUM_SET_ADDR), );
+ TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8,
+ process_enumeration, ENUM_SET_ADDR),);
+ break;
}
- break;
#if 0
- case ENUM_RESET_2:
- // TODO not used by now, but may be needed for some devices !?
- // Reset device again before Set Address
- TU_LOG_USBH("Port reset2 \r\n");
- if (_dev0.hub_addr == 0)
- {
- // connected directly to roothub
- hcd_port_reset( _dev0.rhport );
- osal_task_delay(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
- // sof of controller may not running while resetting
- hcd_port_reset_end(_dev0.rhport);
- // TODO: fall through to SET ADDRESS, refactor later
- }
- #if CFG_TUH_HUB
- else
- {
- // after RESET_DELAY the hub_port_reset() already complete
- TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_HUB_GET_STATUS_2), );
- break;
- }
- #endif
- TU_ATTR_FALLTHROUGH;
+ case ENUM_RESET_2:
+ // TODO not used by now, but may be needed for some devices !?
+ // Reset device again before Set Address
+ TU_LOG_USBH("Port reset2 \r\n");
+ if (_dev0.hub_addr == 0) {
+ // connected directly to roothub
+ hcd_port_reset( _dev0.rhport );
+ osal_task_delay(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
+ // sof of controller may not running while resetting
+ hcd_port_reset_end(_dev0.rhport);
+ // TODO: fall through to SET ADDRESS, refactor later
+ }
+#if CFG_TUH_HUB
+ else {
+ // after RESET_DELAY the hub_port_reset() already complete
+ TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port,
+ process_enumeration, ENUM_HUB_GET_STATUS_2), );
+ break;
+ }
+#endif
+ TU_ATTR_FALLTHROUGH;
#endif
case ENUM_SET_ADDR:
enum_request_set_addr();
- break;
+ break;
- case ENUM_GET_DEVICE_DESC:
- {
+ case ENUM_GET_DEVICE_DESC: {
uint8_t const new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue);
usbh_device_t* new_dev = get_device(new_addr);
- TU_ASSERT(new_dev, );
+ TU_ASSERT(new_dev,);
new_dev->addressed = 1;
// Close device 0
hcd_device_close(_dev0.rhport, 0);
// open control pipe for new address
- TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size), );
+ TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),);
// Get full device descriptor
TU_LOG_USBH("Get Device Descriptor\r\n");
- TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC), );
+ TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t),
+ process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC),);
+ break;
}
- break;
- case ENUM_GET_9BYTE_CONFIG_DESC:
- {
- tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf;
+ case ENUM_GET_9BYTE_CONFIG_DESC: {
+ tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf;
usbh_device_t* dev = get_device(daddr);
- TU_ASSERT(dev, );
+ TU_ASSERT(dev,);
- dev->vid = desc_device->idVendor;
- dev->pid = desc_device->idProduct;
+ dev->vid = desc_device->idVendor;
+ dev->pid = desc_device->idProduct;
dev->i_manufacturer = desc_device->iManufacturer;
- dev->i_product = desc_device->iProduct;
- dev->i_serial = desc_device->iSerialNumber;
+ dev->i_product = desc_device->iProduct;
+ dev->i_serial = desc_device->iSerialNumber;
- // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf);
+ // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf);
// Get 9-byte for total length
uint8_t const config_idx = CONFIG_NUM - 1;
TU_LOG_USBH("Get Configuration[0] Descriptor (9 bytes)\r\n");
- TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC), );
+ TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, 9,
+ process_enumeration, ENUM_GET_FULL_CONFIG_DESC),);
+ break;
}
- break;
- case ENUM_GET_FULL_CONFIG_DESC:
- {
- uint8_t const * desc_config = _usbh_ctrl_buf;
+ case ENUM_GET_FULL_CONFIG_DESC: {
+ uint8_t const* desc_config = _usbh_ctrl_buf;
// Use offsetof to avoid pointer to the odd/misaligned address
- uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) );
+ uint16_t const total_len = tu_le16toh(
+ tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)));
// TODO not enough buffer to hold configuration descriptor
- TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE, );
+ TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE,);
// Get full configuration descriptor
uint8_t const config_idx = CONFIG_NUM - 1;
TU_LOG_USBH("Get Configuration[0] Descriptor\r\n");
- TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG), );
+ TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, total_len,
+ process_enumeration, ENUM_SET_CONFIG),);
+ break;
}
- break;
case ENUM_SET_CONFIG:
- // Parse configuration & set up drivers
- // Driver open aren't allowed to make any usb transfer yet
- TU_ASSERT( _parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_ctrl_buf), );
-
- TU_ASSERT( tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER), );
- break;
+ TU_ASSERT(tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER),);
+ break;
- case ENUM_CONFIG_DRIVER:
- {
+ case ENUM_CONFIG_DRIVER: {
TU_LOG_USBH("Device configured\r\n");
usbh_device_t* dev = get_device(daddr);
- TU_ASSERT(dev, );
+ TU_ASSERT(dev,);
dev->configured = 1;
+ // Parse configuration & set up drivers
+ // driver_open() must not make any usb transfer
+ TU_ASSERT(_parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_ctrl_buf),);
+
// Start the Set Configuration process for interfaces (itf = TUSB_INDEX_INVALID_8)
// Since driver can perform control transfer within its set_config, this is done asynchronously.
// The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete()
// TODO use separated API instead of using TUSB_INDEX_INVALID_8
usbh_driver_set_config_complete(daddr, TUSB_INDEX_INVALID_8);
+ break;
}
- break;
default:
// stop enumeration if unknown state
enum_full_complete();
- break;
+ break;
}
}
-static bool enum_new_device(hcd_event_t* event)
-{
- _dev0.rhport = event->rhport;
+static bool enum_new_device(hcd_event_t* event) {
+ _dev0.rhport = event->rhport;
_dev0.hub_addr = event->connection.hub_addr;
_dev0.hub_port = event->connection.hub_port;
- if (_dev0.hub_addr == 0)
- {
+ if (_dev0.hub_addr == 0) {
// connected/disconnected directly with roothub
- // wait until device is stable TODO non blocking
hcd_port_reset(_dev0.rhport);
- osal_task_delay(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
- // sof of controller may not running while resetting
- hcd_port_reset_end( _dev0.rhport);
+ osal_task_delay(ENUM_RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
+ // sof of controller may not running while resetting
+ hcd_port_reset_end(_dev0.rhport);
+
+ // wait until device connection is stable TODO non blocking
+ osal_task_delay(ENUM_CONTACT_DEBOUNCING_DELAY);
// device unplugged while delaying
- if ( !hcd_port_connect_status(_dev0.rhport) ) return true;
+ if (!hcd_port_connect_status(_dev0.rhport)) {
+ enum_full_complete();
+ return true;
+ }
- _dev0.speed = hcd_port_speed_get(_dev0.rhport );
+ _dev0.speed = hcd_port_speed_get(_dev0.rhport);
TU_LOG_USBH("%s Speed\r\n", tu_str_speed[_dev0.speed]);
// fake transfer to kick-off the enumeration process
tuh_xfer_t xfer;
- xfer.daddr = 0;
- xfer.result = XFER_RESULT_SUCCESS;
+ xfer.daddr = 0;
+ xfer.result = XFER_RESULT_SUCCESS;
xfer.user_data = ENUM_ADDR0_DEVICE_DESC;
process_enumeration(&xfer);
-
}
#if CFG_TUH_HUB
- else
- {
+ else {
// connected/disconnected via external hub
- // wait until device is stable
- osal_task_delay(RESET_DELAY);
+ // wait until device connection is stable TODO non blocking
+ osal_task_delay(ENUM_CONTACT_DEBOUNCING_DELAY);
// ENUM_HUB_GET_STATUS
//TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete, 0) );
- TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_1) );
+ TU_ASSERT(hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf,
+ process_enumeration, ENUM_HUB_CLEAR_RESET_1));
}
#endif // hub
return true;
}
-static uint8_t get_new_address(bool is_hub)
-{
+static uint8_t get_new_address(bool is_hub) {
uint8_t start;
uint8_t end;
- if ( is_hub )
- {
+
+ if ( is_hub ) {
start = CFG_TUH_DEVICE_MAX;
end = start + CFG_TUH_HUB;
- }else
- {
+ }else {
start = 0;
end = start + CFG_TUH_DEVICE_MAX;
}
- for ( uint8_t idx = start; idx < end; idx++)
- {
+ for (uint8_t idx = start; idx < end; idx++) {
if (!_usbh_devices[idx].connected) return (idx+1);
}
return 0; // invalid address
}
-static bool enum_request_set_addr(void)
-{
- tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf;
+static bool enum_request_set_addr(void) {
+ tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf;
// Get new address
uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
TU_ASSERT(new_addr != 0);
-
TU_LOG_USBH("Set Address = %d\r\n", new_addr);
usbh_device_t* new_dev = get_device(new_addr);
-
- new_dev->rhport = _dev0.rhport;
- new_dev->hub_addr = _dev0.hub_addr;
- new_dev->hub_port = _dev0.hub_port;
- new_dev->speed = _dev0.speed;
+ new_dev->rhport = _dev0.rhport;
+ new_dev->hub_addr = _dev0.hub_addr;
+ new_dev->hub_port = _dev0.hub_port;
+ new_dev->speed = _dev0.speed;
new_dev->connected = 1;
- new_dev->ep0_size = desc_device->bMaxPacketSize0;
+ new_dev->ep0_size = desc_device->bMaxPacketSize0;
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_DEVICE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = TUSB_REQ_SET_ADDRESS,
- .wValue = tu_htole16(new_addr),
- .wIndex = 0,
- .wLength = 0
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = TUSB_REQ_SET_ADDRESS,
+ .wValue = tu_htole16(new_addr),
+ .wIndex = 0,
+ .wLength = 0
};
-
- tuh_xfer_t xfer =
- {
- .daddr = 0, // dev0
- .ep_addr = 0,
- .setup = &request,
- .buffer = NULL,
- .complete_cb = process_enumeration,
- .user_data = ENUM_GET_DEVICE_DESC
+ tuh_xfer_t xfer = {
+ .daddr = 0, // dev0
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = NULL,
+ .complete_cb = process_enumeration,
+ .user_data = ENUM_GET_DEVICE_DESC
};
- TU_ASSERT( tuh_control_xfer(&xfer) );
-
+ TU_ASSERT(tuh_control_xfer(&xfer));
return true;
}
-static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg)
-{
+static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) {
usbh_device_t* dev = get_device(dev_addr);
-
uint16_t const total_len = tu_le16toh(desc_cfg->wTotalLength);
uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + total_len;
uint8_t const* p_desc = tu_desc_next(desc_cfg);
@@ -1558,13 +1625,11 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
TU_LOG_USBH("Parsing Configuration descriptor (wTotalLength = %u)\r\n", total_len);
// parse each interfaces
- while( p_desc < desc_end )
- {
+ while( p_desc < desc_end ) {
uint8_t assoc_itf_count = 1;
// Class will always starts with Interface Association (if any) and then Interface descriptor
- if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
- {
+ if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) {
tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
assoc_itf_count = desc_iad->bInterfaceCount;
@@ -1584,8 +1649,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
if (1 == assoc_itf_count &&
TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
- AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol)
- {
+ AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) {
assoc_itf_count = 2;
}
#endif
@@ -1595,8 +1659,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
// manually force associated count = 2
if (1 == assoc_itf_count &&
TUSB_CLASS_CDC == desc_itf->bInterfaceClass &&
- CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == desc_itf->bInterfaceSubClass)
- {
+ CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == desc_itf->bInterfaceSubClass) {
assoc_itf_count = 2;
}
#endif
@@ -1605,18 +1668,14 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t));
// Find driver for this interface
- for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
- {
- usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id];
-
- if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) )
- {
+ for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
+ usbh_class_driver_t const * driver = get_driver(drv_id);
+ if (driver && driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) {
// open successfully
TU_LOG_USBH(" %s opened\r\n", driver->name);
// bind (associated) interfaces to found driver
- for(uint8_t i=0; i<assoc_itf_count; i++)
- {
+ for(uint8_t i=0; i<assoc_itf_count; i++) {
uint8_t const itf_num = desc_itf->bInterfaceNumber+i;
// Interface number must not be used already
@@ -1630,10 +1689,9 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
break; // exit driver find loop
}
- if( drv_id >= USBH_CLASS_DRIVER_COUNT )
- {
- TU_LOG(USBH_DEBUG, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n",
- desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol);
+ if ( drv_id == TOTAL_DRIVER_COUNT - 1 ) {
+ TU_LOG_USBH("[%u:%u] Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n",
+ dev->rhport, dev_addr, desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol);
}
}
@@ -1644,19 +1702,16 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
return true;
}
-void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
-{
+void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) {
usbh_device_t* dev = get_device(dev_addr);
- for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++)
- {
+ for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) {
// continue with next valid interface
// IAD binding interface such as CDCs should return itf_num + 1 when complete
// with usbh_driver_set_config_complete()
uint8_t const drv_id = dev->itf2drv[itf_num];
- if (drv_id != TUSB_INDEX_INVALID_8)
- {
- usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id];
+ usbh_class_driver_t const * driver = get_driver(drv_id);
+ if (driver) {
TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num);
driver->set_config(dev_addr, itf_num);
break;
@@ -1664,23 +1719,19 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
}
// all interface are configured
- if (itf_num == CFG_TUH_INTERFACE_MAX)
- {
+ if (itf_num == CFG_TUH_INTERFACE_MAX) {
enum_full_complete();
- if (is_hub_addr(dev_addr))
- {
- TU_LOG(USBH_DEBUG, "HUB address = %u is mounted\r\n", dev_addr);
- }else
- {
+ if (is_hub_addr(dev_addr)) {
+ TU_LOG_USBH("HUB address = %u is mounted\r\n", dev_addr);
+ }else {
// Invoke callback if available
if (tuh_mount_cb) tuh_mount_cb(dev_addr);
}
}
}
-static void enum_full_complete(void)
-{
+static void enum_full_complete(void) {
// mark enumeration as complete
_dev0.enumerating = 0;
diff --git a/src/host/usbh.h b/src/host/usbh.h
index 0f969a46a..359684169 100644
--- a/src/host/usbh.h
+++ b/src/host/usbh.h
@@ -47,8 +47,7 @@ typedef void (*tuh_xfer_cb_t)(tuh_xfer_t* xfer);
// it is advised to initialize it using member name
// Note2: not all field is available/meaningful in callback,
// some info is not saved by usbh to save SRAM
-struct tuh_xfer_s
-{
+struct tuh_xfer_s {
uint8_t daddr;
uint8_t ep_addr;
uint8_t TU_RESERVED; // reserved
@@ -56,8 +55,7 @@ struct tuh_xfer_s
uint32_t actual_len; // excluding setup packet
- union
- {
+ union {
tusb_control_request_t const* setup; // setup packet pointer if control transfer
uint32_t buflen; // expected length if not control transfer (not available in callback)
};
@@ -70,18 +68,30 @@ struct tuh_xfer_s
};
// Subject to change
-typedef struct
-{
+typedef struct {
uint8_t daddr;
tusb_desc_interface_t desc;
} tuh_itf_info_t;
-// ConfigID for tuh_config()
-enum
-{
- TUH_CFGID_RPI_PIO_USB_CONFIGURATION = OPT_MCU_RP2040 << 8 // cfg_param: pio_usb_configuration_t
+// ConfigID for tuh_configure()
+enum {
+ TUH_CFGID_INVALID = 0,
+ TUH_CFGID_RPI_PIO_USB_CONFIGURATION = 100, // cfg_param: pio_usb_configuration_t
+ TUH_CFGID_MAX3421 = 200,
};
+typedef struct {
+ uint8_t max_nak; // max NAK per endpoint per frame
+ uint8_t cpuctl; // R16: CPU Control Register
+ uint8_t pinctl; // R17: Pin Control Register. FDUPSPI bit is ignored
+} tuh_configure_max3421_t;
+
+typedef union {
+ // For TUH_CFGID_RPI_PIO_USB_CONFIGURATION use pio_usb_configuration_t
+
+ tuh_configure_max3421_t max3421;
+} tuh_configure_param_t;
+
//--------------------------------------------------------------------+
// APPLICATION CALLBACK
//--------------------------------------------------------------------+
@@ -94,9 +104,12 @@ TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr);
// Invoked when a device failed to mount during enumeration process
// TU_ATTR_WEAK void tuh_mount_failed_cb (uint8_t daddr);
-/// Invoked when a device is unmounted (detached)
+// Invoked when a device is unmounted (detached)
TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr);
+// Invoked when there is a new usb event, which need to be processed by tuh_task()/tuh_task_ext()
+void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr);
+
//--------------------------------------------------------------------+
// APPLICATION API
//--------------------------------------------------------------------+
@@ -105,12 +118,16 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr);
// Should be called before tuh_init()
// - cfg_id : configure ID (TBD)
// - cfg_param: configure data, structure depends on the ID
-bool tuh_configure(uint8_t controller_id, uint32_t cfg_id, const void* cfg_param);
+bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);
// Init host stack
-bool tuh_init(uint8_t controller_id);
+bool tuh_init(uint8_t rhport);
+
+// Deinit host stack on rhport
+bool tuh_deinit(uint8_t rhport);
-// Check if host stack is already initialized
+// Check if host stack is already initialized with any roothub ports
+// To check if an rhport is initialized, use tuh_rhport_is_active()
bool tuh_inited(void);
// Task function should be called in main/rtos loop, extended version of tuh_task()
@@ -120,8 +137,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr);
// Task function should be called in main/rtos loop
TU_ATTR_ALWAYS_INLINE static inline
-void tuh_task(void)
-{
+void tuh_task(void) {
tuh_task_ext(UINT32_MAX, false);
}
@@ -129,14 +145,31 @@ void tuh_task(void)
bool tuh_task_event_ready(void);
#ifndef _TUSB_HCD_H_
-extern void hcd_int_handler(uint8_t rhport);
+extern void hcd_int_handler(uint8_t rhport, bool in_isr);
#endif
-// Interrupt handler, name alias to HCD
-#define tuh_int_handler hcd_int_handler
+// Interrupt handler alias to HCD with in_isr as optional parameter
+// - tuh_int_handler(rhport) --> hcd_int_handler(rhport, true)
+// - tuh_int_handler(rhport, in_isr) --> hcd_int_handler(rhport, in_isr)
+// Note: this is similar to TU_VERIFY(), _GET_3RD_ARG() is defined in tusb_verify.h
+#define _tuh_int_handler_1arg(_rhport) hcd_int_handler(_rhport, true)
+#define _tuh_int_hanlder_2arg(_rhport, _in_isr) hcd_int_handler(_rhport, _in_isr)
+#define tuh_int_handler(...) _GET_3RD_ARG(__VA_ARGS__, _tuh_int_hanlder_2arg, _tuh_int_handler_1arg, _dummy)(__VA_ARGS__)
+
+// Check if roothub port is initialized and active as a host
+bool tuh_rhport_is_active(uint8_t rhport);
+// Assert/de-assert Bus Reset signal to roothub port. USB specs: it should last 10-50ms
+bool tuh_rhport_reset_bus(uint8_t rhport, bool active);
+
+//--------------------------------------------------------------------+
+// Device API
+//--------------------------------------------------------------------+
+
+// Get VID/PID of device
bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid);
+// Get speed of device
tusb_speed_t tuh_speed_get(uint8_t daddr);
// Check if device is connected and configured
@@ -144,8 +177,7 @@ bool tuh_mounted(uint8_t daddr);
// Check if device is suspended
TU_ATTR_ALWAYS_INLINE static inline
-bool tuh_suspended(uint8_t daddr)
-{
+bool tuh_suspended(uint8_t daddr) {
// TODO implement suspend & resume on host
(void) daddr;
return false;
@@ -153,8 +185,7 @@ bool tuh_suspended(uint8_t daddr)
// Check if device is ready to communicate with
TU_ATTR_ALWAYS_INLINE static inline
-bool tuh_ready(uint8_t daddr)
-{
+bool tuh_ready(uint8_t daddr) {
return tuh_mounted(daddr) && !tuh_suspended(daddr);
}
@@ -172,8 +203,12 @@ bool tuh_control_xfer(tuh_xfer_t* xfer);
// - sync : blocking if complete callback is NULL.
bool tuh_edpt_xfer(tuh_xfer_t* xfer);
-// Open an non-control endpoint
-bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep);
+// Open a non-control endpoint
+bool tuh_edpt_open(uint8_t daddr, tusb_desc_endpoint_t const * desc_ep);
+
+// Abort a queued transfer. Note: it can only abort transfer that has not been started
+// Return true if a queued transfer is aborted, false if there is no transfer to abort
+bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr);
// Set Configuration (control transfer)
// config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1
diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_pvt.h
index be9811641..95de915e9 100644
--- a/src/host/usbh_classdriver.h
+++ b/src/host/usbh_pvt.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_USBH_CLASSDRIVER_H_
-#define _TUSB_USBH_CLASSDRIVER_H_
+#ifndef _TUSB_USBH_PVT_H_
+#define _TUSB_USBH_PVT_H_
#include "osal/osal.h"
#include "common/tusb_fifo.h"
@@ -35,6 +35,12 @@
extern "C" {
#endif
+#define TU_LOG_USBH(...) TU_LOG(CFG_TUH_LOG_LEVEL, __VA_ARGS__)
+#define TU_LOG_MEM_USBH(...) TU_LOG_MEM(CFG_TUH_LOG_LEVEL, __VA_ARGS__)
+#define TU_LOG_BUF_USBH(...) TU_LOG_BUF(CFG_TUH_LOG_LEVEL, __VA_ARGS__)
+#define TU_LOG_INT_USBH(...) TU_LOG_INT(CFG_TUH_LOG_LEVEL, __VA_ARGS__)
+#define TU_LOG_HEX_USBH(...) TU_LOG_HEX(CFG_TUH_LOG_LEVEL, __VA_ARGS__)
+
enum {
USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS)
};
@@ -44,17 +50,20 @@ enum {
//--------------------------------------------------------------------+
typedef struct {
- #if CFG_TUSB_DEBUG >= 2
char const* name;
- #endif
-
- void (* const init )(void);
+ bool (* const init )(void);
+ bool (* const deinit )(void);
bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num);
bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
void (* const close )(uint8_t dev_addr);
} usbh_class_driver_t;
+// Invoked when initializing host stack to get additional class drivers.
+// Can be implemented by application to extend/overwrite class driver support.
+// Note: The drivers array must be accessible at all time when stack is active
+usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK;
+
// Call by class driver to tell USBH that it has complete the enumeration
void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num);
@@ -64,6 +73,8 @@ uint8_t* usbh_get_enum_buf(void);
void usbh_int_set(bool enabled);
+void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr);
+
//--------------------------------------------------------------------+
// USBH Endpoint API
//--------------------------------------------------------------------+
@@ -73,12 +84,10 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b
tuh_xfer_cb_t complete_cb, uintptr_t user_data);
TU_ATTR_ALWAYS_INLINE
-static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
-{
+static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) {
return usbh_edpt_xfer_with_callback(dev_addr, ep_addr, buffer, total_bytes, NULL, 0);
}
-
// Claim an endpoint before submitting a transfer.
// If caller does not make any transfer, it must release endpoint for others.
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr);
diff --git a/src/osal/osal.h b/src/osal/osal.h
index f092e8ffb..8f45ea5c1 100644
--- a/src/osal/osal.h
+++ b/src/osal/osal.h
@@ -74,15 +74,18 @@ typedef void (*osal_task_func_t)( void * );
// Should be implemented as static inline function in osal_port.h header
/*
osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef);
+ bool osal_semaphore_delete(osal_semaphore_t semd_hdl);
bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr);
bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec);
void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed
osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef);
+ bool osal_mutex_delete(osal_mutex_t mutex_hdl)
bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec);
bool osal_mutex_unlock(osal_mutex_t mutex_hdl);
osal_queue_t osal_queue_create(osal_queue_def_t* qdef);
+ bool osal_queue_delete(osal_queue_t qhdl);
bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec);
bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr);
bool osal_queue_empty(osal_queue_t qhdl);
diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h
index 477f64892..f1f05f353 100644
--- a/src/osal/osal_freertos.h
+++ b/src/osal/osal_freertos.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_OSAL_FREERTOS_H_
-#define _TUSB_OSAL_FREERTOS_H_
+#ifndef TUSB_OSAL_FREERTOS_H_
+#define TUSB_OSAL_FREERTOS_H_
// FreeRTOS Headers
#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h)
@@ -52,53 +52,60 @@ extern "C" {
typedef SemaphoreHandle_t osal_semaphore_t;
typedef SemaphoreHandle_t osal_mutex_t;
-
-// _int_set is not used with an RTOS
-#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
- static _type _name##_##buf[_depth];\
- osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf };
+typedef QueueHandle_t osal_queue_t;
typedef struct
{
uint16_t depth;
uint16_t item_sz;
void* buf;
+
+#if defined(configQUEUE_REGISTRY_SIZE) && (configQUEUE_REGISTRY_SIZE>0)
+ char const* name;
+#endif
+
#if configSUPPORT_STATIC_ALLOCATION
StaticQueue_t sq;
#endif
-}osal_queue_def_t;
+} osal_queue_def_t;
-typedef QueueHandle_t osal_queue_t;
+#if defined(configQUEUE_REGISTRY_SIZE) && (configQUEUE_REGISTRY_SIZE>0)
+ #define _OSAL_Q_NAME(_name) .name = #_name
+#else
+ #define _OSAL_Q_NAME(_name)
+#endif
+
+// _int_set is not used with an RTOS
+#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
+ static _type _name##_##buf[_depth];\
+ osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, _OSAL_Q_NAME(_name) };
//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec)
-{
- if (msec == OSAL_TIMEOUT_WAIT_FOREVER) return portMAX_DELAY;
- if (msec == 0) return 0;
+TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec) {
+ if ( msec == OSAL_TIMEOUT_WAIT_FOREVER ) return portMAX_DELAY;
+ if ( msec == 0 ) return 0;
uint32_t ticks = pdMS_TO_TICKS(msec);
// configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms
// we still need to delay at least 1 tick
- if (ticks == 0) ticks =1 ;
+ if ( ticks == 0 ) ticks = 1;
return ticks;
}
-TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
-{
- vTaskDelay( pdMS_TO_TICKS(msec) );
+TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
+ vTaskDelay(pdMS_TO_TICKS(msec));
}
//--------------------------------------------------------------------+
// Semaphore API
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) {
#if configSUPPORT_STATIC_ALLOCATION
return xSemaphoreCreateBinaryStatic(semdef);
#else
@@ -107,14 +114,15 @@ TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_
#endif
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
-{
- if ( !in_isr )
- {
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
+ vSemaphoreDelete(semd_hdl);
+ return true;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
+ if ( !in_isr ) {
return xSemaphoreGive(sem_hdl) != 0;
- }
- else
- {
+ } else {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken);
@@ -129,13 +137,11 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t se
}
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
return xSemaphoreTake(sem_hdl, _osal_ms2tick(msec));
}
-TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) {
xQueueReset(sem_hdl);
}
@@ -143,8 +149,7 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t c
// MUTEX API (priority inheritance)
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) {
#if configSUPPORT_STATIC_ALLOCATION
return xSemaphoreCreateMutexStatic(mdef);
#else
@@ -153,13 +158,16 @@ TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_de
#endif
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
+ vSemaphoreDelete(mutex_hdl);
+ return true;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
return osal_semaphore_wait(mutex_hdl, msec);
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
return xSemaphoreGive(mutex_hdl);
}
@@ -167,33 +175,40 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
// QUEUE API
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
+ osal_queue_t q;
+
#if configSUPPORT_STATIC_ALLOCATION
- return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq);
+ q = xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq);
#else
- return xQueueCreate(qdef->depth, qdef->item_sz);
+ q = xQueueCreate(qdef->depth, qdef->item_sz);
#endif
+
+#if defined(configQUEUE_REGISTRY_SIZE) && (configQUEUE_REGISTRY_SIZE>0)
+ vQueueAddToRegistry(q, qdef->name);
+#endif
+
+ return q;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
+ vQueueDelete(qhdl);
+ return true;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
return xQueueReceive(qhdl, data, _osal_ms2tick(msec));
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
-{
- if ( !in_isr )
- {
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) {
+ if ( !in_isr ) {
return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0;
- }
- else
- {
+ } else {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken);
#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
- // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7
+ // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 (IDF v5)
if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR();
#else
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
@@ -203,13 +218,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void
}
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
return uxQueueMessagesWaiting(qhdl) == 0;
}
#ifdef __cplusplus
- }
+}
#endif
#endif
diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h
index b8ea2087c..16def0d2a 100644
--- a/src/osal/osal_mynewt.h
+++ b/src/osal/osal_mynewt.h
@@ -36,8 +36,7 @@
//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
os_time_delay( os_time_ms_to_ticks32(msec) );
}
@@ -47,25 +46,26 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
typedef struct os_sem osal_semaphore_def_t;
typedef struct os_sem* osal_semaphore_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) {
return (os_sem_init(semdef, 0) == OS_OK) ? (osal_semaphore_t) semdef : NULL;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
+ (void) semd_hdl;
+ return true; // nothing to do
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
(void) in_isr;
return os_sem_release(sem_hdl) == OS_OK;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec);
return os_sem_pend(sem_hdl, ticks) == OS_OK;
}
-static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
-{
+static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) {
// TODO implement later
}
@@ -75,19 +75,21 @@ static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
typedef struct os_mutex osal_mutex_def_t;
typedef struct os_mutex* osal_mutex_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) {
return (os_mutex_init(mdef) == OS_OK) ? (osal_mutex_t) mdef : NULL;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
+ (void) mutex_hdl;
+ return true; // nothing to do
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec);
return os_mutex_pend(mutex_hdl, ticks) == OS_OK;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
return os_mutex_release(mutex_hdl) == OS_OK;
}
@@ -101,8 +103,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
static struct os_event _name##_##evbuf[_depth];\
osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, .evbuf = _name##_##evbuf};\
-typedef struct
-{
+typedef struct {
uint16_t depth;
uint16_t item_sz;
void* buf;
@@ -116,17 +117,20 @@ typedef struct
typedef osal_queue_def_t* osal_queue_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
-{
- if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usbd queue") ) return NULL;
- if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usbd evqueue") ) return NULL;
+TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
+ if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usb queue") ) return NULL;
+ if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usb evqueue") ) return NULL;
os_eventq_init(&qdef->evq);
return (osal_queue_t) qdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
+ (void) qhdl;
+ return true; // nothing to do
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
(void) msec; // os_eventq_get() does not take timeout, always behave as msec = WAIT_FOREVER
struct os_event* ev;
@@ -139,8 +143,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v
return true;
}
-static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
-{
+static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) {
(void) in_isr;
// get a block from mem pool for data
@@ -150,8 +153,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in
// get a block from event pool to put into queue
struct os_event* ev = (struct os_event*) os_memblock_get(&qhdl->epool);
- if (!ev)
- {
+ if (!ev) {
os_memblock_put(&qhdl->mpool, ptr);
return false;
}
@@ -163,8 +165,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in
return true;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
return STAILQ_EMPTY(&qhdl->evq.evq_list);
}
diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h
index 5f407378e..c954fcfe8 100644
--- a/src/osal/osal_none.h
+++ b/src/osal/osal_none.h
@@ -24,11 +24,11 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_OSAL_NONE_H_
-#define _TUSB_OSAL_NONE_H_
+#ifndef TUSB_OSAL_NONE_H_
+#define TUSB_OSAL_NONE_H_
#ifdef __cplusplus
- extern "C" {
+extern "C" {
#endif
//--------------------------------------------------------------------+
@@ -37,45 +37,46 @@
#if CFG_TUH_ENABLED
// currently only needed/available in host mode
-void osal_task_delay(uint32_t msec);
+TU_ATTR_WEAK void osal_task_delay(uint32_t msec);
#endif
//--------------------------------------------------------------------+
// Binary Semaphore API
//--------------------------------------------------------------------+
-typedef struct
-{
+typedef struct {
volatile uint16_t count;
-}osal_semaphore_def_t;
+} osal_semaphore_def_t;
typedef osal_semaphore_def_t* osal_semaphore_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) {
semdef->count = 0;
return semdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
+ (void) semd_hdl;
+ return true; // nothing to do
+}
+
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
(void) in_isr;
sem_hdl->count++;
return true;
}
// TODO blocking for now
-TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
(void) msec;
- while (sem_hdl->count == 0) { }
+ while (sem_hdl->count == 0) {}
sem_hdl->count--;
return true;
}
-TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) {
sem_hdl->count = 0;
}
@@ -90,19 +91,21 @@ typedef osal_semaphore_t osal_mutex_t;
// Note: multiple cores MCUs usually do provide IPC API for mutex
// or we can use std atomic function
-TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) {
mdef->count = 1;
return mdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
+ (void) mutex_hdl;
+ return true; // nothing to do
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) {
return osal_semaphore_wait(mutex_hdl, msec);
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
return osal_semaphore_post(mutex_hdl, false);
}
@@ -119,11 +122,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
//--------------------------------------------------------------------+
#include "common/tusb_fifo.h"
-typedef struct
-{
- void (*interrupt_set)(bool);
+typedef struct {
+ void (* interrupt_set)(bool);
tu_fifo_t ff;
-}osal_queue_def_t;
+} osal_queue_def_t;
typedef osal_queue_def_t* osal_queue_t;
@@ -136,27 +138,28 @@ typedef osal_queue_def_t* osal_queue_t;
}
// lock queue by disable USB interrupt
-TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) {
// disable dcd/hcd interrupt
qhdl->interrupt_set(false);
}
// unlock queue
-TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) {
// enable dcd/hcd interrupt
qhdl->interrupt_set(true);
}
-TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
tu_fifo_clear(&qdef->ff);
return (osal_queue_t) qdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
+ (void) qhdl;
+ return true; // nothing to do
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
(void) msec; // not used, always behave as msec = 0
_osal_q_lock(qhdl);
@@ -166,8 +169,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v
return success;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) {
if (!in_isr) {
_osal_q_lock(qhdl);
}
@@ -179,19 +181,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void
}
TU_ASSERT(success);
-
return success;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
// Skip queue lock/unlock since this function is primarily called
// with interrupt disabled before going into low power mode
return tu_fifo_empty(&qhdl->ff);
}
#ifdef __cplusplus
- }
+}
#endif
-#endif /* _TUSB_OSAL_NONE_H_ */
+#endif
diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h
index e6efa0968..00c589ef9 100644
--- a/src/osal/osal_pico.h
+++ b/src/osal/osal_pico.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_OSAL_PICO_H_
-#define _TUSB_OSAL_PICO_H_
+#ifndef TUSB_OSAL_PICO_H_
+#define TUSB_OSAL_PICO_H_
#include "pico/time.h"
#include "pico/sem.h"
@@ -33,42 +33,42 @@
#include "pico/critical_section.h"
#ifdef __cplusplus
- extern "C" {
+extern "C" {
#endif
//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
sleep_ms(msec);
}
//--------------------------------------------------------------------+
// Binary Semaphore API
//--------------------------------------------------------------------+
-typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t;
+typedef struct semaphore osal_semaphore_def_t, * osal_semaphore_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) {
sem_init(semdef, 0, 255);
return semdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
+ (void) semd_hdl;
+ return true; // nothing to do
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
(void) in_isr;
sem_release(sem_hdl);
return true;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
return sem_acquire_timeout_ms(sem_hdl, msec);
}
-TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) {
sem_reset(sem_hdl, 0);
}
@@ -76,21 +76,23 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t s
// MUTEX API
// Within tinyusb, mutex is never used in ISR context
//--------------------------------------------------------------------+
-typedef struct mutex osal_mutex_def_t, *osal_mutex_t;
+typedef struct mutex osal_mutex_def_t, * osal_mutex_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) {
mutex_init(mdef);
return mdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
+ (void) mutex_hdl;
+ return true; // nothing to do
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
return mutex_enter_timeout_ms(mutex_hdl, msec);
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
mutex_exit(mutex_hdl);
return true;
}
@@ -100,75 +102,54 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
//--------------------------------------------------------------------+
#include "common/tusb_fifo.h"
-typedef struct
-{
- tu_fifo_t ff;
- struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section
+typedef struct {
+ tu_fifo_t ff;
+ struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section
} osal_queue_def_t;
typedef osal_queue_def_t* osal_queue_t;
// role device/host is used by OS NONE for mutex (disable usb isr) only
-#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
+#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
uint8_t _name##_buf[_depth*sizeof(_type)]; \
osal_queue_def_t _name = { \
.ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \
}
-// lock queue by disable USB interrupt
-TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl)
-{
- critical_section_enter_blocking(&qhdl->critsec);
-}
-
-// unlock queue
-TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl)
-{
- critical_section_exit(&qhdl->critsec);
-}
-
-TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
critical_section_init(&qdef->critsec);
tu_fifo_clear(&qdef->ff);
return (osal_queue_t) qdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
-{
- (void) msec; // not used, always behave as msec = 0
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
+ osal_queue_def_t* qdef = (osal_queue_def_t*) qhdl;
+ critical_section_deinit(&qdef->critsec);
+ return true;
+}
- // TODO: revisit... docs say that mutexes are never used from IRQ context,
- // however osal_queue_recieve may be. therefore my assumption is that
- // the fifo mutex is not populated for queues used from an IRQ context
- //assert(!qhdl->ff.mutex);
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
+ (void) msec; // not used, always behave as msec = 0
- _osal_q_lock(qhdl);
+ critical_section_enter_blocking(&qhdl->critsec);
bool success = tu_fifo_read(&qhdl->ff, data);
- _osal_q_unlock(qhdl);
+ critical_section_exit(&qhdl->critsec);
return success;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
-{
- // TODO: revisit... docs say that mutexes are never used from IRQ context,
- // however osal_queue_recieve may be. therefore my assumption is that
- // the fifo mutex is not populated for queues used from an IRQ context
- //assert(!qhdl->ff.mutex);
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) {
(void) in_isr;
- _osal_q_lock(qhdl);
+ critical_section_enter_blocking(&qhdl->critsec);
bool success = tu_fifo_write(&qhdl->ff, data);
- _osal_q_unlock(qhdl);
+ critical_section_exit(&qhdl->critsec);
TU_ASSERT(success);
-
return success;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
// TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single
// volatile read.
@@ -178,7 +159,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
}
#ifdef __cplusplus
- }
+}
#endif
-#endif /* _TUSB_OSAL_PICO_H_ */
+#endif
diff --git a/src/osal/osal_rtthread.h b/src/osal/osal_rtthread.h
index 18eb9c693..c27814835 100644
--- a/src/osal/osal_rtthread.h
+++ b/src/osal/osal_rtthread.h
@@ -2,6 +2,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2020 tfx2001 ([email protected])
+ * Copyright (c) 2020 yekai ([email protected])
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,8 +25,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_OSAL_RTTHREAD_H_
-#define _TUSB_OSAL_RTTHREAD_H_
+#ifndef TUSB_OSAL_RTTHREAD_H_
+#define TUSB_OSAL_RTTHREAD_H_
// RT-Thread Headers
#include "rtthread.h"
@@ -47,23 +48,27 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
typedef struct rt_semaphore osal_semaphore_def_t;
typedef rt_sem_t osal_semaphore_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t
-osal_semaphore_create(osal_semaphore_def_t *semdef) {
- rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_PRIO);
- return semdef;
+TU_ATTR_ALWAYS_INLINE static inline
+osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) {
+ rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_PRIO);
+ return semdef;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
+ return RT_EOK == rt_sem_detach(semd_hdl);
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
- (void) in_isr;
- return rt_sem_release(sem_hdl) == RT_EOK;
+ (void) in_isr;
+ return rt_sem_release(sem_hdl) == RT_EOK;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
- return rt_sem_take(sem_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK;
+ return rt_sem_take(sem_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK;
}
TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) {
- rt_sem_control(sem_hdl, RT_IPC_CMD_RESET, 0);
+ rt_sem_control(sem_hdl, RT_IPC_CMD_RESET, 0);
}
//--------------------------------------------------------------------+
@@ -73,16 +78,20 @@ typedef struct rt_mutex osal_mutex_def_t;
typedef rt_mutex_t osal_mutex_t;
TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) {
- rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_PRIO);
- return mdef;
+ rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_PRIO);
+ return mdef;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
+ return RT_EOK == rt_mutex_detach(mutex_hdl);
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
- return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK;
+ return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
- return rt_mutex_release(mutex_hdl) == RT_EOK;
+ return rt_mutex_release(mutex_hdl) == RT_EOK;
}
//--------------------------------------------------------------------+
@@ -105,28 +114,35 @@ typedef struct {
typedef rt_mq_t osal_queue_t;
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) {
- rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz,
- qdef->item_sz * qdef->depth, RT_IPC_FLAG_PRIO);
- return &(qdef->sq);
+ rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz,
+ qdef->item_sz * qdef->depth, RT_IPC_FLAG_PRIO);
+ return &(qdef->sq);
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) {
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
+ return RT_EOK == rt_mq_detach(qhdl);
+}
- rt_tick_t tick = rt_tick_from_millisecond((rt_int32_t) msec);
- return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) == RT_EOK;
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) {
+ rt_tick_t tick = rt_tick_from_millisecond((rt_int32_t) msec);
+#if RT_VERSION_MAJOR >= 5
+ return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) > 0;
+#else
+ return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) == RT_EOK;
+#endif /* RT_VERSION_MAJOR >= 5 */
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) {
- (void) in_isr;
- return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK;
+ (void) in_isr;
+ return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
- return (qhdl->entry) == 0;
+ return (qhdl->entry) == 0;
}
#ifdef __cplusplus
}
#endif
-#endif /* _TUSB_OSAL_RTTHREAD_H_ */
+#endif
diff --git a/src/osal/osal_rtx4.h b/src/osal/osal_rtx4.h
index e443135e0..35909e4d6 100644
--- a/src/osal/osal_rtx4.h
+++ b/src/osal/osal_rtx4.h
@@ -25,8 +25,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_OSAL_RTX4_H_
-#define _TUSB_OSAL_RTX4_H_
+#ifndef TUSB_OSAL_RTX4_H_
+#define TUSB_OSAL_RTX4_H_
#include <rtl.h>
@@ -37,8 +37,7 @@ extern "C" {
//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
uint16_t hi = msec >> 16;
uint16_t lo = msec;
while (hi--) {
@@ -48,12 +47,13 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
}
TU_ATTR_ALWAYS_INLINE static inline uint16_t msec2wait(uint32_t msec) {
- if (msec == OSAL_TIMEOUT_WAIT_FOREVER)
+ if (msec == OSAL_TIMEOUT_WAIT_FOREVER) {
return 0xFFFF;
- else if (msec >= 0xFFFE)
+ } else if (msec >= 0xFFFE) {
return 0xFFFE;
- else
+ } else {
return msec;
+ }
}
//--------------------------------------------------------------------+
@@ -67,6 +67,11 @@ TU_ATTR_ALWAYS_INLINE static inline OS_ID osal_semaphore_create(osal_semaphore_d
return semdef;
}
+TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
+ (void) semd_hdl;
+ return true; // nothing to do
+}
+
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
if ( !in_isr ) {
os_sem_send(sem_hdl);
@@ -90,19 +95,21 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t c
typedef OS_MUT osal_mutex_def_t;
typedef OS_ID osal_mutex_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) {
os_mut_init(mdef);
return mdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
+ (void) mutex_hdl;
+ return true; // nothing to do
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) {
return os_mut_wait(mutex_hdl, msec2wait(msec)) != OS_R_TMO;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
return os_mut_release(mutex_hdl) == OS_R_OK;
}
@@ -116,9 +123,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
_declare_box(_name##__pool, sizeof(_type), _depth); \
osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .pool = _name##__pool, .mbox = _name##__mbox };
-
-typedef struct
-{
+typedef struct {
uint16_t depth;
uint16_t item_sz;
U32* pool;
@@ -127,15 +132,13 @@ typedef struct
typedef osal_queue_def_t* osal_queue_t;
-TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
-{
+TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
os_mbx_init(qdef->mbox, (qdef->depth + 4) * 4);
_init_box(qdef->pool, ((qdef->item_sz+3)/4)*(qdef->depth) + 3, qdef->item_sz);
return qdef;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
void* buf;
os_mbx_wait(qhdl->mbox, &buf, msec2wait(msec));
memcpy(data, buf, qhdl->item_sz);
@@ -143,23 +146,23 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v
return true;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
+ (void) qhdl;
+ return true; // nothing to do ?
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) {
void* buf = _alloc_box(qhdl->pool);
memcpy(buf, data, qhdl->item_sz);
- if ( !in_isr )
- {
+ if ( !in_isr ) {
os_mbx_send(qhdl->mbox, buf, 0xFFFF);
- }
- else
- {
+ } else {
isr_mbx_send(qhdl->mbox, buf);
}
return true;
}
-TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
return os_mbx_check(qhdl->mbox) == qhdl->depth;
}
diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c
new file mode 100644
index 000000000..39afb7505
--- /dev/null
+++ b/src/portable/analog/max3421/hcd_max3421.c
@@ -0,0 +1,1010 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
+
+#include <stdatomic.h>
+#include "host/hcd.h"
+#include "host/usbh.h"
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+// Command format is
+// Reg [7:3] | 0 [2] | Dir [1] | Ack [0]
+
+enum {
+ CMDBYTE_WRITE = 0x02,
+};
+
+enum {
+ RCVVFIFO_ADDR = 1u << 3, // 0x08
+ SNDFIFO_ADDR = 2u << 3, // 0x10
+ SUDFIFO_ADDR = 4u << 3, // 0x20
+ RCVBC_ADDR = 6u << 3, // 0x30
+ SNDBC_ADDR = 7u << 3, // 0x38
+ USBIRQ_ADDR = 13u << 3, // 0x68
+ USBIEN_ADDR = 14u << 3, // 0x70
+ USBCTL_ADDR = 15u << 3, // 0x78
+ CPUCTL_ADDR = 16u << 3, // 0x80
+ PINCTL_ADDR = 17u << 3, // 0x88
+ REVISION_ADDR = 18u << 3, // 0x90
+ // 19 is not used
+ IOPINS1_ADDR = 20u << 3, // 0xA0
+ IOPINS2_ADDR = 21u << 3, // 0xA8
+ GPINIRQ_ADDR = 22u << 3, // 0xB0
+ GPINIEN_ADDR = 23u << 3, // 0xB8
+ GPINPOL_ADDR = 24u << 3, // 0xC0
+ HIRQ_ADDR = 25u << 3, // 0xC8
+ HIEN_ADDR = 26u << 3, // 0xD0
+ MODE_ADDR = 27u << 3, // 0xD8
+ PERADDR_ADDR = 28u << 3, // 0xE0
+ HCTL_ADDR = 29u << 3, // 0xE8
+ HXFR_ADDR = 30u << 3, // 0xF0
+ HRSL_ADDR = 31u << 3, // 0xF8
+};
+
+enum {
+ USBIRQ_OSCOK_IRQ = 1u << 0,
+ USBIRQ_NOVBUS_IRQ = 1u << 5,
+ USBIRQ_VBUS_IRQ = 1u << 6,
+};
+
+enum {
+ USBCTL_PWRDOWN = 1u << 4,
+ USBCTL_CHIPRES = 1u << 5,
+};
+
+enum {
+ CPUCTL_IE = 1u << 0,
+ CPUCTL_PULSEWID0 = 1u << 6,
+ CPUCTL_PULSEWID1 = 1u << 7,
+};
+
+enum {
+ PINCTL_GPXA = 1u << 0,
+ PINCTL_GPXB = 1u << 1,
+ PINCTL_POSINT = 1u << 2,
+ PINCTL_INTLEVEL = 1u << 3,
+ PINCTL_FDUPSPI = 1u << 4,
+};
+
+enum {
+ HIRQ_BUSEVENT_IRQ = 1u << 0,
+ HIRQ_RWU_IRQ = 1u << 1,
+ HIRQ_RCVDAV_IRQ = 1u << 2,
+ HIRQ_SNDBAV_IRQ = 1u << 3,
+ HIRQ_SUSDN_IRQ = 1u << 4,
+ HIRQ_CONDET_IRQ = 1u << 5,
+ HIRQ_FRAME_IRQ = 1u << 6,
+ HIRQ_HXFRDN_IRQ = 1u << 7,
+};
+
+enum {
+ MODE_HOST = 1u << 0,
+ MODE_LOWSPEED = 1u << 1,
+ MODE_HUBPRE = 1u << 2,
+ MODE_SOFKAENAB = 1u << 3,
+ MODE_SEPIRQ = 1u << 4,
+ MODE_DELAYISO = 1u << 5,
+ MODE_DMPULLDN = 1u << 6,
+ MODE_DPPULLDN = 1u << 7,
+};
+
+enum {
+ HCTL_BUSRST = 1u << 0,
+ HCTL_FRMRST = 1u << 1,
+ HCTL_SAMPLEBUS = 1u << 2,
+ HCTL_SIGRSM = 1u << 3,
+ HCTL_RCVTOG0 = 1u << 4,
+ HCTL_RCVTOG1 = 1u << 5,
+ HCTL_SNDTOG0 = 1u << 6,
+ HCTL_SNDTOG1 = 1u << 7,
+};
+
+enum {
+ HXFR_EPNUM_MASK = 0x0f,
+ HXFR_SETUP = 1u << 4,
+ HXFR_OUT_NIN = 1u << 5,
+ HXFR_ISO = 1u << 6,
+ HXFR_HS = 1u << 7,
+};
+
+enum {
+ HRSL_RESULT_MASK = 0x0f,
+ HRSL_RCVTOGRD = 1u << 4,
+ HRSL_SNDTOGRD = 1u << 5,
+ HRSL_KSTATUS = 1u << 6,
+ HRSL_JSTATUS = 1u << 7,
+};
+
+enum {
+ HRSL_SUCCESS = 0,
+ HRSL_BUSY,
+ HRSL_BAD_REQ,
+ HRSL_UNDEF,
+ HRSL_NAK,
+ HRSL_STALL,
+ HRSL_TOG_ERR,
+ HRSL_WRONG_PID,
+ HRSL_BAD_BYTECOUNT,
+ HRSL_PID_ERR,
+ HRSL_PKT_ERR,
+ HRSL_CRC_ERR,
+ HRSL_K_ERR,
+ HRSL_J_ERR,
+ HRSL_TIMEOUT,
+ HRSL_BABBLE,
+};
+
+enum {
+ DEFAULT_HIEN = HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ | HIRQ_HXFRDN_IRQ | HIRQ_RCVDAV_IRQ
+};
+
+enum {
+ MAX_NAK_DEFAULT = 1 // Number of NAK per endpoint per usb frame
+};
+
+enum {
+ EP_STATE_IDLE = 0,
+ EP_STATE_COMPLETE = 1,
+ EP_STATE_ATTEMPT_1 = 2, // pending 1st attempt
+ EP_STATE_ATTEMPT_MAX = 15
+};
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+typedef struct {
+ uint8_t daddr;
+
+ union { ;
+ struct TU_ATTR_PACKED {
+ uint8_t ep_num : 4;
+ uint8_t is_setup : 1;
+ uint8_t is_out : 1;
+ uint8_t is_iso : 1;
+ }hxfr_bm;
+
+ uint8_t hxfr;
+ };
+
+ struct TU_ATTR_PACKED {
+ uint8_t state : 4;
+ uint8_t data_toggle : 1;
+ uint16_t packet_size : 11;
+ };
+
+ uint16_t total_len;
+ uint16_t xferred_len;
+ uint8_t* buf;
+} max3421_ep_t;
+
+TU_VERIFY_STATIC(sizeof(max3421_ep_t) == 12, "size is not correct");
+
+typedef struct {
+ volatile uint16_t frame_count;
+
+ // cached register
+ uint8_t sndbc;
+ uint8_t hirq;
+ uint8_t hien;
+ uint8_t mode;
+ uint8_t peraddr;
+ uint8_t hxfr;
+
+ atomic_flag busy; // busy transferring
+
+#if OSAL_MUTEX_REQUIRED
+ OSAL_MUTEX_DEF(spi_mutexdef);
+ osal_mutex_t spi_mutex;
+#endif
+
+ max3421_ep_t ep[CFG_TUH_MAX3421_ENDPOINT_TOTAL]; // [0] is reserved for addr0
+} max3421_data_t;
+
+static max3421_data_t _hcd_data;
+
+// max NAK before giving up in a frame. 0 means infinite NAKs
+static tuh_configure_max3421_t _tuh_cfg = {
+ .max_nak = MAX_NAK_DEFAULT,
+ .cpuctl = 0, // default: INT pulse width = 10.6 us
+ .pinctl = 0, // default: negative edge interrupt
+};
+
+//--------------------------------------------------------------------+
+// API: SPI transfer with MAX3421E
+// - spi_cs_api(), spi_xfer_api(), int_api(): must be implemented by application
+// - reg_read(), reg_write(): is implemented by this driver, can be used by application
+//--------------------------------------------------------------------+
+
+// API to control MAX3421 SPI CS
+extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active);
+
+// API to transfer data with MAX3421 SPI
+// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
+extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes);
+
+// API to enable/disable MAX3421 INTR pin interrupt
+extern void tuh_max3421_int_api(uint8_t rhport, bool enabled);
+
+// API to read MAX3421's register. Implemented by TinyUSB
+uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
+
+// API to write MAX3421's register. Implemented by TinyUSB
+bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
+
+//--------------------------------------------------------------------+
+// SPI Commands and Helper
+//--------------------------------------------------------------------+
+
+#define reg_read tuh_max3421_reg_read
+#define reg_write tuh_max3421_reg_write
+
+static void max3421_spi_lock(uint8_t rhport, bool in_isr) {
+ // disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr
+ if (!in_isr) {
+ (void) osal_mutex_lock(_hcd_data.spi_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
+ tuh_max3421_int_api(rhport, false);
+ }
+
+ // assert CS
+ tuh_max3421_spi_cs_api(rhport, true);
+}
+
+static void max3421_spi_unlock(uint8_t rhport, bool in_isr) {
+ // de-assert CS
+ tuh_max3421_spi_cs_api(rhport, false);
+
+ // mutex unlock and re-enable interrupt
+ if (!in_isr) {
+ tuh_max3421_int_api(rhport, true);
+ (void) osal_mutex_unlock(_hcd_data.spi_mutex);
+ }
+}
+
+uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr) {
+ uint8_t tx_buf[2] = {reg, 0};
+ uint8_t rx_buf[2] = {0, 0};
+
+ max3421_spi_lock(rhport, in_isr);
+ bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
+ max3421_spi_unlock(rhport, in_isr);
+
+ _hcd_data.hirq = rx_buf[0];
+ return ret ? rx_buf[1] : 0;
+}
+
+bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) {
+ uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data};
+ uint8_t rx_buf[2] = {0, 0};
+
+ max3421_spi_lock(rhport, in_isr);
+ bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
+ max3421_spi_unlock(rhport, in_isr);
+
+ // HIRQ register since we are in full-duplex mode
+ _hcd_data.hirq = rx_buf[0];
+
+ return ret;
+}
+
+static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint16_t len, bool in_isr) {
+ uint8_t hirq;
+ reg |= CMDBYTE_WRITE;
+
+ max3421_spi_lock(rhport, in_isr);
+
+ tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
+ _hcd_data.hirq = hirq;
+ tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);
+
+ max3421_spi_unlock(rhport, in_isr);
+}
+
+static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) {
+ uint8_t hirq;
+ uint8_t const reg = RCVVFIFO_ADDR;
+
+ max3421_spi_lock(rhport, in_isr);
+
+ tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
+ _hcd_data.hirq = hirq;
+ tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len);
+
+ max3421_spi_unlock(rhport, in_isr);
+}
+
+//------------- register write helper -------------//
+TU_ATTR_ALWAYS_INLINE static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr) {
+ reg_write(rhport, HIRQ_ADDR, data, in_isr);
+ // HIRQ write 1 is clear
+ _hcd_data.hirq &= (uint8_t) ~data;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void hien_write(uint8_t rhport, uint8_t data, bool in_isr) {
+ _hcd_data.hien = data;
+ reg_write(rhport, HIEN_ADDR, data, in_isr);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void mode_write(uint8_t rhport, uint8_t data, bool in_isr) {
+ _hcd_data.mode = data;
+ reg_write(rhport, MODE_ADDR, data, in_isr);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void peraddr_write(uint8_t rhport, uint8_t data, bool in_isr) {
+ if ( _hcd_data.peraddr == data ) return; // no need to change address
+
+ _hcd_data.peraddr = data;
+ reg_write(rhport, PERADDR_ADDR, data, in_isr);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void hxfr_write(uint8_t rhport, uint8_t data, bool in_isr) {
+ _hcd_data.hxfr = data;
+ reg_write(rhport, HXFR_ADDR, data, in_isr);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void sndbc_write(uint8_t rhport, uint8_t data, bool in_isr) {
+ _hcd_data.sndbc = data;
+ reg_write(rhport, SNDBC_ADDR, data, in_isr);
+}
+
+//--------------------------------------------------------------------+
+// Endpoint helper
+//--------------------------------------------------------------------+
+
+static max3421_ep_t* find_ep_not_addr0(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) {
+ uint8_t const is_out = 1-ep_dir;
+ for(size_t i=1; i<CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) {
+ max3421_ep_t* ep = &_hcd_data.ep[i];
+ // control endpoint is bi-direction (skip check)
+ if (daddr == ep->daddr && ep_num == ep->hxfr_bm.ep_num && (ep_num == 0 || is_out == ep->hxfr_bm.is_out)) {
+ return ep;
+ }
+ }
+
+ return NULL;
+}
+
+// daddr = 0 and ep_num = 0 means find a free (allocate) endpoint
+TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * allocate_ep(void) {
+ return find_ep_not_addr0(0, 0, 0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * find_opened_ep(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) {
+ if (daddr == 0 && ep_num == 0) {
+ return &_hcd_data.ep[0];
+ }else{
+ return find_ep_not_addr0(daddr, ep_num, ep_dir);
+ }
+}
+
+// free all endpoints belong to device address
+static void free_ep(uint8_t daddr) {
+ for (size_t i=1; i<CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) {
+ max3421_ep_t* ep = &_hcd_data.ep[i];
+ if (ep->daddr == daddr) {
+ tu_memclr(ep, sizeof(max3421_ep_t));
+ }
+ }
+}
+
+// Check if endpoint has an queued transfer and not reach max NAK
+TU_ATTR_ALWAYS_INLINE static inline bool is_ep_pending(max3421_ep_t const * ep) {
+ uint8_t const state = ep->state;
+ return ep->packet_size && (state >= EP_STATE_ATTEMPT_1) &&
+ (_tuh_cfg.max_nak == 0 || state < EP_STATE_ATTEMPT_1 + _tuh_cfg.max_nak);
+}
+
+// Find the next pending endpoint using round-robin scheduling, starting from next endpoint.
+// return NULL if not found
+// TODO respect interrupt endpoint's interval
+static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) {
+ size_t const idx = (size_t) (cur_ep - _hcd_data.ep);
+
+ // starting from next endpoint
+ for (size_t i = idx + 1; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) {
+ max3421_ep_t* ep = &_hcd_data.ep[i];
+ if (is_ep_pending(ep)) {
+ return ep;
+ }
+ }
+
+ // wrap around including current endpoint
+ for (size_t i = 0; i <= idx; i++) {
+ max3421_ep_t* ep = &_hcd_data.ep[i];
+ if (is_ep_pending(ep)) {
+ return ep;
+ }
+ }
+
+ return NULL;
+}
+
+//--------------------------------------------------------------------+
+// Controller API
+//--------------------------------------------------------------------+
+
+// optional hcd configuration, called by tuh_configure()
+bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
+ (void) rhport;
+ TU_VERIFY(cfg_id == TUH_CFGID_MAX3421 && cfg_param != NULL);
+
+ tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param;
+ _tuh_cfg = cfg->max3421;
+ return true;
+}
+
+// Initialize controller to host mode
+bool hcd_init(uint8_t rhport) {
+ (void) rhport;
+
+ tuh_max3421_int_api(rhport, false);
+
+ TU_LOG2_INT(sizeof(max3421_ep_t));
+ TU_LOG2_INT(sizeof(max3421_data_t));
+ TU_LOG2_INT(offsetof(max3421_data_t, ep));
+
+ tu_memclr(&_hcd_data, sizeof(_hcd_data));
+ _hcd_data.peraddr = 0xff; // invalid
+
+#if OSAL_MUTEX_REQUIRED
+ _hcd_data.spi_mutex = osal_mutex_create(&_hcd_data.spi_mutexdef);
+#endif
+
+ // full duplex, interrupt negative edge
+ reg_write(rhport, PINCTL_ADDR, _tuh_cfg.pinctl | PINCTL_FDUPSPI, false);
+
+ // v1 is 0x01, v2 is 0x12, v3 is 0x13
+ uint8_t const revision = reg_read(rhport, REVISION_ADDR, false);
+ TU_ASSERT(revision == 0x01 || revision == 0x12 || revision == 0x13, false);
+ TU_LOG2_HEX(revision);
+
+ // reset
+ reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false);
+ reg_write(rhport, USBCTL_ADDR, 0, false);
+ while( !(reg_read(rhport, USBIRQ_ADDR, false) & USBIRQ_OSCOK_IRQ) ) {
+ // wait for oscillator to stabilize
+ }
+
+ // Mode: Host and DP/DM pull down
+ mode_write(rhport, MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST, false);
+
+ // frame reset & bus reset, this will trigger CONDET IRQ if device is already connected
+ reg_write(rhport, HCTL_ADDR, HCTL_BUSRST | HCTL_FRMRST, false);
+
+ // clear all previously pending IRQ
+ hirq_write(rhport, 0xff, false);
+
+ // Enable IRQ
+ hien_write(rhport, DEFAULT_HIEN, false);
+
+ tuh_max3421_int_api(rhport, true);
+
+ // Enable Interrupt pin
+ reg_write(rhport, CPUCTL_ADDR, _tuh_cfg.cpuctl | CPUCTL_IE, false);
+
+ return true;
+}
+
+bool hcd_deinit(uint8_t rhport) {
+ (void) rhport;
+
+ // disable interrupt
+ tuh_max3421_int_api(rhport, false);
+
+ // reset max3421 and power down
+ reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false);
+ reg_write(rhport, USBCTL_ADDR, USBCTL_PWRDOWN, false);
+
+ #if OSAL_MUTEX_REQUIRED
+ osal_mutex_delete(_hcd_data.spi_mutex);
+ _hcd_data.spi_mutex = NULL;
+ #endif
+
+ return true;
+}
+
+// Enable USB interrupt
+// Not actually enable GPIO interrupt, just set variable to prevent handler to process
+void hcd_int_enable (uint8_t rhport) {
+ tuh_max3421_int_api(rhport, true);
+}
+
+// Disable USB interrupt
+// Not actually disable GPIO interrupt, just set variable to prevent handler to process
+void hcd_int_disable(uint8_t rhport) {
+ tuh_max3421_int_api(rhport, false);
+}
+
+// Get frame number (1ms)
+uint32_t hcd_frame_number(uint8_t rhport) {
+ (void) rhport;
+ return (uint32_t ) _hcd_data.frame_count;
+}
+
+//--------------------------------------------------------------------+
+// Port API
+//--------------------------------------------------------------------+
+
+// Get the current connect status of roothub port
+bool hcd_port_connect_status(uint8_t rhport) {
+ (void) rhport;
+ return (_hcd_data.mode & MODE_SOFKAENAB) ? true : false;
+}
+
+// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete.
+// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence.
+void hcd_port_reset(uint8_t rhport) {
+ reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, false);
+}
+
+// Complete bus reset sequence, may be required by some controllers
+void hcd_port_reset_end(uint8_t rhport) {
+ reg_write(rhport, HCTL_ADDR, 0, false);
+}
+
+// Get port link speed
+tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
+ (void) rhport;
+ return (_hcd_data.mode & MODE_LOWSPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL;
+}
+
+// HCD closes all opened endpoints belong to this device
+void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
+ (void) rhport;
+ (void) dev_addr;
+}
+
+//--------------------------------------------------------------------+
+// Endpoints API
+//--------------------------------------------------------------------+
+
+// Open an endpoint
+bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc) {
+ (void) rhport;
+
+ uint8_t const ep_num = tu_edpt_number(ep_desc->bEndpointAddress);
+ tusb_dir_t const ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress);
+
+ max3421_ep_t * ep;
+ if (daddr == 0 && ep_num == 0) {
+ ep = &_hcd_data.ep[0];
+ }else {
+ ep = allocate_ep();
+ TU_ASSERT(ep);
+ ep->daddr = daddr;
+ ep->hxfr_bm.ep_num = (uint8_t) (ep_num & 0x0f);
+ ep->hxfr_bm.is_out = (ep_dir == TUSB_DIR_OUT) ? 1 : 0;
+ ep->hxfr_bm.is_iso = (TUSB_XFER_ISOCHRONOUS == ep_desc->bmAttributes.xfer) ? 1 : 0;
+ }
+
+ ep->packet_size = (uint16_t) (tu_edpt_packet_size(ep_desc) & 0x7ff);
+
+ return true;
+}
+
+static void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) {
+ // Page 12: Programming BULK-OUT Transfers
+ // TODO double buffered
+ if (switch_ep) {
+ peraddr_write(rhport, ep->daddr, in_isr);
+
+ uint8_t const hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0);
+ reg_write(rhport, HCTL_ADDR, hctl, in_isr);
+ }
+
+ uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size);
+ TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,);
+ if (xact_len) {
+ fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr);
+ }
+ sndbc_write(rhport, xact_len, in_isr);
+ hxfr_write(rhport, ep->hxfr, in_isr);
+}
+
+static void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) {
+ // Page 13: Programming BULK-IN Transfers
+ if (switch_ep) {
+ peraddr_write(rhport, ep->daddr, in_isr);
+
+ uint8_t const hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0);
+ reg_write(rhport, HCTL_ADDR, hctl, in_isr);
+ }
+
+ hxfr_write(rhport, ep->hxfr, in_isr);
+}
+
+static void xact_setup(uint8_t rhport, max3421_ep_t *ep, bool in_isr) {
+ peraddr_write(rhport, ep->daddr, in_isr);
+ fifo_write(rhport, SUDFIFO_ADDR, ep->buf, 8, in_isr);
+ hxfr_write(rhport, HXFR_SETUP, in_isr);
+}
+
+static void xact_generic(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) {
+ if (ep->hxfr_bm.ep_num == 0 ) {
+ // setup
+ if (ep->hxfr_bm.is_setup) {
+ xact_setup(rhport, ep, in_isr);
+ return;
+ }
+
+ // status
+ if (ep->buf == NULL || ep->total_len == 0) {
+ uint8_t const hxfr = (uint8_t) (HXFR_HS | (ep->hxfr & HXFR_OUT_NIN));
+ peraddr_write(rhport, ep->daddr, in_isr);
+ hxfr_write(rhport, hxfr, in_isr);
+ return;
+ }
+ }
+
+ if (ep->hxfr_bm.is_out) {
+ xact_out(rhport, ep, switch_ep, in_isr);
+ }else {
+ xact_in(rhport, ep, switch_ep, in_isr);
+ }
+}
+
+// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) {
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ uint8_t const ep_dir = (uint8_t) tu_edpt_dir(ep_addr);
+
+ max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir);
+ TU_VERIFY(ep);
+
+ if (ep_num == 0) {
+ // control transfer can switch direction
+ ep->hxfr_bm.is_out = ep_dir ? 0 : 1;
+ ep->hxfr_bm.is_setup = 0;
+ ep->data_toggle = 1;
+ }
+
+ ep->buf = buffer;
+ ep->total_len = buflen;
+ ep->xferred_len = 0;
+ ep->state = EP_STATE_ATTEMPT_1;
+
+ // carry out transfer if not busy
+ if (!atomic_flag_test_and_set(&_hcd_data.busy)) {
+ xact_generic(rhport, ep, true, false);
+ }
+
+ return true;
+}
+
+// Abort a queued transfer. Note: it can only abort transfer that has not been started
+// Return true if a queued transfer is aborted, false if there is no transfer to abort
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+
+ return false;
+}
+
+// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked
+bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]) {
+ (void) rhport;
+
+ max3421_ep_t* ep = find_opened_ep(daddr, 0, 0);
+ TU_ASSERT(ep);
+
+ ep->hxfr_bm.is_out = 1;
+ ep->hxfr_bm.is_setup = 1;
+ ep->buf = (uint8_t*)(uintptr_t) setup_packet;
+ ep->total_len = 8;
+ ep->xferred_len = 0;
+ ep->state = EP_STATE_ATTEMPT_1;
+
+ // carry out transfer if not busy
+ if (!atomic_flag_test_and_set(&_hcd_data.busy)) {
+ xact_setup(rhport, ep, false);
+ }
+
+ return true;
+}
+
+// clear stall, data toggle is also reset to DATA0
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+
+ return false;
+}
+
+//--------------------------------------------------------------------+
+// Interrupt Handler
+//--------------------------------------------------------------------+
+
+static void handle_connect_irq(uint8_t rhport, bool in_isr) {
+ uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, in_isr);
+ uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS);
+
+ uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST;
+ TU_LOG2_HEX(jk);
+
+ switch(jk) {
+ case 0x00: // SEO is disconnected
+ case (HRSL_JSTATUS | HRSL_KSTATUS): // SE1 is illegal
+ mode_write(rhport, new_mode, in_isr);
+
+ // port reset anyway, this will help to stable bus signal for next connection
+ reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, in_isr);
+ hcd_event_device_remove(rhport, in_isr);
+ reg_write(rhport, HCTL_ADDR, 0, in_isr);
+ break;
+
+ default: {
+ // Bus Reset also cause CONDET IRQ, skip if we are already connected and doing bus reset
+ if ((_hcd_data.hirq & HIRQ_BUSEVENT_IRQ) && (_hcd_data.mode & MODE_SOFKAENAB)) {
+ break;
+ }
+
+ // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State)
+ // However, since we are always in full speed mode, we can just check J-state
+ if (jk == HRSL_KSTATUS) {
+ new_mode |= MODE_LOWSPEED;
+ TU_LOG3("Low speed\r\n");
+ }else {
+ TU_LOG3("Full speed\r\n");
+ }
+ new_mode |= MODE_SOFKAENAB;
+ mode_write(rhport, new_mode, in_isr);
+
+ // FIXME multiple MAX3421 rootdevice address is not 1
+ uint8_t const daddr = 1;
+ free_ep(daddr);
+
+ hcd_event_device_attach(rhport, in_isr);
+ break;
+ }
+ }
+}
+
+static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl, bool in_isr) {
+ uint8_t const ep_dir = 1-ep->hxfr_bm.is_out;
+ uint8_t const ep_addr = tu_edpt_addr(ep->hxfr_bm.ep_num, ep_dir);
+
+ // save data toggle
+ if (ep_dir) {
+ ep->data_toggle = (hrsl & HRSL_RCVTOGRD) ? 1u : 0u;
+ }else {
+ ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1u : 0u;
+ }
+
+ ep->state = EP_STATE_IDLE;
+ hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, in_isr);
+
+ // Find next pending endpoint
+ max3421_ep_t * next_ep = find_next_pending_ep(ep);
+ if (next_ep) {
+ xact_generic(rhport, next_ep, true, in_isr);
+ }else {
+ // no more pending
+ atomic_flag_clear(&_hcd_data.busy);
+ }
+}
+
+static void handle_xfer_done(uint8_t rhport, bool in_isr) {
+ uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, in_isr);
+ uint8_t const hresult = hrsl & HRSL_RESULT_MASK;
+
+ uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
+ uint8_t const hxfr_type = _hcd_data.hxfr & 0xf0;
+ uint8_t const ep_dir = ((hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN)) ? 0 : 1;
+
+ max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, ep_dir);
+ TU_VERIFY(ep, );
+
+ xfer_result_t xfer_result;
+ switch(hresult) {
+ case HRSL_SUCCESS:
+ xfer_result = XFER_RESULT_SUCCESS;
+ break;
+
+ case HRSL_STALL:
+ xfer_result = XFER_RESULT_STALLED;
+ break;
+
+ case HRSL_NAK:
+ if (ep_num == 0) {
+ // control endpoint -> retry immediately
+ hxfr_write(rhport, _hcd_data.hxfr, in_isr);
+ } else {
+ if (ep->state < EP_STATE_ATTEMPT_MAX) {
+ ep->state++;
+ }
+
+ max3421_ep_t * next_ep = find_next_pending_ep(ep);
+ if (ep == next_ep) {
+ // this endpoint is only one pending -> retry immediately
+ hxfr_write(rhport, _hcd_data.hxfr, in_isr);
+ } else if (next_ep) {
+ // switch to next pending endpoint TODO could have issue with double buffered if not clear previously out data
+ xact_generic(rhport, next_ep, true, in_isr);
+ } else {
+ // no more pending in this frame -> clear busy
+ atomic_flag_clear(&_hcd_data.busy);
+ }
+ }
+ return;
+
+ case HRSL_BAD_REQ:
+ // occurred when initialized without any pending transfer. Skip for now
+ return;
+
+ default:
+ TU_LOG3("HRSL: %02X\r\n", hrsl);
+ xfer_result = XFER_RESULT_FAILED;
+ break;
+ }
+
+ if (xfer_result != XFER_RESULT_SUCCESS) {
+ xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
+ return;
+ }
+
+ if (ep_dir) {
+ // IN transfer: fifo data is already received in RCVDAV IRQ
+
+ // mark control handshake as complete
+ if (hxfr_type & HXFR_HS) {
+ ep->state = EP_STATE_COMPLETE;
+ }
+
+ // short packet or all bytes transferred
+ if (ep->state == EP_STATE_COMPLETE) {
+ xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
+ }else {
+ // more to transfer
+ hxfr_write(rhport, _hcd_data.hxfr, in_isr);
+ }
+ } else {
+ // SETUP or OUT transfer
+ uint8_t xact_len;
+
+ if (hxfr_type & HXFR_SETUP) {
+ xact_len = 8;
+ } else if (hxfr_type & HXFR_HS) {
+ xact_len = 0;
+ } else {
+ xact_len = _hcd_data.sndbc;
+ }
+
+ ep->xferred_len += xact_len;
+ ep->buf += xact_len;
+
+ if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) {
+ xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
+ } else {
+ // more to transfer
+ xact_out(rhport, ep, false, in_isr);
+ }
+ }
+}
+
+#if CFG_TUSB_DEBUG >= 3
+void print_hirq(uint8_t hirq) {
+ TU_LOG3_HEX(hirq);
+
+ if (hirq & HIRQ_HXFRDN_IRQ) TU_LOG3(" HXFRDN");
+ if (hirq & HIRQ_FRAME_IRQ) TU_LOG3(" FRAME");
+ if (hirq & HIRQ_CONDET_IRQ) TU_LOG3(" CONDET");
+ if (hirq & HIRQ_SUSDN_IRQ) TU_LOG3(" SUSDN");
+ if (hirq & HIRQ_SNDBAV_IRQ) TU_LOG3(" SNDBAV");
+ if (hirq & HIRQ_RCVDAV_IRQ) TU_LOG3(" RCVDAV");
+ if (hirq & HIRQ_RWU_IRQ) TU_LOG3(" RWU");
+ if (hirq & HIRQ_BUSEVENT_IRQ) TU_LOG3(" BUSEVENT");
+
+ TU_LOG3("\r\n");
+}
+#else
+ #define print_hirq(hirq)
+#endif
+
+// Interrupt handler
+void hcd_int_handler(uint8_t rhport, bool in_isr) {
+ uint8_t hirq = reg_read(rhport, HIRQ_ADDR, in_isr) & _hcd_data.hien;
+ if (!hirq) return;
+// print_hirq(hirq);
+
+ if (hirq & HIRQ_FRAME_IRQ) {
+ _hcd_data.frame_count++;
+
+ max3421_ep_t* ep_retry = NULL;
+
+ // reset all endpoints attempt counter
+ for (size_t i = 0; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) {
+ max3421_ep_t* ep = &_hcd_data.ep[i];
+ if (ep->packet_size && ep->state > EP_STATE_ATTEMPT_1) {
+ ep->state = EP_STATE_ATTEMPT_1;
+
+ if (ep_retry == NULL) {
+ ep_retry = ep;
+ }
+ }
+ }
+
+ // start usb transfer if not busy
+ if (ep_retry != NULL && !atomic_flag_test_and_set(&_hcd_data.busy)) {
+ xact_generic(rhport, ep_retry, true, in_isr);
+ }
+ }
+
+ if (hirq & HIRQ_CONDET_IRQ) {
+ handle_connect_irq(rhport, in_isr);
+ }
+
+ // queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or
+ // not call this handler again. So we need to loop until all IRQ are cleared
+ while (hirq & (HIRQ_RCVDAV_IRQ | HIRQ_HXFRDN_IRQ)) {
+ if (hirq & HIRQ_RCVDAV_IRQ) {
+ uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
+ max3421_ep_t* ep = find_opened_ep(_hcd_data.peraddr, ep_num, 1);
+ uint8_t xact_len = 0;
+
+ // RCVDAV_IRQ can trigger 2 times (dual buffered)
+ while (hirq & HIRQ_RCVDAV_IRQ) {
+ uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, in_isr);
+ xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len);
+ if (xact_len) {
+ fifo_read(rhport, ep->buf, xact_len, in_isr);
+ ep->buf += xact_len;
+ ep->xferred_len += xact_len;
+ }
+
+ // ack RCVDVAV IRQ
+ hirq_write(rhport, HIRQ_RCVDAV_IRQ, in_isr);
+ hirq = reg_read(rhport, HIRQ_ADDR, in_isr);
+ }
+
+ if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) {
+ ep->state = EP_STATE_COMPLETE;
+ }
+ }
+
+ if (hirq & HIRQ_HXFRDN_IRQ) {
+ hirq_write(rhport, HIRQ_HXFRDN_IRQ, in_isr);
+ handle_xfer_done(rhport, in_isr);
+ }
+
+ hirq = reg_read(rhport, HIRQ_ADDR, in_isr);
+ }
+
+ // clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing
+ hirq &= (uint8_t) ~HIRQ_SNDBAV_IRQ;
+ if ( hirq ) {
+ hirq_write(rhport, hirq, in_isr);
+ }
+}
+
+#endif
diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c
index 95dfda49c..f02415904 100644
--- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c
+++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c
@@ -51,7 +51,7 @@ extern int8_t board_ft9xx_vbus(void);
extern int board_uart_write(void const *buf, int len);
// Static array to store an incoming SETUP request for processing by tinyusb.
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN
+CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN
static uint8_t _ft9xx_setup_packet[8];
struct ft9xx_xfer_state
diff --git a/src/portable/chipidea/ci_fs/ci_fs_kinetis.h b/src/portable/chipidea/ci_fs/ci_fs_kinetis.h
new file mode 100644
index 000000000..31e14a546
--- /dev/null
+++ b/src/portable/chipidea/ci_fs/ci_fs_kinetis.h
@@ -0,0 +1,49 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _CI_FS_KINETIS_H
+#define _CI_FS_KINETIS_H
+
+#include "fsl_device_registers.h"
+
+//static const ci_fs_controller_t _ci_controller[] = {
+// {.reg_base = USB0_BASE, .irqnum = USB0_IRQn}
+//};
+
+#define CI_FS_REG(_port) ((ci_fs_regs_t*) USB0_BASE)
+#define CI_REG CI_FS_REG(0)
+
+void dcd_int_enable(uint8_t rhport) {
+ (void) rhport;
+ NVIC_EnableIRQ(USB0_IRQn);
+}
+
+void dcd_int_disable(uint8_t rhport) {
+ (void) rhport;
+ NVIC_DisableIRQ(USB0_IRQn);
+}
+
+#endif
diff --git a/src/common/tusb_timeout.h b/src/portable/chipidea/ci_fs/ci_fs_mcx.h
index 533e67ab8..4b93a03a7 100644
--- a/src/common/tusb_timeout.h
+++ b/src/portable/chipidea/ci_fs/ci_fs_mcx.h
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,57 +24,33 @@
* This file is part of the TinyUSB stack.
*/
-/** \ingroup Group_Common Common Files
- * \defgroup Group_TimeoutTimer timeout timer
- * @{ */
+#ifndef _CI_FS_MCX_H
+#define _CI_FS_MCX_H
-#ifndef _TUSB_TIMEOUT_H_
-#define _TUSB_TIMEOUT_H_
+#include "fsl_device_registers.h"
-#include <stdbool.h>
-#include <stdint.h>
+#if CFG_TUSB_MCU == OPT_MCU_MCXN9
+ #define CI_FS_REG(_port) ((ci_fs_regs_t*) USBFS0_BASE)
+ #define CIFS_IRQN USB0_FS_IRQn
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
- uint32_t start;
- uint32_t interval;
-}tu_timeout_t;
-
-#if 0
+#elif CFG_TUSB_MCU == OPT_MCU_MCXA15
+ #define CI_FS_REG(_port) ((ci_fs_regs_t*) USB0_BASE)
+ #define CIFS_IRQN USB0_IRQn
-extern uint32_t tusb_hal_millis(void);
+#else
+ #error "MCU is not supported"
+#endif
-static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec)
-{
- tt->interval = msec;
- tt->start = tusb_hal_millis();
-}
+#define CI_REG CI_FS_REG(0)
-static inline bool tu_timeout_expired(tu_timeout_t* tt)
-{
- return ( tusb_hal_millis() - tt->start ) >= tt->interval;
+void dcd_int_enable(uint8_t rhport) {
+ (void) rhport;
+ NVIC_EnableIRQ(CIFS_IRQN);
}
-// For used with periodic event to prevent drift
-static inline void tu_timeout_reset(tu_timeout_t* tt)
-{
- tt->start += tt->interval;
+void dcd_int_disable(uint8_t rhport) {
+ (void) rhport;
+ NVIC_DisableIRQ(CIFS_IRQN);
}
-static inline void tu_timeout_restart(tu_timeout_t* tt)
-{
- tt->start = tusb_hal_millis();
-}
-
-#endif
-
-#ifdef __cplusplus
- }
#endif
-
-#endif /* _TUSB_TIMEOUT_H_ */
-
-/** @} */
diff --git a/src/portable/chipidea/ci_fs/ci_fs_type.h b/src/portable/chipidea/ci_fs/ci_fs_type.h
new file mode 100644
index 000000000..5a5e53fb0
--- /dev/null
+++ b/src/portable/chipidea/ci_fs/ci_fs_type.h
@@ -0,0 +1,118 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _CI_FS_TYPE_H
+#define _CI_FS_TYPE_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+// Note: some MCUs can only access these registers in 8-bit mode
+// align 4 is used to get rid of reserved fields
+#define _va32 volatile TU_ATTR_ALIGNED(4)
+
+typedef struct {
+ _va32 uint8_t PER_ID; // [00] Peripheral ID register
+ _va32 uint8_t ID_COMP; // [04] Peripheral ID complement register
+ _va32 uint8_t REV; // [08] Peripheral revision register
+ _va32 uint8_t ADD_INFO; // [0C] Peripheral additional info register
+ _va32 uint8_t OTG_ISTAT; // [10] OTG Interrupt Status Register
+ _va32 uint8_t OTG_ICTRL; // [14] OTG Interrupt Control Register
+ _va32 uint8_t OTG_STAT; // [18] OTG Status Register
+ _va32 uint8_t OTG_CTRL; // [1C] OTG Control register
+ uint32_t reserved_20[24]; // [20]
+ _va32 uint8_t INT_STAT; // [80] Interrupt status register
+ _va32 uint8_t INT_EN; // [84] Interrupt enable register
+ _va32 uint8_t ERR_STAT; // [88] Error interrupt status register
+ _va32 uint8_t ERR_ENB; // [8C] Error interrupt enable register
+ _va32 uint8_t STAT; // [90] Status register
+ _va32 uint8_t CTL; // [94] Control register
+ _va32 uint8_t ADDR; // [98] Address register
+ _va32 uint8_t BDT_PAGE1; // [9C] BDT page register 1
+ _va32 uint8_t FRM_NUML; // [A0] Frame number register
+ _va32 uint8_t FRM_NUMH; // [A4] Frame number register
+ _va32 uint8_t TOKEN; // [A8] Token register
+ _va32 uint8_t SOF_THLD; // [AC] SOF threshold register
+ _va32 uint8_t BDT_PAGE2; // [B0] BDT page register 2
+ _va32 uint8_t BDT_PAGE3; // [B4] BDT page register 3
+
+ uint32_t reserved_b8; // [B8]
+ uint32_t reserved_bc; // [BC]
+
+ struct {
+ _va32 uint8_t CTL;
+ }EP[16]; // [C0] Endpoint control register
+
+ //----- Following is only found available in NXP Kinetis
+ _va32 uint8_t USBCTRL; // [100] USB Control register,
+ _va32 uint8_t OBSERVE; // [104] USB OTG Observe register,
+ _va32 uint8_t CONTROL; // [108] USB OTG Control register,
+ _va32 uint8_t USBTRC0; // [10C] USB Transceiver Control Register 0,
+ uint32_t reserved_110; // [110]
+ _va32 uint8_t USBFRMADJUST; // [114] Frame Adjust Register,
+
+ //----- Following is only found available in NXP MCX
+ uint32_t reserved_118[3]; // [118]
+ _va32 uint8_t KEEP_ALIVE_CTRL; // [124] Keep Alive Mode Control,
+ _va32 uint8_t KEEP_ALIVE_WKCTRL; // [128] Keep Alive Mode Wakeup Control,
+ _va32 uint8_t MISCCTRL; // [12C] Miscellaneous Control,
+ _va32 uint8_t STALL_IL_DIS; // [130] Peripheral Mode Stall Disable for Endpoints[ 7..0] IN
+ _va32 uint8_t STALL_IH_DIS; // [134] Peripheral Mode Stall Disable for Endpoints[15..8] IN
+ _va32 uint8_t STALL_OL_DIS; // [138] Peripheral Mode Stall Disable for Endpoints[ 7..0] OUT
+ _va32 uint8_t STALL_OH_DIS; // [13C] Peripheral Mode Stall Disable for Endpoints[15..8] OUT
+ _va32 uint8_t CLK_RECOVER_CTRL; // [140] USB Clock Recovery Control,
+ _va32 uint8_t CLK_RECOVER_IRC_EN; // [144] FIRC Oscillator Enable,
+ uint32_t reserved_148[3]; // [148]
+ _va32 uint8_t CLK_RECOVER_INT_EN; // [154] Clock Recovery Combined Interrupt Enable,
+ uint32_t reserved_158; // [158]
+ _va32 uint8_t CLK_RECOVER_INT_STATUS; // [15C] Clock Recovery Separated Interrupt Status,
+} ci_fs_regs_t;
+
+TU_VERIFY_STATIC(sizeof(ci_fs_regs_t) == 0x160, "Size is not correct");
+
+typedef struct
+{
+ uint32_t reg_base;
+ uint32_t irqnum;
+} ci_fs_controller_t;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c
new file mode 100644
index 000000000..02f813ab5
--- /dev/null
+++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c
@@ -0,0 +1,567 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Koji Kitayama
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+#if CFG_TUD_ENABLED && defined(TUP_USBIP_CHIPIDEA_FS)
+
+#include "device/dcd.h"
+#include "ci_fs_type.h"
+
+#if defined(TUP_USBIP_CHIPIDEA_FS_KINETIS)
+ #include "ci_fs_kinetis.h"
+#elif defined(TUP_USBIP_CHIPIDEA_FS_MCX)
+ #include "ci_fs_mcx.h"
+#else
+ #error "MCU is not supported"
+#endif
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+
+enum {
+ TOK_PID_OUT = 0x1u,
+ TOK_PID_IN = 0x9u,
+ TOK_PID_SETUP = 0xDu,
+};
+
+typedef struct TU_ATTR_PACKED
+{
+ union {
+ uint32_t head;
+ struct {
+ union {
+ struct {
+ uint16_t : 2;
+ __IO uint16_t tok_pid : 4;
+ uint16_t data : 1;
+ __IO uint16_t own : 1;
+ uint16_t : 8;
+ };
+ struct {
+ uint16_t : 2;
+ uint16_t bdt_stall : 1;
+ uint16_t dts : 1;
+ uint16_t ninc : 1;
+ uint16_t keep : 1;
+ uint16_t : 10;
+ };
+ };
+ __IO uint16_t bc : 10;
+ uint16_t : 6;
+ };
+ };
+ uint8_t *addr;
+}buffer_descriptor_t;
+
+TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" );
+
+typedef struct TU_ATTR_PACKED
+{
+ union {
+ uint32_t state;
+ struct {
+ uint32_t max_packet_size :11;
+ uint32_t : 5;
+ uint32_t odd : 1;
+ uint32_t :15;
+ };
+ };
+ uint16_t length;
+ uint16_t remaining;
+}endpoint_state_t;
+
+TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" );
+
+typedef struct
+{
+ union {
+ /* [#EP][OUT,IN][EVEN,ODD] */
+ buffer_descriptor_t bdt[16][2][2];
+ uint16_t bda[512];
+ };
+ TU_ATTR_ALIGNED(4) union {
+ endpoint_state_t endpoint[16][2];
+ endpoint_state_t endpoint_unified[16 * 2];
+ };
+ uint8_t setup_packet[8];
+ uint8_t addr;
+}dcd_data_t;
+
+//--------------------------------------------------------------------+
+// INTERNAL OBJECT & FUNCTION DECLARATION
+//--------------------------------------------------------------------+
+// BDT(Buffer Descriptor Table) must be 256-byte aligned
+CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd;
+
+TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" );
+
+static void prepare_next_setup_packet(uint8_t rhport)
+{
+ const unsigned out_odd = _dcd.endpoint[0][0].odd;
+ const unsigned in_odd = _dcd.endpoint[0][1].odd;
+ TU_ASSERT(0 == _dcd.bdt[0][0][out_odd].own, );
+
+ _dcd.bdt[0][0][out_odd].data = 0;
+ _dcd.bdt[0][0][out_odd ^ 1].data = 1;
+ _dcd.bdt[0][1][in_odd].data = 1;
+ _dcd.bdt[0][1][in_odd ^ 1].data = 0;
+ dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT),
+ _dcd.setup_packet, sizeof(_dcd.setup_packet));
+}
+
+static void process_stall(uint8_t rhport)
+{
+ for (int i = 0; i < 16; ++i) {
+ uint32_t const ep_ctl = CI_REG->EP[i].CTL;
+
+ if (ep_ctl & USB_ENDPT_EPSTALL_MASK) {
+ // prepare next setup if endpoint0
+ if ( i == 0 ) prepare_next_setup_packet(rhport);
+
+ // clear stall bit
+ CI_REG->EP[i].CTL = ep_ctl & ~USB_ENDPT_EPSTALL_MASK;
+ }
+ }
+}
+
+static void process_tokdne(uint8_t rhport)
+{
+ const unsigned s = CI_REG->STAT;
+ CI_REG->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */
+
+ uint8_t const epnum = (s >> USB_STAT_ENDP_SHIFT);
+ uint8_t const dir = (s & USB_STAT_TX_MASK) >> USB_STAT_TX_SHIFT;
+ unsigned const odd = (s & USB_STAT_ODD_MASK) ? 1 : 0;
+
+ buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s];
+ endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3];
+
+ /* fetch pid before discarded by the next steps */
+ const unsigned pid = bd->tok_pid;
+
+ /* reset values for a next transfer */
+ bd->bdt_stall = 0;
+ bd->dts = 1;
+ bd->ninc = 0;
+ bd->keep = 0;
+ /* update the odd variable to prepare for the next transfer */
+ ep->odd = odd ^ 1;
+ if (pid == TOK_PID_SETUP) {
+ dcd_event_setup_received(rhport, bd->addr, true);
+ CI_REG->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
+ return;
+ }
+
+ const unsigned bc = bd->bc;
+ const unsigned remaining = ep->remaining - bc;
+ if (remaining && bc == ep->max_packet_size) {
+ /* continue the transferring consecutive data */
+ ep->remaining = remaining;
+ const int next_remaining = remaining - ep->max_packet_size;
+ if (next_remaining > 0) {
+ /* prepare to the after next transfer */
+ bd->addr += ep->max_packet_size * 2;
+ bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining;
+ __DSB();
+ bd->own = 1; /* the own bit must set after addr */
+ }
+ return;
+ }
+ const unsigned length = ep->length;
+ dcd_event_xfer_complete(rhport,
+ tu_edpt_addr(epnum, dir),
+ length - remaining, XFER_RESULT_SUCCESS, true);
+ if (0 == epnum && 0 == length) {
+ /* After completion a ZLP of control transfer,
+ * it prepares for the next steup transfer. */
+ if (_dcd.addr) {
+ /* When the transfer was the SetAddress,
+ * the device address should be updated here. */
+ CI_REG->ADDR = _dcd.addr;
+ _dcd.addr = 0;
+ }
+ prepare_next_setup_packet(rhport);
+ }
+}
+
+static void process_bus_reset(uint8_t rhport)
+{
+ CI_REG->USBCTRL &= ~USB_USBCTRL_SUSP_MASK;
+ CI_REG->CTL |= USB_CTL_ODDRST_MASK;
+ CI_REG->ADDR = 0;
+ CI_REG->INT_EN = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | USB_INTEN_SLEEPEN_MASK |
+ USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK;
+
+ CI_REG->EP[0].CTL = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK;
+ for (unsigned i = 1; i < 16; ++i) {
+ CI_REG->EP[i].CTL = 0;
+ }
+ buffer_descriptor_t *bd = _dcd.bdt[0][0];
+ for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) {
+ bd->head = 0;
+ }
+ const endpoint_state_t ep0 = {
+ .max_packet_size = CFG_TUD_ENDPOINT0_SIZE,
+ .odd = 0,
+ .length = 0,
+ .remaining = 0,
+ };
+ _dcd.endpoint[0][0] = ep0;
+ _dcd.endpoint[0][1] = ep0;
+ tu_memclr(_dcd.endpoint[1], sizeof(_dcd.endpoint) - sizeof(_dcd.endpoint[0]));
+ _dcd.addr = 0;
+ prepare_next_setup_packet(rhport);
+ CI_REG->CTL &= ~USB_CTL_ODDRST_MASK;
+ dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true);
+}
+
+static void process_bus_sleep(uint8_t rhport)
+{
+ // Enable resume & disable suspend interrupt
+ const unsigned inten = CI_REG->INT_EN;
+
+ CI_REG->INT_EN = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK;
+ CI_REG->USBTRC0 |= USB_USBTRC0_USBRESMEN_MASK;
+ CI_REG->USBCTRL |= USB_USBCTRL_SUSP_MASK;
+
+ dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
+}
+
+static void process_bus_resume(uint8_t rhport)
+{
+ // Enable suspend & disable resume interrupt
+ const unsigned inten = CI_REG->INT_EN;
+
+ CI_REG->USBCTRL &= ~USB_USBCTRL_SUSP_MASK; // will also clear USB_USBTRC0_USB_RESUME_INT_MASK
+ CI_REG->USBTRC0 &= ~USB_USBTRC0_USBRESMEN_MASK;
+ CI_REG->INT_EN = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK;
+
+ dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
+}
+
+/*------------------------------------------------------------------*/
+/* Device API
+ *------------------------------------------------------------------*/
+void dcd_init(uint8_t rhport)
+{
+ (void) rhport;
+
+ // save crystal-less setting (if available)
+ #if defined(FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED) && FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED == 1
+ uint32_t clk_recover_irc_en = CI_REG->CLK_RECOVER_IRC_EN;
+ uint32_t clk_recover_ctrl = CI_REG->CLK_RECOVER_CTRL;
+ #endif
+
+ CI_REG->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
+ while (CI_REG->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
+
+ // restore crystal-less setting (if available)
+ #if defined(FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED) && FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED == 1
+ CI_REG->CLK_RECOVER_IRC_EN = clk_recover_irc_en;
+ CI_REG->CLK_RECOVER_CTRL |= clk_recover_ctrl;
+ #endif
+
+ tu_memclr(&_dcd, sizeof(_dcd));
+ CI_REG->USBTRC0 |= TU_BIT(6); /* software must set this bit to 1 */
+ CI_REG->BDT_PAGE1 = (uint8_t)((uintptr_t)_dcd.bdt >> 8);
+ CI_REG->BDT_PAGE2 = (uint8_t)((uintptr_t)_dcd.bdt >> 16);
+ CI_REG->BDT_PAGE3 = (uint8_t)((uintptr_t)_dcd.bdt >> 24);
+
+ CI_REG->INT_EN = USB_INTEN_USBRSTEN_MASK;
+
+ dcd_connect(rhport);
+ // NVIC_ClearPendingIRQ(CIFS_IRQN);
+}
+
+void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
+{
+ _dcd.addr = dev_addr & 0x7F;
+ /* Response with status first before changing device address */
+ dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
+}
+
+void dcd_remote_wakeup(uint8_t rhport)
+{
+ (void) rhport;
+
+ CI_REG->CTL |= USB_CTL_RESUME_MASK;
+
+ unsigned cnt = SystemCoreClock / 1000;
+ while (cnt--) __NOP();
+
+ CI_REG->CTL &= ~USB_CTL_RESUME_MASK;
+}
+
+void dcd_connect(uint8_t rhport)
+{
+ (void) rhport;
+ CI_REG->USBCTRL = 0;
+ CI_REG->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK;
+ CI_REG->CTL |= USB_CTL_USBENSOFEN_MASK;
+}
+
+void dcd_disconnect(uint8_t rhport)
+{
+ (void) rhport;
+ CI_REG->CTL = 0;
+ CI_REG->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
+}
+
+void dcd_sof_enable(uint8_t rhport, bool en)
+{
+ (void) rhport;
+ (void) en;
+
+ // TODO implement later
+}
+
+//--------------------------------------------------------------------+
+// Endpoint API
+//--------------------------------------------------------------------+
+bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
+{
+ (void) rhport;
+
+ const unsigned ep_addr = ep_desc->bEndpointAddress;
+ const unsigned epn = tu_edpt_number(ep_addr);
+ const unsigned dir = tu_edpt_dir(ep_addr);
+ const unsigned xfer = ep_desc->bmAttributes.xfer;
+ endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
+ const unsigned odd = ep->odd;
+ buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
+
+ /* No support for control transfer */
+ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL));
+
+ ep->max_packet_size = tu_edpt_packet_size(ep_desc);
+ unsigned val = USB_ENDPT_EPCTLDIS_MASK;
+ val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0;
+ val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK;
+ CI_REG->EP[epn].CTL |= val;
+
+ if (xfer != TUSB_XFER_ISOCHRONOUS) {
+ bd[odd].dts = 1;
+ bd[odd].data = 0;
+ bd[odd ^ 1].dts = 1;
+ bd[odd ^ 1].data = 1;
+ }
+
+ return true;
+}
+
+void dcd_edpt_close_all(uint8_t rhport)
+{
+ dcd_int_disable(rhport);
+
+ for (unsigned i = 1; i < 16; ++i) {
+ CI_REG->EP[i].CTL = 0;
+ }
+
+ dcd_int_enable(rhport);
+
+ buffer_descriptor_t *bd = _dcd.bdt[1][0];
+ for (unsigned i = 2; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) {
+ bd->head = 0;
+ }
+
+ endpoint_state_t *ep = &_dcd.endpoint[1][0];
+ for (unsigned i = 2; i < sizeof(_dcd.endpoint)/sizeof(*ep); ++i, ++ep) {
+ /* Clear except the odd */
+ ep->max_packet_size = 0;
+ ep->length = 0;
+ ep->remaining = 0;
+ }
+}
+
+void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
+{
+ const unsigned epn = tu_edpt_number(ep_addr);
+ const unsigned dir = tu_edpt_dir(ep_addr);
+ endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
+ buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
+ const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK;
+
+ dcd_int_disable(rhport);
+
+ CI_REG->EP[epn].CTL &= ~msk;
+ ep->max_packet_size = 0;
+ ep->length = 0;
+ ep->remaining = 0;
+ bd[0].head = 0;
+ bd[1].head = 0;
+
+ dcd_int_enable(rhport);
+}
+
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
+{
+ const unsigned epn = tu_edpt_number(ep_addr);
+ const unsigned dir = tu_edpt_dir(ep_addr);
+ endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
+ buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd];
+ TU_ASSERT(0 == bd->own);
+
+ dcd_int_disable(rhport);
+
+ ep->length = total_bytes;
+ ep->remaining = total_bytes;
+
+ const unsigned mps = ep->max_packet_size;
+ if (total_bytes > mps) {
+ buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1;
+ /* When total_bytes is greater than the max packet size,
+ * it prepares to the next transfer to avoid NAK in advance. */
+ next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps;
+ next->addr = buffer + mps;
+ next->own = 1;
+ }
+ bd->bc = total_bytes >= mps ? mps: total_bytes;
+ bd->addr = buffer;
+ __DSB();
+ bd->own = 1; /* This bit must be set last */
+
+ dcd_int_enable(rhport);
+
+ return true;
+}
+
+void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+ const unsigned epn = tu_edpt_number(ep_addr);
+
+ if (0 == epn) {
+ CI_REG->EP[epn].CTL |= USB_ENDPT_EPSTALL_MASK;
+ } else {
+ const unsigned dir = tu_edpt_dir(ep_addr);
+ const unsigned odd = _dcd.endpoint[epn][dir].odd;
+ buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][odd];
+ TU_ASSERT(0 == bd->own,);
+
+ dcd_int_disable(rhport);
+
+ bd->bdt_stall = 1;
+ __DSB();
+ bd->own = 1; /* This bit must be set last */
+
+ dcd_int_enable(rhport);
+ }
+}
+
+void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
+{
+ const unsigned epn = tu_edpt_number(ep_addr);
+ TU_VERIFY(epn,);
+ const unsigned dir = tu_edpt_dir(ep_addr);
+ const unsigned odd = _dcd.endpoint[epn][dir].odd;
+ buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
+ TU_VERIFY(bd[odd].own,);
+
+ dcd_int_disable(rhport);
+
+ bd[odd].own = 0;
+ __DSB();
+
+ // clear stall
+ bd[odd].bdt_stall = 0;
+
+ // Reset data toggle
+ bd[odd ].data = 0;
+ bd[odd ^ 1].data = 1;
+
+ // We already cleared this in ISR, but just clear it here to be safe
+ const uint32_t ep_ctl = CI_REG->EP[epn].CTL;
+ if (ep_ctl & USB_ENDPT_EPSTALL_MASK) {
+ CI_REG->EP[epn].CTL = ep_ctl & ~USB_ENDPT_EPSTALL_MASK;
+ }
+
+ dcd_int_enable(rhport);
+}
+
+//--------------------------------------------------------------------+
+// ISR
+//--------------------------------------------------------------------+
+void dcd_int_handler(uint8_t rhport)
+{
+ uint32_t is = CI_REG->INT_STAT;
+ uint32_t msk = CI_REG->INT_EN;
+
+ // clear non-enabled interrupts
+ CI_REG->INT_STAT = is & ~msk;
+ is &= msk;
+
+ if (is & USB_ISTAT_ERROR_MASK) {
+ /* TODO: */
+ uint32_t es = CI_REG->ERR_STAT;
+ CI_REG->ERR_STAT = es;
+ CI_REG->INT_STAT = is; /* discard any pending events */
+ }
+
+ if (is & USB_ISTAT_USBRST_MASK) {
+ CI_REG->INT_STAT = is; /* discard any pending events */
+ process_bus_reset(rhport);
+ }
+
+ if (is & USB_ISTAT_SLEEP_MASK) {
+ // TU_LOG2("Suspend: "); TU_LOG2_HEX(is);
+
+ // Note Host usually has extra delay after bus reset (without SOF), which could falsely
+ // detected as Sleep event. Though usbd has debouncing logic so we are good
+ CI_REG->INT_STAT = USB_ISTAT_SLEEP_MASK;
+ process_bus_sleep(rhport);
+ }
+
+#if 0 // ISTAT_RESUME never trigger, probably for host mode ?
+ if (is & USB_ISTAT_RESUME_MASK) {
+ // TU_LOG2("ISTAT Resume: "); TU_LOG2_HEX(is);
+ KHCI->ISTAT = USB_ISTAT_RESUME_MASK;
+ process_bus_resume(rhport);
+ }
+#endif
+
+ if (CI_REG->USBTRC0 & USB_USBTRC0_USB_RESUME_INT_MASK) {
+ // TU_LOG2("USBTRC0 Resume: "); TU_LOG2_HEX(is); TU_LOG2_HEX(KHCI->USBTRC0);
+ process_bus_resume(rhport);
+ }
+
+ if (is & USB_ISTAT_SOFTOK_MASK) {
+ CI_REG->INT_STAT = USB_ISTAT_SOFTOK_MASK;
+ dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
+ }
+
+ if (is & USB_ISTAT_STALL_MASK) {
+ CI_REG->INT_STAT = USB_ISTAT_STALL_MASK;
+ process_stall(rhport);
+ }
+
+ if (is & USB_ISTAT_TOKDNE_MASK) {
+ process_tokdne(rhport);
+ }
+}
+
+#endif
diff --git a/src/portable/chipidea/ci_hs/ci_hs_imxrt.h b/src/portable/chipidea/ci_hs/ci_hs_imxrt.h
index 607926a65..c59c107ff 100644
--- a/src/portable/chipidea/ci_hs/ci_hs_imxrt.h
+++ b/src/portable/chipidea/ci_hs/ci_hs_imxrt.h
@@ -46,18 +46,56 @@ static const ci_hs_controller_t _ci_controller[] =
{
// RT1010 and RT1020 only has 1 USB controller
#if FSL_FEATURE_SOC_USBHS_COUNT == 1
- { .reg_base = USB_BASE , .irqnum = USB_OTG1_IRQn, .ep_count = 8 }
+ { .reg_base = USB_BASE , .irqnum = USB_OTG1_IRQn }
#else
- { .reg_base = USB1_BASE, .irqnum = USB_OTG1_IRQn, .ep_count = 8 },
- { .reg_base = USB2_BASE, .irqnum = USB_OTG2_IRQn, .ep_count = 8 }
+ { .reg_base = USB1_BASE, .irqnum = USB_OTG1_IRQn},
+ { .reg_base = USB2_BASE, .irqnum = USB_OTG2_IRQn}
#endif
};
+#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base)
+
+//------------- DCD -------------//
#define CI_DCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum)
#define CI_DCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum)
+//------------- HCD -------------//
#define CI_HCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum)
#define CI_HCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum)
+//------------- DCache -------------//
+TU_ATTR_ALWAYS_INLINE static inline bool imxrt_is_cache_mem(uintptr_t addr) {
+ return !(0x20000000 <= addr && addr < 0x20100000);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool imxrt_dcache_clean(void const* addr, uint32_t data_size) {
+ const uintptr_t addr32 = (uintptr_t) addr;
+ if (imxrt_is_cache_mem(addr32)) {
+ TU_ASSERT(tu_is_aligned32(addr32));
+ SCB_CleanDCache_by_Addr((uint32_t *) addr32, (int32_t) data_size);
+ }
+ return true;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool imxrt_dcache_invalidate(void const* addr, uint32_t data_size) {
+ const uintptr_t addr32 = (uintptr_t) addr;
+ if (imxrt_is_cache_mem(addr32)) {
+ // Invalidating does not push cached changes back to RAM so we need to be
+ // *very* careful when we do it. If we're not aligned, then we risk resetting
+ // values back to their RAM state.
+ TU_ASSERT(tu_is_aligned32(addr32));
+ SCB_InvalidateDCache_by_Addr((void*) addr32, (int32_t) data_size);
+ }
+ return true;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool imxrt_dcache_clean_invalidate(void const* addr, uint32_t data_size) {
+ const uintptr_t addr32 = (uintptr_t) addr;
+ if (imxrt_is_cache_mem(addr32)) {
+ TU_ASSERT(tu_is_aligned32(addr32));
+ SCB_CleanInvalidateDCache_by_Addr((uint32_t *) addr32, (int32_t) data_size);
+ }
+ return true;
+}
#endif
diff --git a/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h b/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h
index 8c2e7dfa6..178eec419 100644
--- a/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h
+++ b/src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h
@@ -27,15 +27,26 @@
#ifndef _CI_HS_LPC18_43_H_
#define _CI_HS_LPC18_43_H_
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
// LPCOpen for 18xx & 43xx
#include "chip.h"
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
static const ci_hs_controller_t _ci_controller[] =
{
- { .reg_base = LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 6 },
- { .reg_base = LPC_USB1_BASE, .irqnum = USB1_IRQn, .ep_count = 4 }
+ { .reg_base = LPC_USB0_BASE, .irqnum = USB0_IRQn },
+ { .reg_base = LPC_USB1_BASE, .irqnum = USB1_IRQn }
};
+#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base)
+
#define CI_DCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum)
#define CI_DCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum)
diff --git a/src/portable/chipidea/ci_hs/ci_hs_mcx.h b/src/portable/chipidea/ci_hs/ci_hs_mcx.h
new file mode 100644
index 000000000..f940f4a9d
--- /dev/null
+++ b/src/portable/chipidea/ci_hs/ci_hs_mcx.h
@@ -0,0 +1,52 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _CI_HS_MCX_H_
+#define _CI_HS_MCX_H_
+
+#include "fsl_device_registers.h"
+
+// NOTE: MCX N9 has 2 different USB Controller
+// - USB0 is KHCI FullSpeed
+// - USB1 is ChipIdea HighSpeed, therefore rhport = 1 is actually index 0
+
+static const ci_hs_controller_t _ci_controller[] = {
+ {.reg_base = USBHS1__USBC_BASE, .irqnum = USB1_HS_IRQn}
+};
+
+TU_ATTR_ALWAYS_INLINE static inline ci_hs_regs_t* CI_HS_REG(uint8_t port) {
+ (void) port;
+ return ((ci_hs_regs_t*) _ci_controller[0].reg_base);
+}
+
+#define CI_DCD_INT_ENABLE(_p) do { (void) _p; NVIC_EnableIRQ (_ci_controller[0].irqnum); } while (0)
+#define CI_DCD_INT_DISABLE(_p) do { (void) _p; NVIC_DisableIRQ(_ci_controller[0].irqnum); } while (0)
+
+#define CI_HCD_INT_ENABLE(_p) NVIC_EnableIRQ (_ci_controller[_p].irqnum)
+#define CI_HCD_INT_DISABLE(_p) NVIC_DisableIRQ(_ci_controller[_p].irqnum)
+
+
+#endif
diff --git a/src/portable/chipidea/ci_hs/ci_hs_type.h b/src/portable/chipidea/ci_hs/ci_hs_type.h
index 31b5a012d..2f3aa3694 100644
--- a/src/portable/chipidea/ci_hs/ci_hs_type.h
+++ b/src/portable/chipidea/ci_hs/ci_hs_type.h
@@ -31,13 +31,21 @@
extern "C" {
#endif
+// DCCPARAMS
+enum {
+ DCCPARAMS_DEN_MASK = 0x1Fu, ///< DEN bit 4:0
+};
+
// USBCMD
enum {
USBCMD_RUN_STOP = TU_BIT(0),
USBCMD_RESET = TU_BIT(1),
USBCMD_SETUP_TRIPWIRE = TU_BIT(13),
- USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD
-// Interrupt Threshold bit 23:16
+ USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14), // This bit is used as a semaphore to ensure the to proper addition of a
+ // new dTD to an active (primed) endpoint’s linked list. This bit is set and
+ // cleared by software during the process of adding a new dTD
+
+ USBCMD_INTR_THRESHOLD_MASK = 0x00FF0000u, // Interrupt Threshold bit 23:16
};
// PORTSC1
@@ -72,6 +80,7 @@ enum {
// USBMode
enum {
+ USBMOD_CM_MASK = TU_BIT(0) | TU_BIT(1),
USBMODE_CM_DEVICE = 2,
USBMODE_CM_HOST = 3,
@@ -134,7 +143,6 @@ typedef struct
{
uint32_t reg_base;
uint32_t irqnum;
- uint8_t ep_count; // Max bi-directional Endpoints
}ci_hs_controller_t;
#ifdef __cplusplus
diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c
index bc6736cf2..f9ec666e5 100644
--- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c
+++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c
@@ -28,34 +28,52 @@
#if CFG_TUD_ENABLED && defined(TUP_USBIP_CHIPIDEA_HS)
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
#include "device/dcd.h"
#include "ci_hs_type.h"
-#if CFG_TUSB_MCU == OPT_MCU_MIMXRT
+#if CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX
#include "ci_hs_imxrt.h"
-#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
+
+ void dcd_dcache_clean(void const* addr, uint32_t data_size) {
+ imxrt_dcache_clean(addr, data_size);
+ }
+
+ void dcd_dcache_invalidate(void const* addr, uint32_t data_size) {
+ imxrt_dcache_invalidate(addr, data_size);
+ }
+
+ void dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) {
+ imxrt_dcache_clean_invalidate(addr, data_size);
+ }
+
+#else
+
+#if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
#include "ci_hs_lpc18_43.h"
+
+#elif TU_CHECK_MCU(OPT_MCU_MCXN9)
+ // MCX N9 only port 1 use this controller
+ #include "ci_hs_mcx.h"
#else
#error "Unsupported MCUs"
#endif
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
+ TU_ATTR_WEAK void dcd_dcache_clean(void const* addr, uint32_t data_size) {
+ (void) addr; (void) data_size;
+ }
-#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base)
+ TU_ATTR_WEAK void dcd_dcache_invalidate(void const* addr, uint32_t data_size) {
+ (void) addr; (void) data_size;
+ }
-// Clean means to push any cached changes to RAM and invalidate "removes" the
-// entry from the cache.
-#if defined(__CORTEX_M) && __CORTEX_M == 7 && __DCACHE_PRESENT == 1
- #define CleanInvalidateDCache_by_Addr SCB_CleanInvalidateDCache_by_Addr
-#else
- #define CleanInvalidateDCache_by_Addr(_addr, _dsize)
+ TU_ATTR_WEAK void dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) {
+ (void) addr; (void) data_size;
+ }
#endif
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
// ENDPTCTRL
enum {
@@ -157,10 +175,20 @@ typedef struct {
dcd_qtd_t qtd[TUP_DCD_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(32);
}dcd_data_t;
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048)
+CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(2048)
static dcd_data_t _dcd_data;
//--------------------------------------------------------------------+
+// Prototypes and Helper Functions
+//--------------------------------------------------------------------+
+
+TU_ATTR_ALWAYS_INLINE
+static inline uint8_t ci_ep_count(ci_hs_regs_t const* dcd_reg)
+{
+ return dcd_reg->DCCPARAMS & DCCPARAMS_DEN_MASK;
+}
+
+//--------------------------------------------------------------------+
// Controller API
//--------------------------------------------------------------------+
@@ -174,7 +202,8 @@ static void bus_reset(uint8_t rhport)
// endpoint type of the unused direction must be changed from the control type to any other
// type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior
// for the data PID tracking on the active endpoint.
- for( uint8_t i=1; i < _ci_controller[rhport].ep_count; i++)
+ uint8_t const ep_count = ci_ep_count(dcd_reg);
+ for( uint8_t i=1; i < ep_count; i++)
{
dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
}
@@ -202,7 +231,7 @@ static void bus_reset(uint8_t rhport)
_dcd_data.qhd[0][0].int_on_setup = 1; // OUT only
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+ dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t));
}
void dcd_init(uint8_t rhport)
@@ -211,26 +240,34 @@ void dcd_init(uint8_t rhport)
ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+ TU_ASSERT(ci_ep_count(dcd_reg) <= TUP_DCD_ENDPOINT_MAX, );
+
// Reset controller
dcd_reg->USBCMD |= USBCMD_RESET;
while( dcd_reg->USBCMD & USBCMD_RESET ) {}
// Set mode to device, must be set immediately after reset
- dcd_reg->USBMODE = USBMODE_CM_DEVICE;
+ uint32_t usbmode = dcd_reg->USBMODE & ~USBMOD_CM_MASK;
+ usbmode |= USBMODE_CM_DEVICE;
+ dcd_reg->USBMODE = usbmode;
+
dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION;
#if !TUD_OPT_HIGH_SPEED
dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED;
#endif
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+ dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t));
dcd_reg->ENDPTLISTADDR = (uint32_t) _dcd_data.qhd; // Endpoint List Address has to be 2K alignment
dcd_reg->USBSTS = dcd_reg->USBSTS;
dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_SUSPEND;
- dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0
- dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect
+ uint32_t usbcmd = dcd_reg->USBCMD;
+ usbcmd &= ~USBCMD_INTR_THRESHOLD_MASK; // Interrupt Threshold Interval = 0
+ usbcmd |= USBCMD_RUN_STOP; // run
+
+ dcd_reg->USBCMD = usbcmd;
}
void dcd_int_enable(uint8_t rhport)
@@ -286,7 +323,7 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes)
{
// Force the CPU to flush the buffer. We increase the size by 31 because the call aligns the
// address to 32-byte boundaries. Buffer must be word aligned
- CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31);
+ dcd_dcache_clean_invalidate((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31);
tu_memclr(p_qtd, sizeof(dcd_qtd_t));
@@ -343,8 +380,10 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
+ ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+
// Must not exceed max endpoint number
- TU_ASSERT( epnum < _ci_controller[rhport].ep_count );
+ TU_ASSERT(epnum < ci_ep_count(dcd_reg));
//------------- Prepare Queue Head -------------//
dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
@@ -359,11 +398,9 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
p_qhd->qtd_overlay.next = QTD_NEXT_INVALID;
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+ dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t));
// Enable EP Control
- ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
-
uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET;
if ( dir == TUSB_DIR_OUT )
@@ -382,7 +419,8 @@ void dcd_edpt_close_all (uint8_t rhport)
ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
// Disable all non-control endpoints
- for( uint8_t epnum=1; epnum < _ci_controller[rhport].ep_count; epnum++)
+ uint8_t const ep_count = ci_ep_count(dcd_reg);
+ for (uint8_t epnum = 1; epnum < ep_count; epnum++)
{
_dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1;
_dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1;
@@ -420,7 +458,7 @@ static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir)
p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd
// flush cache
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+ dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t));
if ( epnum == 0 )
{
@@ -498,7 +536,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16
}
}
- CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31);
+ dcd_dcache_clean_invalidate((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31);
}
else
{
@@ -611,20 +649,11 @@ void dcd_int_handler(uint8_t rhport)
if (int_status & INTR_USB)
{
// Make sure we read the latest version of _dcd_data.
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+ dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t));
uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE;
dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge
- if (dcd_reg->ENDPTSETUPSTAT)
- {
- //------------- Set up Received -------------//
- // 23.10.10.2 Operational model for setup transfers
- dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;
-
- dcd_event_setup_received(rhport, (uint8_t*)(uintptr_t) &_dcd_data.qhd[0][0].setup_request, true);
- }
-
// 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
// nothing to do, we will submit xfer as error to usbd
// if (int_status & INTR_ERROR) { }
@@ -637,6 +666,15 @@ void dcd_int_handler(uint8_t rhport)
if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN);
}
}
+
+ // Set up Received
+ // 23.10.10.2 Operational model for setup transfers
+ // Must be after normal transfer complete since it is possible to have both previous control status + new setup
+ // in the same frame and we should handle previous status first.
+ if (dcd_reg->ENDPTSETUPSTAT) {
+ dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;
+ dcd_event_setup_received(rhport, (uint8_t *) (uintptr_t) &_dcd_data.qhd[0][0].setup_request, true);
+ }
}
if (int_status & INTR_SOF)
diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c
index d607627b4..462cbd301 100644
--- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c
+++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c
@@ -28,8 +28,7 @@
// Chipidea Highspeed USB IP implement EHCI for host functionality
-#if CFG_TUH_ENABLED && \
- (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT)
+#if CFG_TUH_ENABLED && defined(TUP_USBIP_EHCI)
//--------------------------------------------------------------------+
// INCLUDE
@@ -39,55 +38,69 @@
#include "portable/ehci/ehci_api.h"
#include "ci_hs_type.h"
-#if CFG_TUSB_MCU == OPT_MCU_MIMXRT
- #include "ci_hs_imxrt.h"
+#if CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX
+
+#include "ci_hs_imxrt.h"
+
+bool hcd_dcache_clean(void const* addr, uint32_t data_size) {
+ return imxrt_dcache_clean(addr, data_size);
+}
+
+bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) {
+ return imxrt_dcache_invalidate(addr, data_size);
+}
+
+bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) {
+ return imxrt_dcache_clean_invalidate(addr, data_size);
+}
+
#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
- #include "ci_hs_lpc18_43.h"
+
+#include "ci_hs_lpc18_43.h"
+
#else
- #error "Unsupported MCUs"
+#error "Unsupported MCUs"
#endif
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-#define CI_HS_REG(_port) ((ci_hs_regs_t*) _ci_controller[_port].reg_base)
-
//--------------------------------------------------------------------+
// Controller API
//--------------------------------------------------------------------+
-bool hcd_init(uint8_t rhport)
-{
- ci_hs_regs_t* hcd_reg = CI_HS_REG(rhport);
+bool hcd_init(uint8_t rhport) {
+ ci_hs_regs_t *hcd_reg = CI_HS_REG(rhport);
// Reset controller
hcd_reg->USBCMD |= USBCMD_RESET;
- while( hcd_reg->USBCMD & USBCMD_RESET ) {}
+ while ( hcd_reg->USBCMD & USBCMD_RESET ) {}
// Set mode to device, must be set immediately after reset
#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
// LPC18XX/43XX need to set VBUS Power Select to HIGH
// RHPORT1 is fullspeed only (need external PHY for Highspeed)
hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
- if (rhport == 1) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
+ if ( rhport == 1 ) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
#else
hcd_reg->USBMODE = USBMODE_CM_HOST;
#endif
// FIXME force full speed, still have issue with Highspeed enumeration
+ // probably due to physical connection bouncing when plug/unplug
+ // 1. Have issue when plug/unplug devices, maybe the port is not reset properly
+ // 2. Also does not seems to detect disconnection
hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD);
}
-void hcd_int_enable(uint8_t rhport)
-{
+void hcd_int_enable(uint8_t rhport) {
CI_HCD_INT_ENABLE(rhport);
}
-void hcd_int_disable(uint8_t rhport)
-{
+void hcd_int_disable(uint8_t rhport) {
CI_HCD_INT_DISABLE(rhport);
}
diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c
index 961da81d6..d1e85c2df 100644
--- a/src/portable/dialog/da146xx/dcd_da146xx.c
+++ b/src/portable/dialog/da146xx/dcd_da146xx.c
@@ -651,7 +651,7 @@ static void handle_epx_tx_ev(xfer_ctl_t *xfer)
}
if (txs & USB_USB_TXS1_REG_USB_TX_URUN_Msk)
{
- TU_LOG1("EP %d FIFO underrun\n", epnum);
+ TU_LOG1("EP %d FIFO underrun\r\n", epnum);
}
// Start next or repeated packet.
start_tx_packet(xfer);
diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c
index 9951aa5da..e145cbb1b 100644
--- a/src/portable/ehci/ehci.c
+++ b/src/portable/ehci/ehci.c
@@ -48,8 +48,8 @@
#ifdef TUP_USBIP_CHIPIDEA_HS
// NXP Transdimension: 8 elements
#define FRAMELIST_SIZE_BIT_VALUE 7u
- #define FRAMELIST_SIZE_USBCMD_VALUE (((FRAMELIST_SIZE_BIT_VALUE & 3) << EHCI_USBCMD_POS_FRAMELIST_SIZE) | \
- ((FRAMELIST_SIZE_BIT_VALUE >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB))
+ #define FRAMELIST_SIZE_USBCMD_VALUE (((FRAMELIST_SIZE_BIT_VALUE & 3) << EHCI_USBCMD_FRAMELIST_SIZE_SHIFT) | \
+ ((FRAMELIST_SIZE_BIT_VALUE >> 2) << EHCI_USBCMD_CHIPIDEA_FRAMELIST_SIZE_MSB_SHIFT))
#else
// STD EHCI: 256 elements
#define FRAMELIST_SIZE_BIT_VALUE 2u
@@ -58,7 +58,8 @@
#define FRAMELIST_SIZE (1024 >> FRAMELIST_SIZE_BIT_VALUE)
-#define QHD_MAX (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX)
+// Total queue head pool. TODO should be user configurable and more optimize memory usage in the future
+#define QHD_MAX (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX + CFG_TUH_HUB)
#define QTD_MAX QHD_MAX
typedef struct
@@ -79,7 +80,8 @@ typedef struct
ehci_qhd_t qhd_pool[QHD_MAX];
ehci_qtd_t qtd_pool[QTD_MAX] TU_ATTR_ALIGNED(32);
- ehci_registers_t* regs;
+ ehci_registers_t* regs; // operational register
+ ehci_cap_registers_t* cap_regs; // capability register
volatile uint32_t uframe_number;
}ehci_data_t;
@@ -88,53 +90,87 @@ typedef struct
CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data;
//--------------------------------------------------------------------+
-// PROTOTYPE
+// Debug
//--------------------------------------------------------------------+
-static inline ehci_link_t* get_period_head(uint8_t rhport, uint32_t interval_ms)
-{
- (void) rhport;
- return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min32(FRAMELIST_SIZE, interval_ms) ) ];
-}
-
-static inline ehci_qhd_t* qhd_control(uint8_t dev_addr)
-{
- return &ehci_data.control[dev_addr].qhd;
-}
+#if CFG_TUSB_DEBUG >= (EHCI_DBG + 1)
+static inline void print_portsc(ehci_registers_t* regs) {
+ TU_LOG_HEX(EHCI_DBG, regs->portsc);
+ TU_LOG(EHCI_DBG, " Connect Status : %u\r\n", regs->portsc_bm.current_connect_status);
+ TU_LOG(EHCI_DBG, " Connect Change : %u\r\n", regs->portsc_bm.connect_status_change);
+ TU_LOG(EHCI_DBG, " Enabled : %u\r\n", regs->portsc_bm.port_enabled);
+ TU_LOG(EHCI_DBG, " Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change);
-static inline ehci_qhd_t* qhd_async_head(uint8_t rhport)
-{
- (void) rhport;
- // control qhd of dev0 is used as async head
- return qhd_control(0);
+ TU_LOG(EHCI_DBG, " OverCurr Change: %u\r\n", regs->portsc_bm.over_current_change);
+ TU_LOG(EHCI_DBG, " Force Resume : %u\r\n", regs->portsc_bm.force_port_resume);
+ TU_LOG(EHCI_DBG, " Suspend : %u\r\n", regs->portsc_bm.suspend);
+ TU_LOG(EHCI_DBG, " Reset : %u\r\n", regs->portsc_bm.port_reset);
+ TU_LOG(EHCI_DBG, " Power : %u\r\n", regs->portsc_bm.port_power);
}
-static inline ehci_qtd_t* qtd_control(uint8_t dev_addr)
-{
- return &ehci_data.control[dev_addr].qtd;
+static inline void print_intr(uint32_t intr) {
+ TU_LOG_HEX(EHCI_DBG, intr);
+ TU_LOG(EHCI_DBG, " USB Interrupt : %u\r\n", (intr & EHCI_INT_MASK_USB) ? 1 : 0);
+ TU_LOG(EHCI_DBG, " USB Error : %u\r\n", (intr & EHCI_INT_MASK_ERROR) ? 1 : 0);
+ TU_LOG(EHCI_DBG, " Port Change Detect : %u\r\n", (intr & EHCI_INT_MASK_PORT_CHANGE) ? 1 : 0);
+ TU_LOG(EHCI_DBG, " Frame List Rollover: %u\r\n", (intr & EHCI_INT_MASK_FRAMELIST_ROLLOVER) ? 1 : 0);
+ TU_LOG(EHCI_DBG, " Host System Error : %u\r\n", (intr & EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR) ? 1 : 0);
+ TU_LOG(EHCI_DBG, " Async Advance : %u\r\n", (intr & EHCI_INT_MASK_ASYNC_ADVANCE) ? 1 : 0);
+// TU_LOG(EHCI_DBG, " Interrupt on Async: %u\r\n", (intr & EHCI_INT_MASK_NXP_ASYNC));
+// TU_LOG(EHCI_DBG, " Periodic Schedule : %u\r\n", (intr & EHCI_INT_MASK_NXP_PERIODIC));
}
+#else
+#define print_portsc(_reg)
+#endif
-static inline ehci_qhd_t* qhd_next (ehci_qhd_t const * p_qhd);
-static inline ehci_qhd_t* qhd_find_free (void);
-static inline ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr);
+//--------------------------------------------------------------------+
+// PROTOTYPE
+//--------------------------------------------------------------------+
-// determine if a queue head has bus-related error
-static inline bool qhd_has_xact_error (ehci_qhd_t * p_qhd)
-{
- return (p_qhd->qtd_overlay.buffer_err || p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err);
- //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error
-}
+// weak dcache for non-cacheable MCU
+TU_ATTR_WEAK bool hcd_dcache_clean(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; }
+TU_ATTR_WEAK bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; }
+TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; }
+TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* qhd_control(uint8_t dev_addr);
+TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* qhd_next (ehci_qhd_t const * p_qhd);
+TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* qhd_find_free (void);
+static ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr);
static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
+static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd);
+static void qhd_remove_qtd(ehci_qhd_t *qhd);
+
+TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t* qtd_control(uint8_t dev_addr);
+TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t* qtd_find_free (void);
+static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes);
-static inline ehci_qtd_t* qtd_find_free (void);
-static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd);
-static inline void qtd_insert_to_qhd (ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new);
-static inline void qtd_remove_1st_from_qhd (ehci_qhd_t *p_qhd);
-static void qtd_init (ehci_qtd_t* p_qtd, void const* buffer, uint16_t total_bytes);
+TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_get_period_head(uint8_t rhport, uint32_t interval_ms);
+TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* list_get_async_head(uint8_t rhport);
+TU_ATTR_ALWAYS_INLINE static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type);
+TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_next (ehci_link_t const *p_link);
+static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr);
+
+static void ehci_disable_schedule(ehci_registers_t* regs, bool is_period) {
+ // maybe have a timeout for status
+ if (is_period) {
+ regs->command_bm.periodic_enable = 0;
+ while(regs->status_bm.periodic_status) {}
+ } else {
+ regs->command_bm.async_enable = 0;
+ while(regs->status_bm.async_status) {} // should have a timeout
+ }
+}
-static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type);
-static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer);
+static void ehci_enable_schedule(ehci_registers_t* regs, bool is_period) {
+ // maybe have a timeout for status
+ if (is_period) {
+ regs->command_bm.periodic_enable = 1;
+ while ( 0 == regs->status_bm.periodic_status ) {}
+ } else {
+ regs->command_bm.async_enable = 1;
+ while( 0 == regs->status_bm.async_status ) {}
+ }
+}
//--------------------------------------------------------------------+
// HCD API
@@ -152,11 +188,16 @@ void hcd_port_reset(uint8_t rhport)
ehci_registers_t* regs = ehci_data.regs;
-// regs->portsc_bm.port_enabled = 0; // disable port before reset
-// regs->portsc_bm.port_reset = 1;
+ // skip if already in reset
+ if (regs->portsc_bm.port_reset) {
+ return;
+ }
- uint32_t portsc = regs->portsc;
+ // mask out Write-1-to-Clear bits
+ uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C;
+ // EHCI Table 2-16 PortSC
+ // when software writes Port Reset bit to a one, it must also write a zero to the Port Enable bit.
portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED);
portsc |= EHCI_PORTSC_MASK_PORT_RESET;
@@ -166,11 +207,18 @@ void hcd_port_reset(uint8_t rhport)
void hcd_port_reset_end(uint8_t rhport)
{
(void) rhport;
-
-#if 0
ehci_registers_t* regs = ehci_data.regs;
- regs->portsc_bm.port_reset = 0;
-#endif
+
+ // skip if reset is already complete
+ if (!regs->portsc_bm.port_reset) {
+ return;
+ }
+
+ // mask out all change bits since they are Write 1 to clear
+ uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C;
+ portsc &= ~EHCI_PORTSC_MASK_PORT_RESET;
+
+ regs->portsc = portsc;
}
bool hcd_port_connect_status(uint8_t rhport)
@@ -185,138 +233,126 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport)
return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed
}
-static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr)
-{
- for(ehci_link_t* prev = list_head;
- !prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head) && prev != NULL;
- prev = list_next(prev) )
- {
- // TODO check type for ISO iTD and siTD
- // TODO Suppress cast-align warning
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wcast-align"
- ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev);
- #pragma GCC diagnostic pop
- if ( qhd->dev_addr == dev_addr )
- {
- // TODO deactivate all TD, wait for QHD to inactive before removal
- prev->address = qhd->next.address;
-
- // EHCI 4.8.2 link the removed qhd to async head (which always reachable by Host Controller)
- qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1);
-
- if ( qhd->int_smask )
- {
- // period list queue element is guarantee to be free in the next frame (1 ms)
- qhd->used = 0;
- }else
- {
- // async list use async advance handshake
- // mark as removing, will completely re-usable when async advance isr occurs
- qhd->removing = 1;
- }
- }
- }
-}
-
// Close all opened endpoint belong to this device
-void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
+void hcd_device_close(uint8_t rhport, uint8_t daddr)
{
// skip dev0
- if (dev_addr == 0) return;
+ if (daddr == 0) {
+ return;
+ }
// Remove from async list
- list_remove_qhd_by_addr( (ehci_link_t*) qhd_async_head(rhport), dev_addr );
+ list_remove_qhd_by_daddr((ehci_link_t *) list_get_async_head(rhport), daddr);
// Remove from all interval period list
- for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++)
- {
- list_remove_qhd_by_addr( (ehci_link_t*) &ehci_data.period_head_arr[i], dev_addr);
+ for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) {
+ list_remove_qhd_by_daddr((ehci_link_t *) &ehci_data.period_head_arr[i], daddr);
}
// Async doorbell (EHCI 4.8.2 for operational details)
ehci_data.regs->command_bm.async_adv_doorbell = 1;
}
-bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
-{
- (void) capability_reg; // not used yet
-
- tu_memclr(&ehci_data, sizeof(ehci_data_t));
-
- ehci_data.regs = (ehci_registers_t* ) operatial_reg;
-
- ehci_registers_t* regs = ehci_data.regs;
-
- //------------- CTRLDSSEGMENT Register (skip) -------------//
- //------------- USB INT Register -------------//
- regs->inten = 0; // 1. disable all the interrupt
- regs->status = EHCI_INT_MASK_ALL; // 2. clear all status
-
- regs->inten = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | EHCI_INT_MASK_ASYNC_ADVANCE |
- EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_FRAMELIST_ROLLOVER;
-
- //------------- Asynchronous List -------------//
- ehci_qhd_t * const async_head = qhd_async_head(rhport);
- tu_memclr(async_head, sizeof(ehci_qhd_t));
-
- async_head->next.address = (uint32_t) async_head; // circular list, next is itself
- async_head->next.type = EHCI_QTYPE_QHD;
- async_head->head_list_flag = 1;
- async_head->qtd_overlay.halted = 1; // inactive most of time
- async_head->qtd_overlay.next.terminate = 1; // TODO removed if verified
-
- regs->async_list_addr = (uint32_t) async_head;
+static void init_periodic_list(uint8_t rhport) {
+ (void) rhport;
- //------------- Periodic List -------------//
// Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
- for ( uint32_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++ )
- {
+ for ( uint32_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++ ) {
ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero
ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive
}
- ehci_link_t * const framelist = ehci_data.period_framelist;
- ehci_link_t * const period_1ms = get_period_head(rhport, 1u);
-
+ // TODO EHCI_FRAMELIST_SIZE with other size than 8
// all links --> period_head_arr[0] (1ms)
// 0, 2, 4, 6 etc --> period_head_arr[1] (2ms)
// 1, 5 --> period_head_arr[2] (4ms)
// 3 --> period_head_arr[3] (8ms)
- // TODO EHCI_FRAMELIST_SIZE with other size than 8
- for(uint32_t i=0; i<FRAMELIST_SIZE; i++)
- {
- framelist[i].address = (uint32_t) period_1ms;
- framelist[i].type = EHCI_QTYPE_QHD;
+ ehci_link_t * const framelist = ehci_data.period_framelist;
+ ehci_link_t * const head_1ms = (ehci_link_t *) &ehci_data.period_head_arr[0];
+ ehci_link_t * const head_2ms = (ehci_link_t *) &ehci_data.period_head_arr[1];
+ ehci_link_t * const head_4ms = (ehci_link_t *) &ehci_data.period_head_arr[2];
+ ehci_link_t * const head_8ms = (ehci_link_t *) &ehci_data.period_head_arr[3];
+
+ for (uint32_t i = 0; i < FRAMELIST_SIZE; i++) {
+ framelist[i].address = (uint32_t) head_1ms;
+ framelist[i].type = EHCI_QTYPE_QHD;
}
- for(uint32_t i=0; i<FRAMELIST_SIZE; i+=2)
- {
- list_insert(framelist + i, get_period_head(rhport, 2u), EHCI_QTYPE_QHD);
+ for (uint32_t i = 0; i < FRAMELIST_SIZE; i += 2) {
+ list_insert(framelist + i, head_2ms, EHCI_QTYPE_QHD);
}
- for(uint32_t i=1; i<FRAMELIST_SIZE; i+=4)
- {
- list_insert(framelist + i, get_period_head(rhport, 4u), EHCI_QTYPE_QHD);
+ for (uint32_t i = 1; i < FRAMELIST_SIZE; i += 4) {
+ list_insert(framelist + i, head_4ms, EHCI_QTYPE_QHD);
}
- list_insert(framelist+3, get_period_head(rhport, 8u), EHCI_QTYPE_QHD);
+ list_insert(framelist + 3, head_8ms, EHCI_QTYPE_QHD);
+
+ head_1ms->terminate = 1;
+}
+
+bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
+{
+ tu_memclr(&ehci_data, sizeof(ehci_data_t));
+
+ ehci_data.regs = (ehci_registers_t*) operatial_reg;
+ ehci_data.cap_regs = (ehci_cap_registers_t*) capability_reg;
- period_1ms->terminate = 1;
+ ehci_registers_t* regs = ehci_data.regs;
- regs->periodic_list_base = (uint32_t) framelist;
+ // EHCI 4.1 Host Controller Initialization
+
+ //------------- CTRLDSSEGMENT Register (skip) -------------//
+
+ //------------- USB INT Register -------------//
+
+ // disable all the interrupt
+ regs->inten = 0;
+
+ // clear all status except port change since device maybe connected before this driver is initialized
+ regs->status = (EHCI_INT_MASK_ALL & ~EHCI_INT_MASK_PORT_CHANGE);
+
+ // Enable interrupts
+ regs->inten = EHCI_INT_MASK_USB | EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
+ EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_FRAMELIST_ROLLOVER;
+
+ //------------- Asynchronous List -------------//
+ ehci_qhd_t * const async_head = list_get_async_head(rhport);
+ tu_memclr(async_head, sizeof(ehci_qhd_t));
+
+ async_head->next.address = (uint32_t) async_head; // circular list, next is itself
+ async_head->next.type = EHCI_QTYPE_QHD;
+ async_head->head_list_flag = 1;
+ async_head->qtd_overlay.halted = 1; // inactive most of time
+ async_head->qtd_overlay.next.terminate = 1; // TODO removed if verified
+
+ regs->async_list_addr = (uint32_t) async_head;
+
+ //------------- Periodic List -------------//
+ init_periodic_list(rhport);
+ regs->periodic_list_base = (uint32_t) ehci_data.period_framelist;
+
+ hcd_dcache_clean(&ehci_data, sizeof(ehci_data_t));
//------------- TT Control (NXP only) -------------//
regs->nxp_tt_control = 0;
//------------- USB CMD Register -------------//
- regs->command |= TU_BIT(EHCI_USBCMD_POS_RUN_STOP) | TU_BIT(EHCI_USBCMD_POS_ASYNC_ENABLE) |
- TU_BIT(EHCI_USBCMD_POS_PERIOD_ENABLE) | // TODO enable period list only there is int/iso endpoint
+ regs->command |= EHCI_USBCMD_RUN_STOP | EHCI_USBCMD_PERIOD_SCHEDULE_ENABLE | EHCI_USBCMD_ASYNC_SCHEDULE_ENABLE |
FRAMELIST_SIZE_USBCMD_VALUE;
//------------- ConfigFlag Register (skip) -------------//
- regs->portsc_bm.port_power = 1; // enable port power
+
+ // enable port power bit in portsc. The function of this bit depends on the value of the Port
+ // Power Control (PPC) field in the HCSPARAMS register.
+ if (ehci_data.cap_regs->hcsparams_bm.port_power_control) {
+ // mask out all change bits since they are Write 1 to clear
+ uint32_t portsc = (regs->portsc & ~EHCI_PORTSC_MASK_W1C);
+ portsc |= EHCI_PORTSC_MASK_PORT_POWER;
+
+ regs->portsc = portsc;
+ }
return true;
}
@@ -347,15 +383,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS);
//------------- Prepare Queue Head -------------//
- ehci_qhd_t * p_qhd;
-
- if ( ep_desc->bEndpointAddress == 0 )
- {
- p_qhd = qhd_control(dev_addr);
- }else
- {
- p_qhd = qhd_find_free();
- }
+ ehci_qhd_t *p_qhd = (ep_desc->bEndpointAddress == 0) ? qhd_control(dev_addr) : qhd_find_free();
TU_ASSERT(p_qhd);
qhd_init(p_qhd, dev_addr, ep_desc);
@@ -370,11 +398,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
{
case TUSB_XFER_CONTROL:
case TUSB_XFER_BULK:
- list_head = (ehci_link_t*) qhd_async_head(rhport);
+ list_head = (ehci_link_t*) list_get_async_head(rhport);
break;
case TUSB_XFER_INTERRUPT:
- list_head = get_period_head(rhport, p_qhd->interval_ms);
+ list_head = list_get_period_head(rhport, p_qhd->interval_ms);
break;
case TUSB_XFER_ISOCHRONOUS:
@@ -383,12 +411,13 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
default: break;
}
-
TU_ASSERT(list_head);
- // TODO might need to disable async/period list
list_insert(list_head, (ehci_link_t*) p_qhd, EHCI_QTYPE_QHD);
+ hcd_dcache_clean(p_qhd, sizeof(ehci_qhd_t));
+ hcd_dcache_clean(list_head, sizeof(ehci_qhd_t));
+
return true;
}
@@ -400,16 +429,17 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd;
qtd_init(td, setup_packet, 8);
- td->pid = EHCI_PID_SETUP;
- td->int_on_complete = 1;
- td->next.terminate = 1;
+ td->pid = EHCI_PID_SETUP;
+
+ hcd_dcache_clean(setup_packet, 8);
- // sw region
- qhd->p_qtd_list_head = td;
- qhd->p_qtd_list_tail = td;
+ // Control endpoint never be stalled. Skip reset Data Toggle since it is fixed per stage
+ if (qhd->qtd_overlay.halted) {
+ qhd->qtd_overlay.halted = false;
+ }
- // attach TD
- qhd->qtd_overlay.next.address = (uint32_t) td;
+ // attach TD to QHD -> start transferring
+ qhd_attach_qtd(qhd, td);
return true;
}
@@ -421,51 +451,84 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
- if ( epnum == 0 )
- {
- ehci_qhd_t* qhd = qhd_control(dev_addr);
- ehci_qtd_t* qtd = qtd_control(dev_addr);
+ ehci_qhd_t* qhd = qhd_get_from_addr(dev_addr, ep_addr);
+ ehci_qtd_t* qtd;
+
+ if (epnum == 0) {
+ // Control endpoint never be stalled. Skip reset Data Toggle since it is fixed per stage
+ if (qhd->qtd_overlay.halted) {
+ qhd->qtd_overlay.halted = false;
+ }
+ qtd = qtd_control(dev_addr);
qtd_init(qtd, buffer, buflen);
- // first first data toggle is always 1 (data & setup stage)
+ // first data toggle is always 1 (data & setup stage)
qtd->data_toggle = 1;
qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT;
- qtd->int_on_complete = 1;
- qtd->next.terminate = 1;
+ } else {
+ // skip if endpoint is halted
+ TU_VERIFY(!qhd->qtd_overlay.halted);
- // sw region
- qhd->p_qtd_list_head = qtd;
- qhd->p_qtd_list_tail = qtd;
+ qtd = qtd_find_free();
+ TU_ASSERT(qtd);
- // attach TD
- qhd->qtd_overlay.next.address = (uint32_t) qtd;
- }else
- {
- ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr);
- ehci_qtd_t *p_qtd = qtd_find_free();
- TU_ASSERT(p_qtd);
+ qtd_init(qtd, buffer, buflen);
+ qtd->pid = qhd->pid;
+ }
- qtd_init(p_qtd, buffer, buflen);
- p_qtd->pid = p_qhd->pid;
+ // IN transfer: invalidate buffer, OUT transfer: clean buffer
+ if (dir) {
+ hcd_dcache_invalidate(buffer, buflen);
+ }else {
+ hcd_dcache_clean(buffer, buflen);
+ }
- // Insert TD to QH
- qtd_insert_to_qhd(p_qhd, p_qtd);
+ // attach TD to QHD -> start transferring
+ qhd_attach_qtd(qhd, qtd);
- p_qhd->p_qtd_list_tail->int_on_complete = 1;
+ return true;
+}
+
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
- // attach head QTD to QHD start transferring
- p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head;
+ // TODO ISO not supported yet
+ ehci_qhd_t* qhd = qhd_get_from_addr(dev_addr, ep_addr);
+ ehci_qtd_t * volatile qtd = qhd->attached_qtd;
+ TU_VERIFY(qtd != NULL); // no queued transfer
+
+ hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t));
+ TU_VERIFY(qtd->active); // transfer is already complete
+
+ // HC is still processing, disable HC list schedule before making changes
+ bool const is_period = (qhd->interval_ms > 0);
+
+ ehci_disable_schedule(ehci_data.regs, is_period);
+
+ // check active bit again just in case HC has just processed the TD
+ bool const still_active = qtd->active;
+ if (still_active) {
+ // remove TD from QH overlay
+ qhd->qtd_overlay.next.terminate = 1;
+ hcd_dcache_clean(qhd, sizeof(ehci_qhd_t));
+
+ // remove TD from QH software list
+ qhd_remove_qtd(qhd);
}
- return true;
+ ehci_enable_schedule(ehci_data.regs, is_period);
+
+ return still_active; // true if removed an active transfer
}
-bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
-{
- ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr);
- p_qhd->qtd_overlay.halted = 0;
- // TODO reset data toggle ?
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport;
+ ehci_qhd_t *qhd = qhd_get_from_addr(daddr, ep_addr);
+ qhd->qtd_overlay.halted = 0;
+ qhd->qtd_overlay.data_toggle = 0;
+ hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t));
+
return true;
}
@@ -476,343 +539,283 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
// async_advance is handshake between usb stack & ehci controller.
// This isr mean it is safe to modify previously removed queue head from async list.
// In tinyusb, queue head is only removed when device is unplugged.
-static void async_advance_isr(uint8_t rhport)
+TU_ATTR_ALWAYS_INLINE static inline
+void async_advance_isr(uint8_t rhport)
{
(void) rhport;
- ehci_qhd_t* qhd_pool = ehci_data.qhd_pool;
- for(uint32_t i = 0; i < QHD_MAX; i++)
- {
- if ( qhd_pool[i].removing )
- {
+ ehci_qhd_t *qhd_pool = ehci_data.qhd_pool;
+ for (uint32_t i = 0; i < QHD_MAX; i++) {
+ if (qhd_pool[i].removing) {
qhd_pool[i].removing = 0;
- qhd_pool[i].used = 0;
+ qhd_pool[i].used = 0;
}
}
}
-static void port_connect_status_change_isr(uint8_t rhport)
-{
+TU_ATTR_ALWAYS_INLINE static inline
+void port_connect_status_change_isr(uint8_t rhport) {
// NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device
- if (ehci_data.regs->portsc_bm.current_connect_status)
- {
+ if ( ehci_data.regs->portsc_bm.current_connect_status ) {
hcd_port_reset(rhport);
hcd_event_device_attach(rhport, true);
- }else // device unplugged
+ } else // device unplugged
{
hcd_event_device_remove(rhport, true);
}
}
-static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
-{
- // free all TDs from the head td to the first active TD
- while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active)
- {
- ehci_qtd_t * volatile qtd = (ehci_qtd_t * volatile) p_qhd->p_qtd_list_head;
- bool const is_ioc = (qtd->int_on_complete != 0);
- uint8_t const ep_addr = tu_edpt_addr(p_qhd->ep_number, qtd->pid == EHCI_PID_IN ? 1 : 0);
-
- p_qhd->total_xferred_bytes += qtd->expected_bytes - qtd->total_bytes;
+// Check queue head for potential transfer complete (successful or error)
+TU_ATTR_ALWAYS_INLINE static inline
+void qhd_xfer_complete_isr(ehci_qhd_t * qhd) {
+ hcd_dcache_invalidate(qhd, sizeof(ehci_qhd_t)); // HC may have updated the overlay
+ volatile ehci_qtd_t *qtd_overlay = &qhd->qtd_overlay;
- // TD need to be freed and removed from qhd, before invoking callback
- qtd->used = 0; // free QTD
- qtd_remove_1st_from_qhd(p_qhd);
-
- if (is_ioc)
- {
- hcd_event_xfer_complete(p_qhd->dev_addr, ep_addr, p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true);
- p_qhd->total_xferred_bytes = 0;
- }
- }
-}
+ // process non-active (completed) QHD with attached (scheduled) TD
+ if ( !qtd_overlay->active && qhd->attached_qtd != NULL ) {
+ xfer_result_t xfer_result;
-static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
-{
- ehci_qhd_t *p_qhd = async_head;
- do
- {
- if ( !p_qhd->qtd_overlay.halted ) // halted or error is processed in error isr
- {
- qhd_xfer_complete_isr(p_qhd);
+ if ( qtd_overlay->halted ) {
+ if (qtd_overlay->xact_err || qtd_overlay->err_count == 0 || qtd_overlay->buffer_err || qtd_overlay->babble_err) {
+ // Error count = 0 often occurs when device disconnected, or other bus-related error
+ // clear halted bit if not caused by STALL to allow more transfer
+ xfer_result = XFER_RESULT_FAILED;
+ qtd_overlay->halted = false;
+ TU_LOG3(" QHD xfer err count: %d\r\n", qtd_overlay->err_count);
+ // TU_BREAKPOINT(); // TODO skip unplugged device
+ }else {
+ // no error bits are set, endpoint is halted due to STALL
+ xfer_result = XFER_RESULT_STALLED;
+ }
+ } else {
+ xfer_result = XFER_RESULT_SUCCESS;
}
- p_qhd = qhd_next(p_qhd);
- }while(p_qhd != async_head); // async list traversal, stop if loop around
-}
-
-static void period_list_xfer_complete_isr(uint8_t hostid, uint32_t interval_ms)
-{
- uint16_t max_loop = 0;
- uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u);
- ehci_link_t next_item = * get_period_head(hostid, interval_ms);
- // TODO abstract max loop guard for period
- while( !next_item.terminate &&
- !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) &&
- max_loop < (QHD_MAX + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX)
- {
- switch ( next_item.type )
- {
- case EHCI_QTYPE_QHD:
- {
- ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address);
- if ( !p_qhd_int->qtd_overlay.halted )
- {
- qhd_xfer_complete_isr(p_qhd_int);
- }
- }
- break;
+ ehci_qtd_t * volatile qtd = qhd->attached_qtd;
+ hcd_dcache_invalidate(qtd, sizeof(ehci_qtd_t)); // HC may have written back TD
- case EHCI_QTYPE_ITD: // TODO support hs/fs ISO
- case EHCI_QTYPE_SITD:
- case EHCI_QTYPE_FSTN:
+ uint8_t const dir = (qtd->pid == EHCI_PID_IN) ? 1 : 0;
+ uint32_t const xferred_bytes = qtd->expected_bytes - qtd->total_bytes;
- default: break;
+ // invalidate dcache if IN transfer with data
+ if (dir == 1 && qhd->attached_buffer != 0 && xferred_bytes > 0) {
+ hcd_dcache_invalidate((void*) qhd->attached_buffer, xferred_bytes);
}
- next_item = *list_next(&next_item);
- max_loop++;
+ // remove and free TD before invoking callback
+ qhd_remove_qtd(qhd);
+
+ // notify usbh
+ uint8_t const ep_addr = tu_edpt_addr(qhd->ep_number, dir);
+ hcd_event_xfer_complete(qhd->dev_addr, ep_addr, xferred_bytes, xfer_result, true);
}
}
-static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
+TU_ATTR_ALWAYS_INLINE static inline
+void proccess_async_xfer_isr(ehci_qhd_t * const list_head)
{
- if ( (p_qhd->dev_addr != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL
- qhd_has_xact_error(p_qhd) )
- {
- // current qhd has error in transaction
- xfer_result_t error_event;
-
- // no error bits are set, endpoint is halted due to STALL
- error_event = qhd_has_xact_error(p_qhd) ? XFER_RESULT_FAILED : XFER_RESULT_STALLED;
+ ehci_qhd_t *qhd = list_head;
- p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
-
-// if ( XFER_RESULT_FAILED == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device
-
- p_qhd->p_qtd_list_head->used = 0; // free QTD
- qtd_remove_1st_from_qhd(p_qhd);
-
- if ( 0 == p_qhd->ep_number )
- {
- // control cannot be halted --> clear all qtd list
- p_qhd->p_qtd_list_head = NULL;
- p_qhd->p_qtd_list_tail = NULL;
-
- p_qhd->qtd_overlay.next.terminate = 1;
- p_qhd->qtd_overlay.alternate.terminate = 1;
- p_qhd->qtd_overlay.halted = 0;
-
- ehci_qtd_t *p_setup = qtd_control(p_qhd->dev_addr);
- p_setup->used = 0;
- }
-
- // call USBH callback
- hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, error_event, true);
-
- p_qhd->total_xferred_bytes = 0;
- }
+ do {
+ qhd_xfer_complete_isr(qhd);
+ qhd = qhd_next(qhd);
+ } while ( qhd != list_head ); // async list traversal, stop if loop around
}
-static void xfer_error_isr(uint8_t hostid)
+TU_ATTR_ALWAYS_INLINE static inline
+void process_period_xfer_isr(uint8_t rhport, uint32_t interval_ms)
{
- //------------- async list -------------//
- ehci_qhd_t * const async_head = qhd_async_head(hostid);
- ehci_qhd_t *p_qhd = async_head;
- do
- {
- qhd_xfer_error_isr( p_qhd );
- p_qhd = qhd_next(p_qhd);
- }while(p_qhd != async_head); // async list traversal, stop if loop around
+ uint32_t const period_1ms_addr = (uint32_t) list_get_period_head(rhport, 1u);
+ ehci_link_t next_link = *list_get_period_head(rhport, interval_ms);
- //------------- TODO refractor period list -------------//
- uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u);
- for (uint32_t interval_ms=1; interval_ms <= FRAMELIST_SIZE; interval_ms *= 2)
- {
- ehci_link_t next_item = * get_period_head(hostid, interval_ms);
+ while (!next_link.terminate) {
+ if (interval_ms > 1 && period_1ms_addr == tu_align32(next_link.address)) {
+ // 1ms period list is end of list for all larger interval
+ break;
+ }
- // TODO abstract max loop guard for period
- while( !next_item.terminate &&
- !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) )
- {
- switch ( next_item.type )
- {
- case EHCI_QTYPE_QHD:
- {
- ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address);
- qhd_xfer_error_isr(p_qhd_int);
- }
- break;
+ uintptr_t const entry_addr = tu_align32(next_link.address);
- // TODO support hs/fs ISO
- case EHCI_QTYPE_ITD:
- case EHCI_QTYPE_SITD:
- case EHCI_QTYPE_FSTN:
- default: break;
+ switch (next_link.type) {
+ case EHCI_QTYPE_QHD: {
+ ehci_qhd_t *qhd = (ehci_qhd_t *) entry_addr;
+ qhd_xfer_complete_isr(qhd);
}
+ break;
- next_item = *list_next(&next_item);
+ // TODO support hs/fs ISO
+ case EHCI_QTYPE_ITD:
+ case EHCI_QTYPE_SITD:
+ case EHCI_QTYPE_FSTN:
+ default:
+ break;
}
- }
-}
-
-#if CFG_TUSB_DEBUG >= EHCI_DBG
-
-static inline void print_portsc(ehci_registers_t* regs)
-{
- TU_LOG_HEX(EHCI_DBG, regs->portsc);
- TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status);
- TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change);
- TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled);
- TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change);
- TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset);
- TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power);
+ next_link = *list_next(&next_link);
+ }
}
-#else
-
-#define print_portsc(_reg)
-
-#endif
-
//------------- Host Controller Driver's Interrupt Handler -------------//
-void hcd_int_handler(uint8_t rhport)
-{
+void hcd_int_handler(uint8_t rhport, bool in_isr) {
+ (void) in_isr;
ehci_registers_t* regs = ehci_data.regs;
+ uint32_t const int_status = regs->status;
- uint32_t int_status = regs->status;
- int_status &= regs->inten;
-
- regs->status = int_status; // Acknowledge handled interrupt
-
- if (int_status == 0) return;
+ if (int_status & EHCI_INT_MASK_HC_HALTED) {
+ // something seriously wrong, maybe forget to flush/invalidate cache
+ TU_BREAKPOINT();
+ TU_LOG1(" HC halted\r\n");
+ return;
+ }
- if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER)
- {
+ if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER) {
ehci_data.uframe_number += (FRAMELIST_SIZE << 3);
+ regs->status = EHCI_INT_MASK_FRAMELIST_ROLLOVER; // Acknowledge
}
- if (int_status & EHCI_INT_MASK_PORT_CHANGE)
- {
- uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
- print_portsc(regs);
+ if (int_status & EHCI_INT_MASK_PORT_CHANGE) {
+ // Including: Force port resume, over-current change, enable/disable change and connect status change.
+ uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_W1C;
+ // print_portsc(regs);
- if (regs->portsc_bm.connect_status_change)
- {
+ if (regs->portsc_bm.connect_status_change) {
port_connect_status_change_isr(rhport);
}
regs->portsc |= port_status; // Acknowledge change bits in portsc
+ regs->status = EHCI_INT_MASK_PORT_CHANGE; // Acknowledge
}
- if (int_status & EHCI_INT_MASK_ERROR)
- {
- xfer_error_isr(rhport);
- }
-
- //------------- some QTD/SITD/ITD with IOC set is completed -------------//
- if (int_status & EHCI_INT_MASK_NXP_ASYNC)
- {
- async_list_xfer_complete_isr( qhd_async_head(rhport) );
- }
+ // A USB transfer is completed (OK or error)
+ uint32_t const usb_int = int_status & (EHCI_INT_MASK_USB | EHCI_INT_MASK_ERROR);
+ if (usb_int) {
+ proccess_async_xfer_isr(list_get_async_head(rhport));
- if (int_status & EHCI_INT_MASK_NXP_PERIODIC)
- {
- for (uint32_t i=1; i <= FRAMELIST_SIZE; i *= 2)
- {
- period_list_xfer_complete_isr( rhport, i );
+ for ( uint32_t i = 1; i <= FRAMELIST_SIZE; i *= 2 ) {
+ process_period_xfer_isr(rhport, i);
}
+
+ regs->status = usb_int; // Acknowledge
}
//------------- There is some removed async previously -------------//
- if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC
- {
+ // need to place after EHCI_INT_MASK_NXP_ASYNC
+ if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) {
async_advance_isr(rhport);
+ regs->status = EHCI_INT_MASK_ASYNC_ADVANCE; // Acknowledge
}
}
//--------------------------------------------------------------------+
-// HELPER
+// List Managing Helper
//--------------------------------------------------------------------+
+// Get head of periodic list
+TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_get_period_head(uint8_t rhport, uint32_t interval_ms) {
+ (void) rhport;
+ return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min32(FRAMELIST_SIZE, interval_ms) ) ];
+}
-//------------- queue head helper -------------//
-static inline ehci_qhd_t* qhd_find_free (void)
-{
- for (uint32_t i=0; i<QHD_MAX; i++)
- {
- if ( !ehci_data.qhd_pool[i].used ) return &ehci_data.qhd_pool[i];
- }
+// Get head of async list
+TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* list_get_async_head(uint8_t rhport) {
+ (void) rhport;
+ return qhd_control(0); // control qhd of dev0 is used as async head
+}
- return NULL;
+TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_next(ehci_link_t const *p_link) {
+ return (ehci_link_t*) tu_align32(p_link->address);
}
-static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd)
+TU_ATTR_ALWAYS_INLINE static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type)
{
- return (ehci_qhd_t*) tu_align32(p_qhd->next.address);
+ new->address = current->address;
+ current->address = ((uint32_t) new) | (new_type << 1);
}
-static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr)
-{
- ehci_qhd_t* qhd_pool = ehci_data.qhd_pool;
+// Remove all queue head belong to this device address
+static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr) {
+ ehci_link_t* prev = list_head;
- for(uint32_t i=0; i<QHD_MAX; i++)
- {
- if ( (qhd_pool[i].dev_addr == dev_addr) &&
- ep_addr == tu_edpt_addr(qhd_pool[i].ep_number, qhd_pool[i].pid) )
- {
- return &qhd_pool[i];
+ while (prev && !prev->terminate) {
+ ehci_qhd_t* qhd = (ehci_qhd_t*) (uintptr_t) list_next(prev);
+
+ // done if loop back to head
+ if ( (uintptr_t) qhd == (uintptr_t) list_head) {
+ break;
+ }
+
+ if ( qhd->dev_addr == dev_addr ) {
+ // TODO deactivate all TD, wait for QHD to inactive before removal
+ prev->address = qhd->next.address;
+
+ // EHCI 4.8.2 link the removed qhd's next to async head (which always reachable by Host Controller)
+ qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1);
+
+ if ( qhd->int_smask )
+ {
+ // period list queue element is guarantee to be free in the next frame (1 ms)
+ qhd->used = 0;
+ }else
+ {
+ // async list use async advance handshake
+ // mark as removing, will completely re-usable when async advance isr occurs
+ qhd->removing = 1;
+ }
+
+ hcd_dcache_clean(qhd, sizeof(ehci_qhd_t));
+ hcd_dcache_clean(prev, sizeof(ehci_qhd_t));
+ }else {
+ prev = list_next(prev);
}
}
+}
- return NULL;
+
+//--------------------------------------------------------------------+
+// Queue Header helper
+//--------------------------------------------------------------------+
+
+// Get queue head for control transfer (always available)
+TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* qhd_control(uint8_t dev_addr) {
+ return &ehci_data.control[dev_addr].qhd;
}
-//------------- TD helper -------------//
-static inline ehci_qtd_t* qtd_find_free(void)
-{
- for (uint32_t i=0; i<QTD_MAX; i++)
- {
- if ( !ehci_data.qtd_pool[i].used ) return &ehci_data.qtd_pool[i];
+// Find a free queue head
+TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t *qhd_find_free(void) {
+ for ( uint32_t i = 0; i < QHD_MAX; i++ ) {
+ if ( !ehci_data.qhd_pool[i].used ) return &ehci_data.qhd_pool[i];
}
-
return NULL;
}
-static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
-{
- return (ehci_qtd_t*) tu_align32(p_qtd->next.address);
+// Next queue head link
+TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t *qhd_next(ehci_qhd_t const *p_qhd) {
+ return (ehci_qhd_t *) tu_align32(p_qhd->next.address);
}
-static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd)
-{
- if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL
- {
- p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL;
- }else
- {
- p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head );
+// Get queue head from device + endpoint address
+static ehci_qhd_t *qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) {
+ if ( 0 == tu_edpt_number(ep_addr) ) {
+ return qhd_control(dev_addr);
}
-}
-static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new)
-{
- if (p_qhd->p_qtd_list_head == NULL) // empty list
- {
- p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new;
- }else
- {
- p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new;
- p_qhd->p_qtd_list_tail = p_qtd_new;
+ ehci_qhd_t *qhd_pool = ehci_data.qhd_pool;
+
+ for ( uint32_t i = 0; i < QHD_MAX; i++ ) {
+ if ( (qhd_pool[i].dev_addr == dev_addr) &&
+ ep_addr == tu_edpt_addr(qhd_pool[i].ep_number, qhd_pool[i].pid) ) {
+ return &qhd_pool[i];
+ }
}
+
+ return NULL;
}
+// Init queue head with endpoint descriptor
static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
{
// address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise)
- if (dev_addr != 0)
- {
+ if (dev_addr != 0) {
tu_memclr(p_qhd, sizeof(ehci_qhd_t));
}
@@ -862,58 +865,84 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
p_qhd->int_smask = p_qhd->fl_int_cmask = 0;
}
- p_qhd->fl_hub_addr = devtree_info.hub_addr;
- p_qhd->fl_hub_port = devtree_info.hub_port;
- p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
+ p_qhd->fl_hub_addr = devtree_info.hub_addr;
+ p_qhd->fl_hub_port = devtree_info.hub_port;
+ p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
//------------- HCD Management Data -------------//
- p_qhd->used = 1;
- p_qhd->removing = 0;
- p_qhd->p_qtd_list_head = NULL;
- p_qhd->p_qtd_list_tail = NULL;
+ p_qhd->used = 1;
+ p_qhd->removing = 0;
+ p_qhd->attached_qtd = NULL;
p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
//------------- active, but no TD list -------------//
p_qhd->qtd_overlay.halted = 0;
p_qhd->qtd_overlay.next.terminate = 1;
p_qhd->qtd_overlay.alternate.terminate = 1;
+
if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT)
{
p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
}
}
-static void qtd_init(ehci_qtd_t* p_qtd, void const* buffer, uint16_t total_bytes)
-{
- tu_memclr(p_qtd, sizeof(ehci_qtd_t));
+// Attach a TD to queue head
+static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd) {
+ qhd->attached_qtd = qtd;
+ qhd->attached_buffer = qtd->buffer[0];
- p_qtd->used = 1;
+ // clean and invalidate cache before physically write
+ hcd_dcache_clean_invalidate(qtd, sizeof(ehci_qtd_t));
- p_qtd->next.terminate = 1; // init to null
- p_qtd->alternate.terminate = 1; // not used, always set to terminated
- p_qtd->active = 1;
- p_qtd->err_count = 3; // TODO 3 consecutive errors tolerance
- p_qtd->data_toggle = 0;
- p_qtd->total_bytes = total_bytes;
- p_qtd->expected_bytes = total_bytes;
+ qhd->qtd_overlay.next.address = (uint32_t) qtd;
+ hcd_dcache_clean_invalidate(qhd, sizeof(ehci_qhd_t));
+}
- p_qtd->buffer[0] = (uint32_t) buffer;
- for(uint8_t i=1; i<5; i++)
- {
- p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096;
- }
+// Remove an attached TD from queue head
+static void qhd_remove_qtd(ehci_qhd_t *qhd) {
+ ehci_qtd_t * volatile qtd = qhd->attached_qtd;
+
+ qhd->attached_qtd = NULL;
+ qhd->attached_buffer = 0;
+ hcd_dcache_clean(qhd, sizeof(ehci_qhd_t));
+
+ qtd->used = 0; // free QTD
+ hcd_dcache_clean(qtd, sizeof(ehci_qtd_t));
}
-//------------- List Managing Helper -------------//
-static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type)
-{
- new->address = current->address;
- current->address = ((uint32_t) new) | (new_type << 1);
+//--------------------------------------------------------------------+
+// Queue TD helper
+//--------------------------------------------------------------------+
+
+// Get TD for control transfer (always available)
+TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t* qtd_control(uint8_t dev_addr) {
+ return &ehci_data.control[dev_addr].qtd;
}
-static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer)
-{
- return (ehci_link_t*) tu_align32(p_link_pointer->address);
+TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t *qtd_find_free(void) {
+ for (uint32_t i = 0; i < QTD_MAX; i++) {
+ if (!ehci_data.qtd_pool[i].used) return &ehci_data.qtd_pool[i];
+ }
+ return NULL;
+}
+
+static void qtd_init(ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes) {
+ tu_memclr(qtd, sizeof(ehci_qtd_t));
+ qtd->used = 1;
+
+ qtd->next.terminate = 1; // init to null
+ qtd->alternate.terminate = 1; // not used, always set to terminated
+ qtd->active = 1;
+ qtd->err_count = 3; // TODO 3 consecutive errors tolerance
+ qtd->data_toggle = 0;
+ qtd->int_on_complete = 1;
+ qtd->total_bytes = total_bytes;
+ qtd->expected_bytes = total_bytes;
+
+ qtd->buffer[0] = (uint32_t) buffer;
+ for(uint8_t i=1; i<5; i++) {
+ qtd->buffer[i] |= tu_align4k(qtd->buffer[i - 1] ) + 4096;
+ }
}
#endif
diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h
index 36f8649be..457adc1d3 100644
--- a/src/portable/ehci/ehci.h
+++ b/src/portable/ehci/ehci.h
@@ -81,6 +81,8 @@ typedef union {
};
}ehci_link_t;
+TU_VERIFY_STATIC( sizeof(ehci_link_t) == 4, "size is not correct" );
+
/// Queue Element Transfer Descriptor
/// Qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with TU_ATTR_ALIGNED(32)
typedef struct
@@ -162,11 +164,12 @@ typedef struct TU_ATTR_ALIGNED(32)
uint8_t pid;
uint8_t interval_ms; // polling interval in frames (or millisecond)
- uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set
- uint8_t reserved2[2];
+ uint8_t TU_RESERVED[4];
- ehci_qtd_t * volatile p_qtd_list_head; // head of the scheduled TD list
- ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list
+ // Attached TD management, note usbh will only queue 1 TD per QHD.
+ // buffer for dcache invalidate since td's buffer is modified by HC and finding initial buffer address is not trivial
+ uint32_t attached_buffer;
+ ehci_qtd_t * volatile attached_qtd;
} ehci_qhd_t;
TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" );
@@ -245,14 +248,6 @@ typedef struct TU_ATTR_ALIGNED(32)
/// Word 4-5: Buffer Pointer List
uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count
-// union{
-// uint32_t BufferPointer1;
-// struct {
-// volatile uint32_t TCount : 3;
-// volatile uint32_t TPosition : 2;
-// };
-// };
-
/*---------- Word 6 ----------*/
ehci_link_t back;
@@ -267,53 +262,63 @@ TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" );
//--------------------------------------------------------------------+
// EHCI Operational Register
//--------------------------------------------------------------------+
-enum ehci_interrupt_mask_{
+enum {
+ // Bit 0-5 has maskable in interrupt enabled register
EHCI_INT_MASK_USB = TU_BIT(0),
EHCI_INT_MASK_ERROR = TU_BIT(1),
EHCI_INT_MASK_PORT_CHANGE = TU_BIT(2),
-
EHCI_INT_MASK_FRAMELIST_ROLLOVER = TU_BIT(3),
EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR = TU_BIT(4),
EHCI_INT_MASK_ASYNC_ADVANCE = TU_BIT(5),
+
EHCI_INT_MASK_NXP_SOF = TU_BIT(7),
- EHCI_INT_MASK_NXP_ASYNC = TU_BIT(18),
- EHCI_INT_MASK_NXP_PERIODIC = TU_BIT(19),
+ EHCI_INT_MASK_HC_HALTED = TU_BIT(12),
+ EHCI_INT_MASK_RECLAIMATION = TU_BIT(13),
+ EHCI_INT_MASK_PERIODIC_SCHED_STATUS = TU_BIT(14),
+ EHCI_INT_MASK_ASYNC_SCHED_STATUS = TU_BIT(15),
EHCI_INT_MASK_ALL =
EHCI_INT_MASK_USB | EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
EHCI_INT_MASK_FRAMELIST_ROLLOVER | EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR |
- EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_SOF |
- EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_NXP_PERIODIC
+ EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_SOF
};
-enum ehci_usbcmd_pos_ {
- EHCI_USBCMD_POS_RUN_STOP = 0,
- EHCI_USBCMD_POS_FRAMELIST_SIZE = 2,
- EHCI_USBCMD_POS_PERIOD_ENABLE = 4,
- EHCI_USBCMD_POS_ASYNC_ENABLE = 5,
- EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB = 15,
- EHCI_USBCMD_POS_INTERRUPT_THRESHOLD = 16
+enum {
+ EHCI_USBCMD_FRAMELIST_SIZE_SHIFT = 2, // [2..3]
+ EHCI_USBCMD_CHIPIDEA_FRAMELIST_SIZE_MSB_SHIFT = 15,
+ EHCI_USBCMD_INTERRUPT_THRESHOLD_SHIFT = 16
};
-enum ehci_portsc_change_mask_{
+enum {
+ EHCI_USBCMD_RUN_STOP = TU_BIT(0), // [0..0] 1 = Run, 0 = Stop
+ EHCI_USBCMD_HCRESET = TU_BIT(1), // [1..1] SW write 1 to reset HC, clear by HC when complete
+ EHCI_USBCMD_PERIOD_SCHEDULE_ENABLE = TU_BIT(4), // [4..4] Enable periodic schedule
+ EHCI_USBCMD_ASYNC_SCHEDULE_ENABLE = TU_BIT(5), // [5..5] Enable async schedule
+ EHCI_USBCMD_INTR_ON_ASYNC_ADVANCE_DOORBELL = TU_BIT(6), // [6..6] Tell HC to interrupt next time it advances async list. Clear by HC
+};
+
+enum {
EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0),
EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1),
EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2),
- EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3),
+ EHCI_PORTSC_MASK_PORT_ENABLE_CHANGE = TU_BIT(3),
EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5),
+ EHCI_PORTSC_MASK_FORCE_RESUME = TU_BIT(6),
+ EHCI_PORTSC_MASK_PORT_SUSPEND = TU_BIT(7),
EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8),
+ EHCI_PORTSC_MASK_PORT_POWER = TU_BIT(12),
- EHCI_PORTSC_MASK_ALL =
- EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE |
- EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE |
- EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE
+ EHCI_PORTSC_MASK_W1C =
+ EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE |
+ EHCI_PORTSC_MASK_PORT_ENABLE_CHANGE |
+ EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE
};
typedef volatile struct
{
union {
- uint32_t command;
+ uint32_t command; // 0x00
struct {
uint32_t run_stop : 1 ; ///< 1=Run. 0=Stop
@@ -333,7 +338,7 @@ typedef volatile struct
};
union {
- uint32_t status;
+ uint32_t status; // 0x04
struct {
uint32_t usb : 1 ; ///< qTD with IOC is retired
@@ -357,7 +362,7 @@ typedef volatile struct
};
union{
- uint32_t inten;
+ uint32_t inten; // 0x08
struct {
uint32_t usb : 1 ;
@@ -375,43 +380,87 @@ typedef volatile struct
}inten_bm;
};
- uint32_t frame_index ; ///< Micro frame counter
- uint32_t ctrl_ds_seg ; ///< Control Data Structure Segment
- uint32_t periodic_list_base ; ///< Beginning address of perodic frame list
- uint32_t async_list_addr ; ///< Address of next async QHD to be executed
+ uint32_t frame_index ; ///< 0x0C Micro frame counter
+ uint32_t ctrl_ds_seg ; ///< 0x10 Control Data Structure Segment
+ uint32_t periodic_list_base ; ///< 0x14 Beginning address of perodic frame list
+ uint32_t async_list_addr ; ///< 0x18 Address of next async QHD to be executed
uint32_t nxp_tt_control ; ///< nxp embedded transaction translator (reserved by EHCI specs)
uint32_t reserved[8] ;
- uint32_t config_flag ; ///< not used by NXP
+ uint32_t config_flag ; ///< 0x40 not used by NXP
union {
- uint32_t portsc ; ///< port status and control
- struct {
- uint32_t current_connect_status : 1; ///< 0: No device, 1: Device is present on port
- uint32_t connect_status_change : 1; ///< Change in Current Connect Status
- uint32_t port_enabled : 1; ///< Ports can only be enabled by HC as a part of the reset and enable. SW can write 0 to disable
- uint32_t port_enable_change : 1; ///< Port Enabled has changed
- uint32_t over_current_active : 1; ///< Port has an over-current condition
- uint32_t over_current_change : 1; ///< Change to Over-current Active
- uint32_t force_port_resume : 1; ///< Resume detected/driven on port. This functionality defined for manipulating this bit depends on the value of the Suspend bit.
- uint32_t suspend : 1; ///< Port in suspend state
- uint32_t port_reset : 1; ///< 1=Port is in Reset. 0=Port is not in Reset
- uint32_t nxp_highspeed_status : 1; ///< NXP customized: 0=connected to the port is not in High-speed mode, 1=connected to the port is in High-speed mode
- uint32_t line_status : 2; ///< D+/D- state: 00: SE0, 10: J-state, 01: K-state
- uint32_t port_power : 1; ///< 0= power off, 1= power on
- uint32_t port_owner : 1; ///< not used by NXP
- uint32_t port_indicator_control : 2; ///< 00b: off, 01b: Amber, 10b: green, 11b: undefined
- uint32_t port_test_control : 4; ///< Port test mode, not used by tinyusb
- uint32_t wake_on_connect_enable : 1; ///< Enables device connects as wake-up events
- uint32_t wake_on_disconnect_enable : 1; ///< Enables device disconnects as wake-up events
- uint32_t wake_on_over_current_enable : 1; ///< Enables over-current conditions as wake-up events
- uint32_t nxp_phy_clock_disable : 1; ///< NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock
- uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device.
- uint32_t TU_RESERVED : 1;
- uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed
+ // mixed with RW and R/WC bits, care should be taken when writing to this register
+ uint32_t portsc ; ///< 0x44 port status and control
+ const struct {
+ uint32_t current_connect_status : 1; ///< 00: 0: No device, 1: Device is present on port
+ uint32_t connect_status_change : 1; ///< 01: [R/WC] Change in Current Connect Status
+ uint32_t port_enabled : 1; ///< 02: Ports can only be enabled by HC as a part of the reset and enable. SW can write 0 to disable
+ uint32_t port_enable_change : 1; ///< 03: [R/WC] Port Enabled has changed
+ uint32_t over_current_active : 1; ///< 04: Port has an over-current condition
+ uint32_t over_current_change : 1; ///< 05: [R/WC] Change to Over-current Active
+ uint32_t force_port_resume : 1; ///< 06: Resume detected/driven on port. This functionality defined for manipulating this bit depends on the value of the Suspend bit.
+ uint32_t suspend : 1; ///< 07: Port in suspend state
+ uint32_t port_reset : 1; ///< 08: 1=Port is in Reset. 0=Port is not in Reset
+ uint32_t nxp_highspeed_status : 1; ///< 09: NXP customized: 0=connected to the port is not in High-speed mode, 1=connected to the port is in High-speed mode
+ uint32_t line_status : 2; ///< 10-11: D+/D- state: 00: SE0, 10: J-state, 01: K-state
+ uint32_t port_power : 1; ///< 12: 0= power off, 1= power on
+ uint32_t port_owner : 1; ///< 13: not used by NXP
+ uint32_t port_indicator_control : 2; ///< 14-15: 00b: off, 01b: Amber, 10b: green, 11b: undefined
+ uint32_t port_test_control : 4; ///< 16-19: Port test mode, not used by tinyusb
+ uint32_t wake_on_connect_enable : 1; ///< 20: Enables device connects as wake-up events
+ uint32_t wake_on_disconnect_enable : 1; ///< 21: Enables device disconnects as wake-up events
+ uint32_t wake_on_over_current_enable : 1; ///< 22: Enables over-current conditions as wake-up events
+ uint32_t nxp_phy_clock_disable : 1; ///< 23: NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock
+ uint32_t nxp_port_force_fullspeed : 1; ///< 24: NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device.
+ uint32_t TU_RESERVED : 1; ///< 25
+ uint32_t nxp_port_speed : 2; ///< 26-27: NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed
uint32_t TU_RESERVED : 4;
}portsc_bm;
};
-}ehci_registers_t;
+} ehci_registers_t;
+
+//--------------------------------------------------------------------+
+// Capability Registers
+//--------------------------------------------------------------------+
+typedef volatile struct {
+ uint8_t caplength; // 0x00
+ uint8_t TU_RESERVED; // 0x01
+ uint16_t hciversion; // 0x02
+
+ union {
+ uint32_t hcsparams; // 0x04
+ struct {
+ uint32_t num_ports : 4; // [00:03]
+ uint32_t port_power_control : 1; // [04]
+ uint32_t TU_RESERVED : 2; // [05:06]
+ uint32_t port_route_rule : 1; // [07]
+ uint32_t n_pcc : 4; // [08:11] Number of Ports per Companion Controller
+ uint32_t n_cc : 4; // [12:15] Number of Companion Controllers
+ uint32_t port_ind : 1; // [16] Port Indicators
+ uint32_t TU_RESERVED : 3; // [17:19]
+ uint32_t n_ptt : 4; // [20:23] ChipIdea: Number of Ports per Transaction Translator
+ uint32_t n_tt : 4; // [24:27] ChipIdea: Number of Transaction Translators
+ uint32_t TU_RESERVED : 4; // [28:31]
+ } hcsparams_bm;
+ };
+
+ union {
+ uint32_t hccparams; // 0x08
+ struct {
+ uint32_t addr_64bit : 1; // [00] 64-bit Addressing Capability
+ uint32_t programmable_frame_list_flag : 1; // [01] Programmable Frame List Flag
+ uint32_t async_park_cap : 1; // [02] Asynchronous Schedule Park Capability
+ uint32_t TU_RESERVED : 1; // [03]
+ uint32_t iso_schedule_threshold : 4; // [4:7] Isochronous Scheduling Threshold
+ uint32_t eecp : 8; // [8:15] EHCI Extended Capabilities Pointer
+ uint32_t TU_RESERVED : 16;// [16:31]
+ } hccparams_bm;
+ };
+
+ uint32_t hcsp_portroute; // 0x0C HCSP Port Route Register
+} ehci_cap_registers_t;
+
+TU_VERIFY_STATIC(sizeof(ehci_cap_registers_t) == 16, "size is not correct");
#ifdef __cplusplus
}
diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c
index 1fcfb6241..bfc0baa56 100644
--- a/src/portable/espressif/esp32sx/dcd_esp32sx.c
+++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c
@@ -31,16 +31,26 @@
#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && CFG_TUD_ENABLED)
// Espressif
-#include "freertos/xtensa_api.h"
+#include "xtensa_api.h"
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "soc/dport_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/usb_periph.h"
+#include "soc/usb_reg.h"
+#include "soc/usb_struct.h"
#include "soc/periph_defs.h" // for interrupt source
#include "device/dcd.h"
+#ifndef USB_OUT_EP_NUM
+#define USB_OUT_EP_NUM ((int) (sizeof(USB0.out_ep_reg) / sizeof(USB0.out_ep_reg[0])))
+#endif
+
+#ifndef USB_IN_EP_NUM
+#define USB_IN_EP_NUM ((int) (sizeof(USB0.in_ep_reg) / sizeof(USB0.in_ep_reg[0])))
+#endif
+
// Max number of bi-directional endpoints including EP0
// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0
// We should probably prohibit enabling Endpoint IN > 4 (not done yet)
diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c
index 487761847..a817c5d6e 100644
--- a/src/portable/mentor/musb/dcd_musb.c
+++ b/src/portable/mentor/musb/dcd_musb.c
@@ -158,9 +158,9 @@ static inline unsigned free_block_size(free_block_t const *blk)
#if 0
static inline void print_block_list(free_block_t const *blk, unsigned num)
{
- TU_LOG1("*************\n");
+ TU_LOG1("*************\r\n");
for (unsigned i = 0; i < num; ++i) {
- TU_LOG1(" Blk%u %u %u\n", i, blk->beg, blk->end);
+ TU_LOG1(" Blk%u %u %u\r\n", i, blk->beg, blk->end);
++blk;
}
}
@@ -317,7 +317,7 @@ static bool handle_xfer_in(uint_fast8_t ep_addr)
const unsigned mps = regs->TXMAXP;
const unsigned len = TU_MIN(mps, rem);
void *buf = pipe->buf;
- // TU_LOG1(" %p mps %d len %d rem %d\n", buf, mps, len, rem);
+ // TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem);
if (len) {
if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) {
pipe_read_write_packet_ff(buf, &USB0->FIFO1_WORD + epnum_minus1, len, TUSB_DIR_IN);
@@ -328,7 +328,7 @@ static bool handle_xfer_in(uint_fast8_t ep_addr)
pipe->remaining = rem - len;
}
regs->TXCSRL = USB_TXCSRL1_TXRDY;
- // TU_LOG1(" TXCSRL%d = %x %d\n", epnum_minus1 + 1, regs->TXCSRL, rem - len);
+ // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum_minus1 + 1, regs->TXCSRL, rem - len);
return false;
}
@@ -337,7 +337,7 @@ static bool handle_xfer_out(uint_fast8_t ep_addr)
unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1;
pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
volatile hw_endpoint_t *regs = edpt_regs(epnum_minus1);
- // TU_LOG1(" RXCSRL%d = %x\n", epnum_minus1 + 1, regs->RXCSRL);
+ // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, regs->RXCSRL);
TU_ASSERT(regs->RXCSRL & USB_RXCSRL1_RXRDY);
@@ -399,14 +399,14 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_
* may have already finished and received the next setup packet
* without calling this function, so we have no choice but to
* invoke the callback function of status packet here. */
- // TU_LOG1(" STATUS OUT USB0->CSRL0 = %x\n", USB0->CSRL0);
+ // TU_LOG1(" STATUS OUT USB0->CSRL0 = %x\r\n", USB0->CSRL0);
_dcd.status_out = 0;
if (req == REQUEST_TYPE_INVALID) {
dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false);
} else {
/* The next setup packet has already been received, it aborts
* invoking callback function to avoid confusing TUSB stack. */
- TU_LOG1("Drop CONTROL_STAGE_ACK\n");
+ TU_LOG1("Drop CONTROL_STAGE_ACK\r\n");
}
return true;
}
@@ -431,16 +431,16 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_
} else {
USB0->CSRL0 = USB_CSRL0_TXRDY; /* Flush TX FIFO to return ACK. */
}
- // TU_LOG1(" IN USB0->CSRL0 = %x\n", USB0->CSRL0);
+ // TU_LOG1(" IN USB0->CSRL0 = %x\r\n", USB0->CSRL0);
} else {
- // TU_LOG1(" OUT USB0->CSRL0 = %x\n", USB0->CSRL0);
+ // TU_LOG1(" OUT USB0->CSRL0 = %x\r\n", USB0->CSRL0);
_dcd.pipe0.buf = buffer;
_dcd.pipe0.length = len;
_dcd.pipe0.remaining = len;
USB0->CSRL0 = USB_CSRL0_RXRDYC; /* Clear RX FIFO to return ACK. */
}
} else if (dir_in) {
- // TU_LOG1(" STATUS IN USB0->CSRL0 = %x\n", USB0->CSRL0);
+ // TU_LOG1(" STATUS IN USB0->CSRL0 = %x\r\n", USB0->CSRL0);
_dcd.pipe0.buf = NULL;
_dcd.pipe0.length = 0;
_dcd.pipe0.remaining = 0;
@@ -454,7 +454,7 @@ static void process_ep0(uint8_t rhport)
{
uint_fast8_t csrl = USB0->CSRL0;
- // TU_LOG1(" EP0 USB0->CSRL0 = %x\n", csrl);
+ // TU_LOG1(" EP0 USB0->CSRL0 = %x\r\n", csrl);
if (csrl & USB_CSRL0_STALLED) {
/* Returned STALL packet to HOST. */
@@ -464,7 +464,7 @@ static void process_ep0(uint8_t rhport)
unsigned req = _dcd.setup_packet.bmRequestType;
if (csrl & USB_CSRL0_SETEND) {
- TU_LOG1(" ABORT by the next packets\n");
+ TU_LOG1(" ABORT by the next packets\r\n");
USB0->CSRL0 = USB_CSRL0_SETENDC;
if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) {
/* DATA stage was aborted by receiving STATUS or SETUP packet. */
@@ -539,14 +539,14 @@ static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr)
volatile hw_endpoint_t *regs = edpt_regs(epn_minus1);
if (dir_in) {
- // TU_LOG1(" TXCSRL%d = %x\n", epn_minus1 + 1, regs->TXCSRL);
+ // TU_LOG1(" TXCSRL%d = %x\r\n", epn_minus1 + 1, regs->TXCSRL);
if (regs->TXCSRL & USB_TXCSRL1_STALLED) {
regs->TXCSRL &= ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_UNDRN);
return;
}
completed = handle_xfer_in(ep_addr);
} else {
- // TU_LOG1(" RXCSRL%d = %x\n", epn_minus1 + 1, regs->RXCSRL);
+ // TU_LOG1(" RXCSRL%d = %x\r\n", epn_minus1 + 1, regs->RXCSRL);
if (regs->RXCSRL & USB_RXCSRL1_STALLED) {
regs->RXCSRL &= ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_OVER);
return;
@@ -789,7 +789,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
{
(void)rhport;
bool ret;
- // TU_LOG1("X %x %d\n", ep_addr, total_bytes);
+ // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
unsigned const epnum = tu_edpt_number(ep_addr);
unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
NVIC_DisableIRQ(USB0_IRQn);
@@ -807,7 +807,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_
{
(void)rhport;
bool ret;
- // TU_LOG1("X %x %d\n", ep_addr, total_bytes);
+ // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
unsigned const epnum = tu_edpt_number(ep_addr);
TU_ASSERT(epnum);
unsigned const ie = NVIC_GetEnableIRQ(USB0_IRQn);
@@ -869,7 +869,7 @@ void dcd_int_handler(uint8_t rhport)
is = USB0->IS; /* read and clear interrupt status */
txis = USB0->TXIS; /* read and clear interrupt status */
rxis = USB0->RXIS; /* read and clear interrupt status */
- // TU_LOG1("D%2x T%2x R%2x\n", is, txis, rxis);
+ // TU_LOG1("D%2x T%2x R%2x\r\n", is, txis, rxis);
is &= USB0->IE; /* Clear disabled interrupts */
if (is & USB_IS_DISCON) {
diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c
index 9eb2e005e..5312c2812 100644
--- a/src/portable/mentor/musb/hcd_musb.c
+++ b/src/portable/mentor/musb/hcd_musb.c
@@ -418,7 +418,7 @@ static void process_ep0(uint8_t rhport)
(void)rhport;
uint_fast8_t csrl = USB0->CSRL0;
- // TU_LOG1(" EP0 CSRL = %x\n", csrl);
+ // TU_LOG1(" EP0 CSRL = %x\r\n", csrl);
unsigned const dev_addr = USB0->TXFUNCADDR0;
unsigned const req = _hcd.bmRequestType;
@@ -508,7 +508,7 @@ static void process_pipe_tx(uint8_t rhport, uint_fast8_t pipenum)
volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1);
unsigned const csrl = regs->TXCSRL;
- // TU_LOG1(" TXCSRL%d = %x\n", pipenum, csrl);
+ // TU_LOG1(" TXCSRL%d = %x\r\n", pipenum, csrl);
if (csrl & (USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR)) {
if (csrl & USB_TXCSRL1_TXRDY)
regs->TXCSRL = (csrl & ~(USB_TXCSRL1_STALLED | USB_TXCSRL1_ERROR)) | USB_TXCSRL1_FLUSH;
@@ -537,7 +537,7 @@ static void process_pipe_rx(uint8_t rhport, uint_fast8_t pipenum)
volatile hw_endpoint_t *regs = edpt_regs(pipenum - 1);
unsigned const csrl = regs->RXCSRL;
- // TU_LOG1(" RXCSRL%d = %x\n", pipenum, csrl);
+ // TU_LOG1(" RXCSRL%d = %x\r\n", pipenum, csrl);
if (csrl & (USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR)) {
if (csrl & USB_RXCSRL1_RXRDY)
regs->RXCSRL = (csrl & ~(USB_RXCSRL1_STALLED | USB_RXCSRL1_ERROR)) | USB_RXCSRL1_FLUSH;
@@ -822,9 +822,17 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b
return ret;
}
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+ // TODO not implemented yet
+ return false;
+}
+
// clear stall, data toggle is also reset to DATA0
-bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
-{
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
unsigned const pipenum = find_pipe(dev_addr, ep_addr);
if (!pipenum) return false;
hw_endpoint_t volatile *regs = edpt_regs(pipenum - 1);
@@ -839,14 +847,16 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
/*-------------------------------------------------------------------
* ISR
*-------------------------------------------------------------------*/
-void hcd_int_handler(uint8_t rhport)
+void hcd_int_handler(uint8_t rhport, bool in_isr)
{
+ (void) in_isr;
+
uint_fast8_t is, txis, rxis;
is = USB0->IS; /* read and clear interrupt status */
txis = USB0->TXIS; /* read and clear interrupt status */
rxis = USB0->RXIS; /* read and clear interrupt status */
- // TU_LOG1("D%2x T%2x R%2x\n", is, txis, rxis);
+ // TU_LOG1("D%2x T%2x R%2x\r\n", is, txis, rxis);
is &= USB0->IE; /* Clear disabled interrupts */
if (is & USB_IS_RESUME) {
diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c
index 6986c8317..ccc27c3c9 100644
--- a/src/portable/microchip/pic/dcd_pic.c
+++ b/src/portable/microchip/pic/dcd_pic.c
@@ -189,7 +189,7 @@ typedef struct
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
// BDT(Buffer Descriptor Table) must be 256-byte aligned
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) volatile static dcd_data_t _dcd;
+CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(512) volatile static dcd_data_t _dcd;
#if TU_PIC_INT_SIZE == 4
TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" );
diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c
index 2bbb345d6..9586df84d 100644
--- a/src/portable/microchip/samx7x/dcd_samx7x.c
+++ b/src/portable/microchip/samx7x/dcd_samx7x.c
@@ -77,7 +77,7 @@ static tusb_speed_t get_speed(void);
static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix);
// DMA descriptors shouldn't be placed in ITCM !
-CFG_TUSB_MEM_SECTION static dma_desc_t dma_desc[6];
+CFG_TUD_MEM_SECTION static dma_desc_t dma_desc[6];
static xfer_ctl_t xfer_status[EP_MAX];
diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c
index 39b09db68..c3d0c7297 100644
--- a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c
+++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c
@@ -110,7 +110,7 @@ typedef struct
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
// BDT(Buffer Descriptor Table) must be 256-byte aligned
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd;
+CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd;
TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" );
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index eee5686f4..80a285ef0 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -29,10 +29,24 @@
#if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_NRF5X
#include <stdatomic.h>
+
+// Suppress warning caused by nrfx driver
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#pragma GCC diagnostic ignored "-Wcast-align"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
#include "nrf.h"
#include "nrf_clock.h"
#include "nrf_power.h"
#include "nrfx_usbd_errata.h"
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
#include "device/dcd.h"
// TODO remove later
@@ -232,7 +246,7 @@ static void xact_in_dma(uint8_t epnum)
//--------------------------------------------------------------------+
void dcd_init (uint8_t rhport)
{
- TU_LOG1("dcd init\r\n");
+ TU_LOG2("dcd init\r\n");
(void) rhport;
}
@@ -326,6 +340,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
NRF_USBD->INTENSET = TU_BIT(USBD_INTEN_ENDEPIN0_Pos + epnum);
NRF_USBD->EPINEN |= TU_BIT(epnum);
}
+ // clear stall and reset DataToggle
+ NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
+ NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr;
}
else
{
@@ -361,10 +378,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
}
}
- // clear stall and reset DataToggle
- NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
- NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr;
-
__ISB(); __DSB();
return true;
@@ -640,7 +653,11 @@ void dcd_int_handler(uint8_t rhport)
if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk)
{
iso_enabled = true;
- xact_out_dma(EP_ISO_NUM);
+ // Transfer from endpoint to RAM only if data is not corrupted
+ if ((int_status & USBD_INTEN_USBEVENT_Msk) == 0 ||
+ (NRF_USBD->EVENTCAUSE & USBD_EVENTCAUSE_ISOOUTCRC_Msk) == 0) {
+ xact_out_dma(EP_ISO_NUM);
+ }
}
// ISOIN: Notify client that data was transferred
@@ -668,9 +685,9 @@ void dcd_int_handler(uint8_t rhport)
if ( int_status & USBD_INTEN_USBEVENT_Msk )
{
- TU_LOG(2, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE);
+ TU_LOG(3, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE);
- enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk };
+ enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk | USBD_EVENTCAUSE_ISOOUTCRC_Msk };
uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK;
NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt
diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c
index 52f4145f2..dc71117b3 100644
--- a/src/portable/nxp/khci/dcd_khci.c
+++ b/src/portable/nxp/khci/dcd_khci.c
@@ -114,7 +114,7 @@ typedef struct
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
// BDT(Buffer Descriptor Table) must be 256-byte aligned
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd;
+CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd;
TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" );
@@ -269,9 +269,21 @@ void dcd_init(uint8_t rhport)
{
(void) rhport;
+ // save crystal-less setting (if available)
+ #if defined(FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED) && FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED == 1
+ uint32_t clk_recover_irc_en = KHCI->CLK_RECOVER_IRC_EN;
+ uint32_t clk_recover_ctrl = KHCI->CLK_RECOVER_CTRL;
+ #endif
+
KHCI->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
while (KHCI->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
+ // restore crystal-less setting (if available)
+ #if defined(FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED) && FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED == 1
+ KHCI->CLK_RECOVER_IRC_EN = clk_recover_irc_en;
+ KHCI->CLK_RECOVER_CTRL |= clk_recover_ctrl;
+ #endif
+
tu_memclr(&_dcd, sizeof(_dcd));
KHCI->USBTRC0 |= TU_BIT(6); /* software must set this bit to 1 */
KHCI->BDTPAGE1 = (uint8_t)((uintptr_t)_dcd.bdt >> 8);
diff --git a/src/portable/nxp/khci/hcd_khci.c b/src/portable/nxp/khci/hcd_khci.c
index f6029ee0d..57684b259 100644
--- a/src/portable/nxp/khci/hcd_khci.c
+++ b/src/portable/nxp/khci/hcd_khci.c
@@ -161,7 +161,7 @@ static int prepare_packets(int pipenum)
buffer_descriptor_t *bd = _hcd.bdt[dir_tx];
TU_ASSERT(0 == bd[odd].own, -1);
- // TU_LOG1(" %p dir %d odd %d data %d\n", &bd[odd], dir_tx, odd, pipe->data);
+ // TU_LOG1(" %p dir %d odd %d data %d\r\n", &bd[odd], dir_tx, odd, pipe->data);
ep->pipenum = pipenum;
@@ -251,7 +251,7 @@ static bool resume_transfer(int pipenum)
flags |= USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPCTLDIS_MASK | USB_ENDPT_RETRYDIS_MASK;
break;
}
- // TU_LOG1(" resume pipenum %d flags %x\n", pipenum, flags);
+ // TU_LOG1(" resume pipenum %d flags %x\r\n", pipenum, flags);
KHCI->ENDPOINT[0].ENDPT = flags;
KHCI->ADDR = (KHCI->ADDR & USB_ADDR_LSEN_MASK) | pipe->dev_addr;
@@ -302,7 +302,7 @@ static void process_tokdne(uint8_t rhport)
int pipenum = ep->pipenum;
int next_pipenum;
- // TU_LOG1("TOKDNE %x PID %x pipe %d\n", s, pid, pipenum);
+ // TU_LOG1("TOKDNE %x PID %x pipe %d\r\n", s, pid, pipenum);
xfer_result_t result;
switch (pid) {
@@ -447,6 +447,10 @@ void hcd_port_reset(uint8_t rhport)
_hcd.need_reset = false;
}
+void hcd_port_reset_end(uint8_t rhport) {
+ (void) rhport;
+}
+
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
{
(void)rhport;
@@ -479,7 +483,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
{
(void)rhport;
- // TU_LOG1("SETUP %u\n", dev_addr);
+ // TU_LOG1("SETUP %u\r\n", dev_addr);
TU_ASSERT(0 == (_hcd.in_progress & TU_BIT(0)));
int pipenum = find_pipe(dev_addr, 0);
@@ -510,7 +514,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
{
(void)rhport;
uint8_t const ep_addr = ep_desc->bEndpointAddress;
- // TU_LOG1("O %u %x\n", dev_addr, ep_addr);
+ // TU_LOG1("O %u %x\r\n", dev_addr, ep_addr);
/* Find a free pipe */
pipe_state_t *p = &_hcd.pipe[0];
pipe_state_t *end = &_hcd.pipe[CFG_TUH_ENDPOINT_MAX * 2];
@@ -543,7 +547,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
{
(void)rhport;
- // TU_LOG1("X %u %x %x %d\n", dev_addr, ep_addr, (uintptr_t)buffer, buflen);
+ // TU_LOG1("X %u %x %x %d\r\n", dev_addr, ep_addr, (uintptr_t)buffer, buflen);
int pipenum = find_pipe(dev_addr, ep_addr);
TU_ASSERT(0 <= pipenum);
@@ -562,8 +566,16 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
return true;
}
-bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
-{
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+ // TODO not implemented yet
+ return false;
+}
+
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
if (!tu_edpt_number(ep_addr)) return true;
int num = find_pipe(dev_addr, ep_addr);
if (num < 0) return false;
@@ -575,12 +587,13 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
/*--------------------------------------------------------------------+
* ISR
*--------------------------------------------------------------------+*/
-void hcd_int_handler(uint8_t rhport)
+void hcd_int_handler(uint8_t rhport, bool in_isr)
{
+ (void) in_isr;
uint32_t is = KHCI->ISTAT;
uint32_t msk = KHCI->INTEN;
- // TU_LOG1("S %lx\n", is);
+ // TU_LOG1("S %lx\r\n", is);
/* clear disabled interrupts */
KHCI->ISTAT = (is & ~msk & ~USB_ISTAT_TOKDNE_MASK) | USB_ISTAT_SOFTOK_MASK;
@@ -589,7 +602,7 @@ void hcd_int_handler(uint8_t rhport)
if (is & USB_ISTAT_ERROR_MASK) {
unsigned err = KHCI->ERRSTAT;
if (err) {
- TU_LOG1(" ERR %x\n", err);
+ TU_LOG1(" ERR %x\r\n", err);
KHCI->ERRSTAT = err;
} else {
KHCI->INTEN &= ~USB_ISTAT_ERROR_MASK;
diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
index 86149afd8..b880c2870 100644
--- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
+++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
@@ -92,7 +92,7 @@ typedef struct
} dcd_data_t;
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(128) static dcd_data_t _dcd;
+CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(128) static dcd_data_t _dcd;
//--------------------------------------------------------------------+
diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
index 5368ef868..f4ed09d83 100644
--- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
+++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
@@ -34,18 +34,13 @@
* - LPC54114
* - LPC55s69
*/
-#if CFG_TUD_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_LPC11UXX || \
- CFG_TUSB_MCU == OPT_MCU_LPC13XX || \
- CFG_TUSB_MCU == OPT_MCU_LPC15XX || \
- CFG_TUSB_MCU == OPT_MCU_LPC51UXX || \
- CFG_TUSB_MCU == OPT_MCU_LPC54XXX || \
- CFG_TUSB_MCU == OPT_MCU_LPC55XX)
+#if CFG_TUD_ENABLED && defined(TUP_USBIP_IP3511)
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
-#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13XX || CFG_TUSB_MCU == OPT_MCU_LPC15XX
+#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX)
// LPCOpen
#include "chip.h"
#else
@@ -80,7 +75,7 @@ typedef struct {
enum {
NBYTES_ISO_FS_MAX = 1023, // FS ISO
NBYTES_ISO_HS_MAX = 1024, // HS ISO
- NBYTES_CBI_FS_MAX = 64, // FS control/bulk/interrupt
+ NBYTES_CBI_FS_MAX = 64, // FS control/bulk/interrupt. TODO some FS can do burst with higher size e.g 1024. Need to test
NBYTES_CBI_HS_MAX = 32767 // can be up to all 15-bit, but only tested with 4096
};
@@ -90,26 +85,36 @@ enum {
};
enum {
- CMDSTAT_DEVICE_ADDR_MASK = TU_BIT(7 )-1,
- CMDSTAT_DEVICE_ENABLE_MASK = TU_BIT(7 ),
- CMDSTAT_SETUP_RECEIVED_MASK = TU_BIT(8 ),
- CMDSTAT_DEVICE_CONNECT_MASK = TU_BIT(16), // reflect the soft-connect only, does not reflect the actual attached state
- CMDSTAT_DEVICE_SUSPEND_MASK = TU_BIT(17),
- // 23-22 is link speed (only available for HighSpeed port)
- CMDSTAT_CONNECT_CHANGE_MASK = TU_BIT(24),
- CMDSTAT_SUSPEND_CHANGE_MASK = TU_BIT(25),
- CMDSTAT_RESET_CHANGE_MASK = TU_BIT(26),
- CMDSTAT_VBUS_DEBOUNCED_MASK = TU_BIT(28),
+ DEVCMDSTAT_DEVICE_ADDR_MASK = TU_BIT(7 )-1,
+ DEVCMDSTAT_DEVICE_ENABLE_MASK = TU_BIT(7 ),
+ DEVCMDSTAT_SETUP_RECEIVED_MASK = TU_BIT(8 ),
+ DEVCMDSTAT_DEVICE_CONNECT_MASK = TU_BIT(16), // reflect the soft-connect only, does not reflect the actual attached state
+ DEVCMDSTAT_DEVICE_SUSPEND_MASK = TU_BIT(17),
+ // 23-22 is link speed (only available for HighSpeed port)
+ DEVCMDSTAT_CONNECT_CHANGE_MASK = TU_BIT(24),
+ DEVCMDSTAT_SUSPEND_CHANGE_MASK = TU_BIT(25),
+ DEVCMDSTAT_RESET_CHANGE_MASK = TU_BIT(26),
+ DEVCMDSTAT_VBUS_DEBOUNCED_MASK = TU_BIT(28),
};
enum {
- CMDSTAT_SPEED_SHIFT = 22
+ DEVCMDSTAT_SPEED_SHIFT = 22
};
//--------------------------------------------------------------------+
// Endpoint Command/Status List
//--------------------------------------------------------------------+
+// EP Command/Status field definition
+enum {
+ EPCS_TYPE = TU_BIT(26),
+ EPCS_RF_TV = TU_BIT(27),
+ EPCS_TOGGLE_RESET = TU_BIT(28),
+ EPCS_STALL = TU_BIT(29),
+ EPCS_DISABLED = TU_BIT(30),
+ EPCS_ACTIVE = TU_BIT(31),
+};
+
// Endpoint Command/Status
typedef union TU_ATTR_PACKED
{
@@ -133,8 +138,8 @@ typedef union TU_ATTR_PACKED
volatile struct {
uint32_t TU_RESERVED : 26;
- uint32_t is_iso : 1 ;
- uint32_t toggle_mode : 1 ;
+ uint32_t type : 1 ;
+ uint32_t rf_tv : 1 ; // rate feedback or toggle value
uint32_t toggle_reset : 1 ;
uint32_t stall : 1 ;
uint32_t disable : 1 ;
@@ -176,11 +181,12 @@ typedef struct
// EP list must be 256-byte aligned
// Some MCU controller may require this variable to be placed in specific SRAM region.
// For example: LPC55s69 port1 Highspeed must be USB_RAM (0x40100000)
-// Use CFG_TUSB_MEM_SECTION to place it accordingly.
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static dcd_data_t _dcd;
+// Use CFG_TUD_MEM_SECTION to place it accordingly.
+CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(256) static dcd_data_t _dcd;
// Dummy buffer to fix ZLPs overwriting the buffer (probably an USB/DMA controller bug)
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(64) static uint8_t dummy[8];
+// TODO find way to save memory
+CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(64) static uint8_t dummy[8];
//--------------------------------------------------------------------+
// Multiple Controllers
@@ -188,59 +194,73 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(64) static uint8_t dummy[8];
typedef struct
{
- dcd_registers_t* regs; // registers
- const tusb_speed_t max_speed; // max link speed
- const IRQn_Type irqnum; // IRQ number
- const uint8_t ep_pairs; // Max bi-directional Endpoints
+ dcd_registers_t* regs; // registers
+ const bool is_highspeed; // max link speed
+ const IRQn_Type irqnum; // IRQ number
+ const uint8_t ep_pairs; // Max bi-directional Endpoints
}dcd_controller_t;
#ifdef INCLUDE_FSL_DEVICE_REGISTERS
-static const dcd_controller_t _dcd_controller[] =
-{
- { .regs = (dcd_registers_t*) USB0_BASE , .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM },
+static const dcd_controller_t _dcd_controller[] = {
+ { .regs = (dcd_registers_t*) USB0_BASE , .is_highspeed = false, .irqnum = USB0_IRQn, .ep_pairs = FSL_FEATURE_USB_EP_NUM },
#if defined(FSL_FEATURE_SOC_USBHSD_COUNT) && FSL_FEATURE_SOC_USBHSD_COUNT
- { .regs = (dcd_registers_t*) USBHSD_BASE, .max_speed = TUSB_SPEED_HIGH, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM }
+ { .regs = (dcd_registers_t*) USBHSD_BASE, .is_highspeed = true, .irqnum = USB1_IRQn, .ep_pairs = FSL_FEATURE_USBHSD_EP_NUM }
#endif
};
#else
-static const dcd_controller_t _dcd_controller[] =
-{
- { .regs = (dcd_registers_t*) LPC_USB0_BASE, .max_speed = TUSB_SPEED_FULL, .irqnum = USB0_IRQn, .ep_pairs = 5 },
+static const dcd_controller_t _dcd_controller[] = {
+ { .regs = (dcd_registers_t*) LPC_USB0_BASE, .is_highspeed = false, .irqnum = USB0_IRQn, .ep_pairs = 5 },
};
#endif
+#if defined(FSL_FEATURE_SOC_USBHSD_COUNT) && FSL_FEATURE_SOC_USBHSD_COUNT
+ #define IP3511_HAS_HIGHSPEED
+#endif
+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-static inline uint16_t get_buf_offset(void const * buffer)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint16_t get_buf_offset(void const * buffer) {
uint32_t addr = (uint32_t) buffer;
TU_ASSERT( (addr & 0x3f) == 0, 0 );
return ( (addr >> 6) & 0xFFFFUL ) ;
}
-static inline uint8_t ep_addr2id(uint8_t ep_addr)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint8_t ep_addr2id(uint8_t ep_addr) {
return 2*(ep_addr & 0x0F) + ((ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0);
}
+TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(ep_cmd_sts_t* ep_cs, bool is_highspeed) {
+ return is_highspeed ? (ep_cs[0].cmd_sts.type && !ep_cs[0].cmd_sts.rf_tv) : ep_cs->cmd_sts.type;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool ep_is_bulk(ep_cmd_sts_t* ep_cs) {
+ return (ep_cs[0].cmd_sts.type == 0) && (ep_cs[0].cmd_sts.rf_tv == 0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline ep_cmd_sts_t* get_ep_cs(uint8_t ep_id) {
+ return _dcd.ep[ep_id];
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool rhport_is_highspeed(uint8_t rhport) {
+ return _dcd_controller[rhport].is_highspeed;
+}
+
//--------------------------------------------------------------------+
// CONTROLLER API
//--------------------------------------------------------------------+
-static void prepare_setup_packet(uint8_t rhport)
-{
- if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL )
- {
- _dcd.ep[0][1].buffer_fs.offset = get_buf_offset(_dcd.setup_packet);
- }else
- {
- _dcd.ep[0][1].buffer_hs.offset = get_buf_offset(_dcd.setup_packet);
+static void prepare_setup_packet(uint8_t rhport) {
+ uint16_t const buf_offset = get_buf_offset(_dcd.setup_packet);
+ if ( _dcd_controller[rhport].is_highspeed ) {
+ _dcd.ep[0][1].buffer_hs.offset = buf_offset;
+ } else {
+ _dcd.ep[0][1].buffer_fs.offset = buf_offset;
}
}
@@ -268,8 +288,8 @@ void dcd_init(uint8_t rhport)
dcd_reg->DATABUFSTART = tu_align((uint32_t) &_dcd, TU_BIT(22)); // 22-bit alignment
dcd_reg->INTSTAT |= dcd_reg->INTSTAT; // clear all pending interrupt
dcd_reg->INTEN = INT_DEVICE_STATUS_MASK;
- dcd_reg->DEVCMDSTAT |= CMDSTAT_DEVICE_ENABLE_MASK | CMDSTAT_DEVICE_CONNECT_MASK |
- CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK;
+ dcd_reg->DEVCMDSTAT |= DEVCMDSTAT_DEVICE_ENABLE_MASK | DEVCMDSTAT_DEVICE_CONNECT_MASK |
+ DEVCMDSTAT_RESET_CHANGE_MASK | DEVCMDSTAT_CONNECT_CHANGE_MASK | DEVCMDSTAT_SUSPEND_CHANGE_MASK;
NVIC_ClearPendingIRQ(_dcd_controller[rhport].irqnum);
}
@@ -291,7 +311,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
// Response with status first before changing device address
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
- dcd_reg->DEVCMDSTAT &= ~CMDSTAT_DEVICE_ADDR_MASK;
+ dcd_reg->DEVCMDSTAT &= ~DEVCMDSTAT_DEVICE_ADDR_MASK;
dcd_reg->DEVCMDSTAT |= dev_addr;
}
@@ -303,13 +323,13 @@ void dcd_remote_wakeup(uint8_t rhport)
void dcd_connect(uint8_t rhport)
{
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->DEVCMDSTAT |= CMDSTAT_DEVICE_CONNECT_MASK;
+ dcd_reg->DEVCMDSTAT |= DEVCMDSTAT_DEVICE_CONNECT_MASK;
}
void dcd_disconnect(uint8_t rhport)
{
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->DEVCMDSTAT &= ~CMDSTAT_DEVICE_CONNECT_MASK;
+ dcd_reg->DEVCMDSTAT &= ~DEVCMDSTAT_DEVICE_CONNECT_MASK;
}
void dcd_sof_enable(uint8_t rhport, bool en)
@@ -340,19 +360,39 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
_dcd.ep[ep_id][0].cmd_sts.stall = 0;
_dcd.ep[ep_id][0].cmd_sts.toggle_reset = 1;
- _dcd.ep[ep_id][0].cmd_sts.toggle_mode = 0;
+ _dcd.ep[ep_id][0].cmd_sts.rf_tv = 0;
}
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
{
//------------- Prepare Queue Head -------------//
uint8_t ep_id = ep_addr2id(p_endpoint_desc->bEndpointAddress);
+ ep_cmd_sts_t* ep_cs = get_ep_cs(ep_id);
// Check if endpoint is available
- TU_ASSERT( _dcd.ep[ep_id][0].cmd_sts.disable && _dcd.ep[ep_id][1].cmd_sts.disable );
+ TU_ASSERT( ep_cs[0].cmd_sts.disable && ep_cs[1].cmd_sts.disable );
edpt_reset(rhport, ep_id);
- _dcd.ep[ep_id][0].cmd_sts.is_iso = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS);
+
+ switch (p_endpoint_desc->bmAttributes.xfer) {
+ case TUSB_XFER_ISOCHRONOUS:
+ ep_cs[0].cmd_sts.type = 1;
+ break;
+
+ case TUSB_XFER_INTERRUPT:
+ // What is interrupt endpoint in rate feedback mode ?
+ if ( rhport_is_highspeed(rhport) ) {
+ ep_cs[0].cmd_sts.type = 1;
+ ep_cs[0].cmd_sts.rf_tv = 1;
+ }
+ break;
+
+ case TUSB_XFER_BULK:
+ // nothing to do both type and rf_tv are 0
+ break;
+
+ default: break;
+ }
// Enable EP interrupt
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
@@ -379,42 +419,50 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
_dcd.ep[ep_id][0].cmd_sts.disable = _dcd.ep[ep_id][1].cmd_sts.disable = 1;
}
-static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes)
-{
+static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes) {
uint16_t nbytes;
+ ep_cmd_sts_t* ep_cs = get_ep_cs(ep_id);
- if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL )
- {
- nbytes = tu_min16(total_bytes, _dcd.ep[ep_id][0].cmd_sts.is_iso ? NBYTES_ISO_FS_MAX : NBYTES_CBI_FS_MAX);
- _dcd.ep[ep_id][0].buffer_fs.offset = buf_offset;
- _dcd.ep[ep_id][0].buffer_fs.nbytes = nbytes;
- }else
- {
- nbytes = tu_min16(total_bytes, NBYTES_CBI_HS_MAX);
- _dcd.ep[ep_id][0].buffer_hs.offset = buf_offset;
- _dcd.ep[ep_id][0].buffer_hs.nbytes = nbytes;
+ const bool is_iso = ep_is_iso(ep_cs, _dcd_controller[rhport].is_highspeed);
+
+ if ( rhport_is_highspeed(rhport) ) {
+ nbytes = tu_min16(total_bytes, is_iso ? NBYTES_ISO_HS_MAX : NBYTES_CBI_HS_MAX);
+ #if TU_CHECK_MCU(OPT_MCU_LPC54)
+ // LPC54 Errata USB.1: In USB high-speed device mode, the NBytes field does not decrement after BULK OUT transfer.
+ // Suggested Work-around: Program the NByte to the max packet size (512)
+ // Actual Work-around: round up NByte to multiple of 4.
+ // Note: this can cause buffer overflowed and corrupt data if host send more data than total_bytes
+ if ( (ep_id > 1) && (ep_id & 0x01) == 0 && ep_is_bulk(ep_cs) ) {
+ if ( nbytes & 0x03 ) {
+ nbytes = tu_align4(nbytes) + 4;
+ }
+ }
+ #endif
+
+ ep_cs[0].buffer_hs.offset = buf_offset;
+ ep_cs[0].buffer_hs.nbytes = nbytes;
+ }else {
+ nbytes = tu_min16(total_bytes, is_iso ? NBYTES_ISO_FS_MAX : NBYTES_CBI_FS_MAX);
+ ep_cs[0].buffer_fs.offset = buf_offset;
+ ep_cs[0].buffer_fs.nbytes = nbytes;
}
_dcd.dma[ep_id].nbytes = nbytes;
-
- _dcd.ep[ep_id][0].cmd_sts.active = 1;
+ ep_cs[0].cmd_sts.active = 1;
}
-bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
-{
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
uint8_t const ep_id = ep_addr2id(ep_addr);
+ if (!buffer || total_bytes == 0) {
+ // Although having no data, ZLPs can cause buffer overwritten to zeroes. Probably due to USB/DMA controller side
+ // effect/bug. Assigned buffer offset to (valid) dummy to prevent overwriting to DATABUFSTART
+ buffer = (uint8_t *) (uint32_t) dummy;
+ }
+
tu_memclr(&_dcd.dma[ep_id], sizeof(xfer_dma_t));
_dcd.dma[ep_id].total_bytes = total_bytes;
- if (!buffer)
- {
- // Although having no data, ZLPs can cause buffer overwritten to zeroes.
- // Probably due to USB/DMA controller side effect/bug.
- // Assigned buffer offset to (valid) dummy to prevent overwriting to DATABUFSTART
- buffer = (uint8_t*)(uint32_t)dummy;
- }
-
prepare_ep_xfer(rhport, ep_id, get_buf_offset(buffer), total_bytes);
return true;
@@ -441,23 +489,19 @@ static void bus_reset(uint8_t rhport)
dcd_reg->EPSKIP = 0xFFFFFFFF;
dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt
- dcd_reg->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; // clear setup received interrupt
+ dcd_reg->DEVCMDSTAT |= DEVCMDSTAT_SETUP_RECEIVED_MASK; // clear setup received interrupt
dcd_reg->INTEN = INT_DEVICE_STATUS_MASK | TU_BIT(0) | TU_BIT(1); // enable device status & control endpoints
}
-static void process_xfer_isr(uint8_t rhport, uint32_t int_status)
-{
+static void process_xfer_isr(uint8_t rhport, uint32_t int_status) {
uint8_t const max_ep = 2*_dcd_controller[rhport].ep_pairs;
- for(uint8_t ep_id = 0; ep_id < max_ep; ep_id++ )
- {
- if ( tu_bit_test(int_status, ep_id) )
- {
+ for(uint8_t ep_id = 0; ep_id < max_ep; ep_id++ ) {
+ if ( tu_bit_test(int_status, ep_id) ) {
ep_cmd_sts_t * ep_cs = &_dcd.ep[ep_id][0];
xfer_dma_t* xfer_dma = &_dcd.dma[ep_id];
- if ( ep_id == 0 || ep_id == 1)
- {
+ if ( ep_id <= 1 ) {
// For control endpoint, we need to manually clear Active bit
ep_cs->cmd_sts.active = 0;
}
@@ -465,26 +509,29 @@ static void process_xfer_isr(uint8_t rhport, uint32_t int_status)
uint16_t buf_offset;
uint16_t buf_nbytes;
- if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL)
- {
- buf_offset = ep_cs->buffer_fs.offset;
- buf_nbytes = ep_cs->buffer_fs.nbytes;
- }else
- {
+ if ( rhport_is_highspeed(rhport) ) {
buf_offset = ep_cs->buffer_hs.offset;
buf_nbytes = ep_cs->buffer_hs.nbytes;
+
+ #if TU_CHECK_MCU(OPT_MCU_LPC54)
+ // LPC54 Errata USB.2: In USB high-speed device mode, the NBytes field is not correct after BULK IN transfer
+ // There is no work-around. For EP in transfer, the NByte value can be ignored after a packet is transmitted.
+ if ( (ep_id > 1) && (ep_id & 0x01) == 1 && ep_is_bulk(ep_cs) ) {
+ buf_nbytes = 0;
+ }
+ #endif
+ } else {
+ buf_offset = ep_cs->buffer_fs.offset;
+ buf_nbytes = ep_cs->buffer_fs.nbytes;
}
xfer_dma->xferred_bytes += xfer_dma->nbytes - buf_nbytes;
- if ( (buf_nbytes == 0) && (xfer_dma->total_bytes > xfer_dma->xferred_bytes) )
- {
+ if ( (buf_nbytes == 0) && (xfer_dma->total_bytes > xfer_dma->xferred_bytes) ) {
// There is more data to transfer
// buff_offset has been already increased by hw to correct value for next transfer
prepare_ep_xfer(rhport, ep_id, buf_offset, xfer_dma->total_bytes - xfer_dma->xferred_bytes);
- }
- else
- {
+ } else {
// for detecting ZLP
xfer_dma->total_bytes = xfer_dma->xferred_bytes;
@@ -511,19 +558,16 @@ void dcd_int_handler(uint8_t rhport)
//------------- Device Status -------------//
if ( int_status & INT_DEVICE_STATUS_MASK )
{
- dcd_reg->DEVCMDSTAT |= CMDSTAT_RESET_CHANGE_MASK | CMDSTAT_CONNECT_CHANGE_MASK | CMDSTAT_SUSPEND_CHANGE_MASK;
+ dcd_reg->DEVCMDSTAT |= DEVCMDSTAT_RESET_CHANGE_MASK | DEVCMDSTAT_CONNECT_CHANGE_MASK | DEVCMDSTAT_SUSPEND_CHANGE_MASK;
- if ( cmd_stat & CMDSTAT_RESET_CHANGE_MASK) // bus reset
+ if ( cmd_stat & DEVCMDSTAT_RESET_CHANGE_MASK) // bus reset
{
bus_reset(rhport);
tusb_speed_t speed = TUSB_SPEED_FULL;
-
- if (_dcd_controller[rhport].max_speed == TUSB_SPEED_HIGH)
- {
+ if ( _dcd_controller[rhport].is_highspeed ) {
// 0 : reserved, 1 : full, 2 : high, 3: super
- if ( 2 == ((cmd_stat >> CMDSTAT_SPEED_SHIFT) & 0x3UL) )
- {
+ if ( 2 == ((cmd_stat >> DEVCMDSTAT_SPEED_SHIFT) & 0x3UL) ) {
speed= TUSB_SPEED_HIGH;
}
}
@@ -531,35 +575,35 @@ void dcd_int_handler(uint8_t rhport)
dcd_event_bus_reset(rhport, speed, true);
}
- if (cmd_stat & CMDSTAT_CONNECT_CHANGE_MASK)
+ if (cmd_stat & DEVCMDSTAT_CONNECT_CHANGE_MASK)
{
// device disconnect
- if (cmd_stat & CMDSTAT_DEVICE_ADDR_MASK)
+ if (cmd_stat & DEVCMDSTAT_DEVICE_ADDR_MASK)
{
// debouncing as this can be set when device is powering
dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
}
}
- if (cmd_stat & CMDSTAT_SUSPEND_CHANGE_MASK)
+ if (cmd_stat & DEVCMDSTAT_SUSPEND_CHANGE_MASK)
{
// suspend signal, bus idle for more than 3ms
// Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration.
- if (cmd_stat & CMDSTAT_DEVICE_ADDR_MASK)
+ if (cmd_stat & DEVCMDSTAT_DEVICE_ADDR_MASK)
{
- dcd_event_bus_signal(rhport, (cmd_stat & CMDSTAT_DEVICE_SUSPEND_MASK) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME, true);
+ dcd_event_bus_signal(rhport, (cmd_stat & DEVCMDSTAT_DEVICE_SUSPEND_MASK) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME, true);
}
}
}
// Setup Receive
- if ( tu_bit_test(int_status, 0) && (cmd_stat & CMDSTAT_SETUP_RECEIVED_MASK) )
+ if ( tu_bit_test(int_status, 0) && (cmd_stat & DEVCMDSTAT_SETUP_RECEIVED_MASK) )
{
// Follow UM flowchart to clear Active & Stall on both Control IN/OUT endpoints
_dcd.ep[0][0].cmd_sts.active = _dcd.ep[1][0].cmd_sts.active = 0;
_dcd.ep[0][0].cmd_sts.stall = _dcd.ep[1][0].cmd_sts.stall = 0;
- dcd_reg->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK;
+ dcd_reg->DEVCMDSTAT |= DEVCMDSTAT_SETUP_RECEIVED_MASK;
dcd_event_setup_received(rhport, _dcd.setup_packet, true);
diff --git a/src/portable/nxp/transdimension/common_transdimension.h b/src/portable/nxp/transdimension/common_transdimension.h
deleted file mode 100644
index 95ae1903e..000000000
--- a/src/portable/nxp/transdimension/common_transdimension.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2021, Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#ifndef COMMON_TRANSDIMENSION_H_
-#define COMMON_TRANSDIMENSION_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-// USBCMD
-enum {
- USBCMD_RUN_STOP = TU_BIT(0),
- USBCMD_RESET = TU_BIT(1),
- USBCMD_SETUP_TRIPWIRE = TU_BIT(13),
- USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD
-// Interrupt Threshold bit 23:16
-};
-
-// PORTSC1
-#define PORTSC1_PORT_SPEED_POS 26
-
-enum {
- PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0),
- PORTSC1_FORCE_PORT_RESUME = TU_BIT(6),
- PORTSC1_SUSPEND = TU_BIT(7),
- PORTSC1_FORCE_FULL_SPEED = TU_BIT(24),
- PORTSC1_PORT_SPEED = TU_BIT(26) | TU_BIT(27)
-};
-
-// OTGSC
-enum {
- OTGSC_VBUS_DISCHARGE = TU_BIT(0),
- OTGSC_VBUS_CHARGE = TU_BIT(1),
-// OTGSC_HWASSIST_AUTORESET = TU_BIT(2),
- OTGSC_OTG_TERMINATION = TU_BIT(3), ///< Must set to 1 when OTG go to device mode
- OTGSC_DATA_PULSING = TU_BIT(4),
- OTGSC_ID_PULLUP = TU_BIT(5),
-// OTGSC_HWASSIT_DATA_PULSE = TU_BIT(6),
-// OTGSC_HWASSIT_BDIS_ACONN = TU_BIT(7),
- OTGSC_ID = TU_BIT(8), ///< 0 = A device, 1 = B Device
- OTGSC_A_VBUS_VALID = TU_BIT(9),
- OTGSC_A_SESSION_VALID = TU_BIT(10),
- OTGSC_B_SESSION_VALID = TU_BIT(11),
- OTGSC_B_SESSION_END = TU_BIT(12),
- OTGSC_1MS_TOGGLE = TU_BIT(13),
- OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14),
-};
-
-// USBMode
-enum {
- USBMODE_CM_DEVICE = 2,
- USBMODE_CM_HOST = 3,
-
- USBMODE_SLOM = TU_BIT(3),
- USBMODE_SDIS = TU_BIT(4),
-
- USBMODE_VBUS_POWER_SELECT = TU_BIT(5), // Need to be enabled for LPC18XX/43XX in host mode
-};
-
-// Device Registers
-typedef struct
-{
- //------------- ID + HW Parameter Registers-------------//
- __I uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
-
- //------------- Capability Registers-------------//
- __I uint8_t CAPLENGTH; ///< Capability Registers Length
- __I uint8_t TU_RESERVED[1];
- __I uint16_t HCIVERSION; ///< Host Controller Interface Version
-
- __I uint32_t HCSPARAMS; ///< Host Controller Structural Parameters
- __I uint32_t HCCPARAMS; ///< Host Controller Capability Parameters
- __I uint32_t TU_RESERVED[5];
-
- __I uint16_t DCIVERSION; ///< Device Controller Interface Version
- __I uint8_t TU_RESERVED[2];
-
- __I uint32_t DCCPARAMS; ///< Device Controller Capability Parameters
- __I uint32_t TU_RESERVED[6];
-
- //------------- Operational Registers -------------//
- __IO uint32_t USBCMD; ///< USB Command Register
- __IO uint32_t USBSTS; ///< USB Status Register
- __IO uint32_t USBINTR; ///< Interrupt Enable Register
- __IO uint32_t FRINDEX; ///< USB Frame Index
- __I uint32_t TU_RESERVED;
- __IO uint32_t DEVICEADDR; ///< Device Address
- __IO uint32_t ENDPTLISTADDR; ///< Endpoint List Address
- __I uint32_t TU_RESERVED;
- __IO uint32_t BURSTSIZE; ///< Programmable Burst Size
- __IO uint32_t TXFILLTUNING; ///< TX FIFO Fill Tuning
- uint32_t TU_RESERVED[4];
- __IO uint32_t ENDPTNAK; ///< Endpoint NAK
- __IO uint32_t ENDPTNAKEN; ///< Endpoint NAK Enable
- __I uint32_t TU_RESERVED;
- __IO uint32_t PORTSC1; ///< Port Status & Control
- __I uint32_t TU_RESERVED[7];
- __IO uint32_t OTGSC; ///< On-The-Go Status & control
- __IO uint32_t USBMODE; ///< USB Device Mode
- __IO uint32_t ENDPTSETUPSTAT; ///< Endpoint Setup Status
- __IO uint32_t ENDPTPRIME; ///< Endpoint Prime
- __IO uint32_t ENDPTFLUSH; ///< Endpoint Flush
- __I uint32_t ENDPTSTAT; ///< Endpoint Status
- __IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete
- __IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7
-} dcd_registers_t, hcd_registers_t;
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* COMMON_TRANSDIMENSION_H_ */
diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c
deleted file mode 100644
index 983d7cfcf..000000000
--- a/src/portable/nxp/transdimension/dcd_transdimension.c
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "tusb_option.h"
-
-#if CFG_TUD_ENABLED && \
- (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT)
-
-#warning "transdimenion is renamed to chipidea (portable/chipidea/ci_hs) to match other opensource naming convention such as linux. This file will be removed in the future, please update your makefile accordingly"
-
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#if CFG_TUSB_MCU == OPT_MCU_MIMXRT
- #include "fsl_device_registers.h"
- #define INCLUDE_FSL_DEVICE_REGISTERS
-#else
- // LPCOpen for 18xx & 43xx
- #include "chip.h"
-#endif
-
-#include "common/tusb_common.h"
-#include "device/dcd.h"
-#include "common_transdimension.h"
-
-#if defined(__CORTEX_M) && __CORTEX_M == 7 && __DCACHE_PRESENT == 1
- #define CleanInvalidateDCache_by_Addr SCB_CleanInvalidateDCache_by_Addr
-#else
- #define CleanInvalidateDCache_by_Addr(_addr, _dsize)
-#endif
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
-// ENDPTCTRL
-enum {
- ENDPTCTRL_STALL = TU_BIT(0),
- ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), // used for test only
- ENDPTCTRL_TOGGLE_RESET = TU_BIT(6),
- ENDPTCTRL_ENABLE = TU_BIT(7)
-};
-
-enum {
- ENDPTCTRL_TYPE_POS = 2, // Endpoint type is 2-bit field
-};
-
-// USBSTS, USBINTR
-enum {
- INTR_USB = TU_BIT(0),
- INTR_ERROR = TU_BIT(1),
- INTR_PORT_CHANGE = TU_BIT(2),
- INTR_RESET = TU_BIT(6),
- INTR_SOF = TU_BIT(7),
- INTR_SUSPEND = TU_BIT(8),
- INTR_NAK = TU_BIT(16)
-};
-
-// Queue Transfer Descriptor
-typedef struct
-{
- // Word 0: Next QTD Pointer
- uint32_t next; ///< Next link pointer This field contains the physical memory address of the next dTD to be processed
-
- // Word 1: qTQ Token
- uint32_t : 3 ;
- volatile uint32_t xact_err : 1 ;
- uint32_t : 1 ;
- volatile uint32_t buffer_err : 1 ;
- volatile uint32_t halted : 1 ;
- volatile uint32_t active : 1 ;
- uint32_t : 2 ;
- uint32_t iso_mult_override : 2 ; ///< This field can be used for transmit ISOs to override the MULT field in the dQH. This field must be zero for all packet types that are not transmit-ISO.
- uint32_t : 3 ;
- uint32_t int_on_complete : 1 ;
- volatile uint32_t total_bytes : 15 ;
- uint32_t : 1 ;
-
- // Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page
- uint32_t buffer[5]; ///< buffer1 has frame_n for TODO Isochronous
-
- //--------------------------------------------------------------------+
- // TD is 32 bytes aligned but occupies only 28 bytes
- // Therefore there are 4 bytes padding that we can use.
- //--------------------------------------------------------------------+
- uint16_t expected_bytes;
- uint8_t reserved[2];
-} dcd_qtd_t;
-
-TU_VERIFY_STATIC( sizeof(dcd_qtd_t) == 32, "size is not correct");
-
-// Queue Head
-typedef struct
-{
- // Word 0: Capabilities and Characteristics
- uint32_t : 15 ; ///< Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed.
- uint32_t int_on_setup : 1 ; ///< Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received.
- uint32_t max_packet_size : 11 ; ///< Endpoint's wMaxPacketSize
- uint32_t : 2 ;
- uint32_t zero_length_termination : 1 ; ///< This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length.
- uint32_t iso_mult : 2 ; ///<
-
- // Word 1: Current qTD Pointer
- volatile uint32_t qtd_addr;
-
- // Word 2-9: Transfer Overlay
- volatile dcd_qtd_t qtd_overlay;
-
- // Word 10-11: Setup request (control OUT only)
- volatile tusb_control_request_t setup_request;
-
- //--------------------------------------------------------------------+
- // QHD is 64 bytes aligned but occupies only 48 bytes
- // Therefore there are 16 bytes padding that we can use.
- //--------------------------------------------------------------------+
- tu_fifo_t * ff;
- uint8_t reserved[12];
-} dcd_qhd_t;
-
-TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct");
-
-//--------------------------------------------------------------------+
-// Variables
-//--------------------------------------------------------------------+
-
-typedef struct
-{
- dcd_registers_t* regs; // registers
- const IRQn_Type irqnum; // IRQ number
- const uint8_t ep_count; // Max bi-directional Endpoints
-}dcd_controller_t;
-
-#if CFG_TUSB_MCU == OPT_MCU_MIMXRT
- static const dcd_controller_t _dcd_controller[] =
- {
- // RT1010 and RT1020 only has 1 USB controller
- #if FSL_FEATURE_SOC_USBHS_COUNT == 1
- { .regs = (dcd_registers_t*) USB_BASE , .irqnum = USB_OTG1_IRQn, .ep_count = 8 }
- #else
- { .regs = (dcd_registers_t*) USB1_BASE, .irqnum = USB_OTG1_IRQn, .ep_count = 8 },
- { .regs = (dcd_registers_t*) USB2_BASE, .irqnum = USB_OTG2_IRQn, .ep_count = 8 }
- #endif
- };
-
-#else
- static const dcd_controller_t _dcd_controller[] =
- {
- { .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 6 },
- { .regs = (dcd_registers_t*) LPC_USB1_BASE, .irqnum = USB1_IRQn, .ep_count = 4 }
- };
-#endif
-
-#define QTD_NEXT_INVALID 0x01
-
-typedef struct {
- // Must be at 2K alignment
- // Each endpoint with direction (IN/OUT) occupies a queue head
- // for portability, TinyUSB only queue 1 TD for each Qhd
- dcd_qhd_t qhd[TUP_DCD_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(64);
- dcd_qtd_t qtd[TUP_DCD_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(32);
-}dcd_data_t;
-
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048)
-static dcd_data_t _dcd_data;
-
-//--------------------------------------------------------------------+
-// Controller API
-//--------------------------------------------------------------------+
-
-/// follows LPC43xx User Manual 23.10.3
-static void bus_reset(uint8_t rhport)
-{
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
-
- // The reset value for all endpoint types is the control endpoint. If one endpoint
- // direction is enabled and the paired endpoint of opposite direction is disabled, then the
- // endpoint type of the unused direction must be changed from the control type to any other
- // type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior
- // for the data PID tracking on the active endpoint.
- for( uint8_t i=1; i < _dcd_controller[rhport].ep_count; i++)
- {
- dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
- }
-
- //------------- Clear All Registers -------------//
- dcd_reg->ENDPTNAK = dcd_reg->ENDPTNAK;
- dcd_reg->ENDPTNAKEN = 0;
- dcd_reg->USBSTS = dcd_reg->USBSTS;
- dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;
- dcd_reg->ENDPTCOMPLETE = dcd_reg->ENDPTCOMPLETE;
-
- while (dcd_reg->ENDPTPRIME) {}
- dcd_reg->ENDPTFLUSH = 0xFFFFFFFF;
- while (dcd_reg->ENDPTFLUSH) {}
-
- // read reset bit in portsc
-
- //------------- Queue Head & Queue TD -------------//
- tu_memclr(&_dcd_data, sizeof(dcd_data_t));
-
- //------------- Set up Control Endpoints (0 OUT, 1 IN) -------------//
- _dcd_data.qhd[0][0].zero_length_termination = _dcd_data.qhd[0][1].zero_length_termination = 1;
- _dcd_data.qhd[0][0].max_packet_size = _dcd_data.qhd[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE;
- _dcd_data.qhd[0][0].qtd_overlay.next = _dcd_data.qhd[0][1].qtd_overlay.next = QTD_NEXT_INVALID;
-
- _dcd_data.qhd[0][0].int_on_setup = 1; // OUT only
-}
-
-void dcd_init(uint8_t rhport)
-{
- tu_memclr(&_dcd_data, sizeof(dcd_data_t));
-
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
-
- // Reset controller
- dcd_reg->USBCMD |= USBCMD_RESET;
- while( dcd_reg->USBCMD & USBCMD_RESET ) {}
-
- // Set mode to device, must be set immediately after reset
- dcd_reg->USBMODE = USBMODE_CM_DEVICE;
- dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION;
-
-#if !TUD_OPT_HIGH_SPEED
- dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED;
-#endif
-
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
-
- dcd_reg->ENDPTLISTADDR = (uint32_t) _dcd_data.qhd; // Endpoint List Address has to be 2K alignment
- dcd_reg->USBSTS = dcd_reg->USBSTS;
- dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_SUSPEND;
-
- dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0
- dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect
-}
-
-void dcd_int_enable(uint8_t rhport)
-{
- NVIC_EnableIRQ(_dcd_controller[rhport].irqnum);
-}
-
-void dcd_int_disable(uint8_t rhport)
-{
- NVIC_DisableIRQ(_dcd_controller[rhport].irqnum);
-}
-
-void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
-{
- // Response with status first before changing device address
- dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
-
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->DEVICEADDR = (dev_addr << 25) | TU_BIT(24);
-}
-
-void dcd_remote_wakeup(uint8_t rhport)
-{
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->PORTSC1 |= PORTSC1_FORCE_PORT_RESUME;
-}
-
-void dcd_connect(uint8_t rhport)
-{
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->USBCMD |= USBCMD_RUN_STOP;
-}
-
-void dcd_disconnect(uint8_t rhport)
-{
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->USBCMD &= ~USBCMD_RUN_STOP;
-}
-
-void dcd_sof_enable(uint8_t rhport, bool en)
-{
- (void) rhport;
- (void) en;
-
- // TODO implement later
-}
-
-//--------------------------------------------------------------------+
-// HELPER
-//--------------------------------------------------------------------+
-
-static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes)
-{
- // Force the CPU to flush the buffer. We increase the size by 31 because the call aligns the
- // address to 32-byte boundaries. Buffer must be word aligned
- CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31);
-
- tu_memclr(p_qtd, sizeof(dcd_qtd_t));
-
- p_qtd->next = QTD_NEXT_INVALID;
- p_qtd->active = 1;
- p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
- p_qtd->int_on_complete = true;
-
- if (data_ptr != NULL)
- {
- p_qtd->buffer[0] = (uint32_t) data_ptr;
-
- uint32_t const bufend = p_qtd->buffer[0] + total_bytes;
- for(uint8_t i=1; i<5; i++)
- {
- uint32_t const next_page = tu_align4k( p_qtd->buffer[i-1] ) + 4096;
- if ( bufend <= next_page ) break;
-
- p_qtd->buffer[i] = next_page;
-
- // TODO page[1] FRAME_N for ISO transfer
- }
- }
-}
-
-//--------------------------------------------------------------------+
-// DCD Endpoint Port
-//--------------------------------------------------------------------+
-void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_STALL << (dir ? 16 : 0);
-
- // flush to abort any primed buffer
- dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
-}
-
-void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- // data toggle also need to be reset
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_TOGGLE_RESET << ( dir ? 16 : 0 );
- dcd_reg->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << ( dir ? 16 : 0));
-}
-
-bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
-{
- uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
- uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
-
- // Must not exceed max endpoint number
- TU_ASSERT( epnum < _dcd_controller[rhport].ep_count );
-
- //------------- Prepare Queue Head -------------//
- dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
- tu_memclr(p_qhd, sizeof(dcd_qhd_t));
-
- p_qhd->zero_length_termination = 1;
- p_qhd->max_packet_size = tu_edpt_packet_size(p_endpoint_desc);
- if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
- {
- p_qhd->iso_mult = 1;
- }
-
- p_qhd->qtd_overlay.next = QTD_NEXT_INVALID;
-
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
-
- // Enable EP Control
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
-
- uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET;
-
- if ( dir == TUSB_DIR_OUT )
- {
- dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0xFFFF0000u) | epctrl;
- }else
- {
- dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0x0000FFFFu) | (epctrl << 16);
- }
-
- return true;
-}
-
-void dcd_edpt_close_all (uint8_t rhport)
-{
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
-
- // Disable all non-control endpoints
- for( uint8_t epnum=1; epnum < _dcd_controller[rhport].ep_count; epnum++)
- {
- _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1;
- _dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1;
-
- dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum+16);
- dcd_reg->ENDPTCTRL[epnum] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
- }
-}
-
-void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
-
- _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1;
-
- // Flush EP
- uint32_t const flush_mask = TU_BIT(epnum + (dir ? 16 : 0));
- dcd_reg->ENDPTFLUSH = flush_mask;
- while(dcd_reg->ENDPTFLUSH & flush_mask);
-
- // Clear EP enable
- dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0));
-}
-
-static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir)
-{
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir];
- dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir];
-
- p_qhd->qtd_overlay.halted = false; // clear any previous error
- p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd
-
- // flush cache
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
-
- if ( epnum == 0 )
- {
- // follows UM 24.10.8.1.1 Setup packet handling using setup lockout mechanism
- // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out
- while(dcd_reg->ENDPTSETUPSTAT & TU_BIT(0)) {}
- }
-
- // start transfer
- dcd_reg->ENDPTPRIME = TU_BIT(epnum + (dir ? 16 : 0));
-}
-
-bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir];
- dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir];
-
- // Prepare qtd
- qtd_init(p_qtd, buffer, total_bytes);
-
- // Start qhd transfer
- p_qhd->ff = NULL;
- qhd_start_xfer(rhport, epnum, dir);
-
- return true;
-}
-
-// fifo has to be aligned to 4k boundary
-bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
- dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
-
- tu_fifo_buffer_info_t fifo_info;
-
- if (dir)
- {
- tu_fifo_get_read_info(ff, &fifo_info);
- } else
- {
- tu_fifo_get_write_info(ff, &fifo_info);
- }
-
- if ( fifo_info.len_lin >= total_bytes )
- {
- // Linear length is enough for this transfer
- qtd_init(p_qtd, fifo_info.ptr_lin, total_bytes);
- }
- else
- {
- // linear part is not enough
-
- // prepare TD up to linear length
- qtd_init(p_qtd, fifo_info.ptr_lin, fifo_info.len_lin);
-
- if ( !tu_offset4k((uint32_t) fifo_info.ptr_wrap) && !tu_offset4k(tu_fifo_depth(ff)) )
- {
- // If buffer is aligned to 4K & buffer size is multiple of 4K
- // We can make use of buffer page array to also combine the linear + wrapped length
- p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
-
- for(uint8_t i = 1, page = 0; i < 5; i++)
- {
- // pick up buffer array where linear ends
- if (p_qtd->buffer[i] == 0)
- {
- p_qtd->buffer[i] = (uint32_t) fifo_info.ptr_wrap + 4096 * page;
- page++;
- }
- }
-
- CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31);
- }
- else
- {
- // TODO we may need to carry the wrapped length after the linear part complete
- // for now only transfer up to linear part
- }
- }
-
- // Start qhd transfer
- p_qhd->ff = ff;
- qhd_start_xfer(rhport, epnum, dir);
-
- return true;
-}
-
-//--------------------------------------------------------------------+
-// ISR
-//--------------------------------------------------------------------+
-
-static void process_edpt_complete_isr(uint8_t rhport, uint8_t epnum, uint8_t dir)
-{
- dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
- dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
-
- uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED :
- ( p_qtd->xact_err || p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS;
-
- if ( result != XFER_RESULT_SUCCESS )
- {
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- // flush to abort error buffer
- dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
- }
-
- uint16_t const xferred_bytes = p_qtd->expected_bytes - p_qtd->total_bytes;
-
- if (p_qhd->ff)
- {
- if (dir == TUSB_DIR_IN)
- {
- tu_fifo_advance_read_pointer(p_qhd->ff, xferred_bytes);
- } else
- {
- tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes);
- }
- }
-
- // only number of bytes in the IOC qtd
- dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, dir), xferred_bytes, result, true);
-}
-
-void dcd_int_handler(uint8_t rhport)
-{
- dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
-
- uint32_t const int_enable = dcd_reg->USBINTR;
- uint32_t const int_status = dcd_reg->USBSTS & int_enable;
- dcd_reg->USBSTS = int_status; // Acknowledge handled interrupt
-
- // disabled interrupt sources
- if (int_status == 0) return;
-
- // Set if the port controller enters the full or high-speed operational state.
- // either from Bus Reset or Suspended state
- if (int_status & INTR_PORT_CHANGE)
- {
- // TU_LOG2("PortChange %08lx\r\n", dcd_reg->PORTSC1);
-
- // Reset interrupt is not enabled, we manually check if Port Change is due
- // to connection / disconnection
- if ( dcd_reg->USBSTS & INTR_RESET )
- {
- dcd_reg->USBSTS = INTR_RESET;
-
- if (dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS)
- {
- uint32_t const speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS;
- bus_reset(rhport);
- dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true);
- }else
- {
- dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
- }
- }
- else
- {
- // Triggered by resuming from suspended state
- if ( !(dcd_reg->PORTSC1 & PORTSC1_SUSPEND) )
- {
- dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
- }
- }
- }
-
- if (int_status & INTR_SUSPEND)
- {
- // TU_LOG2("Suspend %08lx\r\n", dcd_reg->PORTSC1);
-
- if (dcd_reg->PORTSC1 & PORTSC1_SUSPEND)
- {
- // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration.
- // Skip suspend event if we are not addressed
- if ((dcd_reg->DEVICEADDR >> 25) & 0x0f)
- {
- dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
- }
- }
- }
-
- if (int_status & INTR_USB)
- {
- // Make sure we read the latest version of _dcd_data.
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
-
- uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE;
- dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge
-
- if (dcd_reg->ENDPTSETUPSTAT)
- {
- //------------- Set up Received -------------//
- // 23.10.10.2 Operational model for setup transfers
- dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;
-
- dcd_event_setup_received(rhport, (uint8_t*)(uintptr_t) &_dcd_data.qhd[0][0].setup_request, true);
- }
-
- // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
- // nothing to do, we will submit xfer as error to usbd
- // if (int_status & INTR_ERROR) { }
-
- if ( edpt_complete )
- {
- for(uint8_t epnum = 0; epnum < TUP_DCD_ENDPOINT_MAX; epnum++)
- {
- if ( tu_bit_test(edpt_complete, epnum) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_OUT);
- if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN);
- }
- }
- }
-
- if (int_status & INTR_SOF)
- {
- dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
- }
-}
-
-#endif
diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c
deleted file mode 100644
index 0b3e9e4ef..000000000
--- a/src/portable/nxp/transdimension/hcd_transdimension.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "tusb_option.h"
-
-// NXP Trans-Dimension USB IP implement EHCI for host functionality
-
-#if CFG_TUH_ENABLED && \
- (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT)
-
-#warning "transdimenion is renamed to chipidea (portable/chipidea/ci_hs) to match other opensource naming convention such as linux. This file will be removed in the future, please update your makefile accordingly"
-
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#if CFG_TUSB_MCU == OPT_MCU_MIMXRT
- #include "fsl_device_registers.h"
-#else
- // LPCOpen for 18xx & 43xx
- #include "chip.h"
-#endif
-
-#include "common/tusb_common.h"
-#include "common_transdimension.h"
-#include "portable/ehci/ehci_api.h"
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
-// TODO can be merged with dcd_controller_t
-typedef struct
-{
- uint32_t regs_base; // registers base
- const IRQn_Type irqnum; // IRQ number
-}hcd_controller_t;
-
-#if CFG_TUSB_MCU == OPT_MCU_MIMXRT
- static const hcd_controller_t _hcd_controller[] =
- {
- // RT1010 and RT1020 only has 1 USB controller
- #if FSL_FEATURE_SOC_USBHS_COUNT == 1
- { .regs_base = USB_BASE , .irqnum = USB_OTG1_IRQn }
- #else
- { .regs_base = USB1_BASE, .irqnum = USB_OTG1_IRQn },
- { .regs_base = USB2_BASE, .irqnum = USB_OTG2_IRQn }
- #endif
- };
-
-#else
- static const hcd_controller_t _hcd_controller[] =
- {
- { .regs_base = LPC_USB0_BASE, .irqnum = USB0_IRQn },
- { .regs_base = LPC_USB1_BASE, .irqnum = USB1_IRQn }
- };
-#endif
-
-//--------------------------------------------------------------------+
-// Controller API
-//--------------------------------------------------------------------+
-
-bool hcd_init(uint8_t rhport)
-{
- hcd_registers_t* hcd_reg = (hcd_registers_t*) _hcd_controller[rhport].regs_base;
-
- // Reset controller
- hcd_reg->USBCMD |= USBCMD_RESET;
- while( hcd_reg->USBCMD & USBCMD_RESET ) {}
-
- // Set mode to device, must be set immediately after reset
-#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
- // LPC18XX/43XX need to set VBUS Power Select to HIGH
- // RHPORT1 is fullspeed only (need external PHY for Highspeed)
- hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
- if (rhport == 1) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
-#else
- hcd_reg->USBMODE = USBMODE_CM_HOST;
-#endif
-
- // FIXME force full speed, still have issue with Highspeed enumeration
- hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
-
- return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD);
-}
-
-void hcd_int_enable(uint8_t rhport)
-{
- NVIC_EnableIRQ(_hcd_controller[rhport].irqnum);
-}
-
-void hcd_int_disable(uint8_t rhport)
-{
- NVIC_DisableIRQ(_hcd_controller[rhport].irqnum);
-}
-
-#endif
diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c
index 3f702d22c..c59d4755e 100644
--- a/src/portable/ohci/ohci.c
+++ b/src/portable/ohci/ohci.c
@@ -157,6 +157,7 @@ static ohci_ed_t * const p_ed_head[] =
static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed);
static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr);
+static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd);
//--------------------------------------------------------------------+
// USBH-HCD API
@@ -341,19 +342,24 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t
p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0);
}
-static void gtd_init(ohci_gtd_t* p_td, uint8_t* data_ptr, uint16_t total_bytes)
-{
+static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) {
tu_memclr(p_td, sizeof(ohci_gtd_t));
- p_td->used = 1;
- p_td->expected_bytes = total_bytes;
+ p_td->used = 1;
+ gtd_get_extra_data(p_td)->expected_bytes = total_bytes;
+
+ p_td->buffer_rounding = 1; // less than queued length is not a error
+ p_td->delay_interrupt = OHCI_INT_ON_COMPLETE_NO;
+ p_td->condition_code = OHCI_CCODE_NOT_ACCESSED;
- p_td->buffer_rounding = 1; // less than queued length is not a error
- p_td->delay_interrupt = OHCI_INT_ON_COMPLETE_NO;
- p_td->condition_code = OHCI_CCODE_NOT_ACCESSED;
+ uint8_t *cbp = (uint8_t *) _phys_addr(data_ptr);
- p_td->current_buffer_pointer = _phys_addr(data_ptr);
- p_td->buffer_end = total_bytes ? (_phys_addr(data_ptr + total_bytes - 1)) : (uint8_t *)p_td->current_buffer_pointer;
+ p_td->current_buffer_pointer = cbp;
+ if ( total_bytes ) {
+ p_td->buffer_end = _phys_addr(data_ptr + total_bytes - 1);
+ } else {
+ p_td->buffer_end = cbp;
+ }
}
static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr)
@@ -487,7 +493,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
ohci_ed_t* ed = &ohci_data.control[dev_addr].ed;
ohci_gtd_t *qtd = &ohci_data.control[dev_addr].gtd;
- gtd_init(qtd, (uint8_t*) setup_packet, 8);
+ gtd_init(qtd, (uint8_t*)(uintptr_t) setup_packet, 8);
qtd->index = dev_addr;
qtd->pid = PID_SETUP;
qtd->data_toggle = GTD_DT_DATA0;
@@ -543,8 +549,16 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
return true;
}
-bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
-{
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+ // TODO not implemented yet
+ return false;
+}
+
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr);
p_ed->is_stalled = 0;
@@ -597,6 +611,15 @@ static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd)
}
}
+static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) {
+ if ( gtd_is_control(gtd) ) {
+ uint8_t idx = ((uintptr_t)gtd - (uintptr_t)&ohci_data.control->gtd) / sizeof(ohci_data.control[0]);
+ return &ohci_data.gtd_extra_control[idx];
+ }else {
+ return &ohci_data.gtd_extra[gtd - ohci_data.gtd_pool];
+ }
+}
+
static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer)
{
// 5.2.9 OHCI sample code
@@ -628,8 +651,7 @@ static void done_queue_isr(uint8_t hostid)
if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) )
{
ohci_ed_t * const ed = gtd_get_ed(qtd);
-
- uint32_t const xferred_bytes = qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer);
+ uint32_t const xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer);
// NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs.
// When there is a error resulting this ED is halted, and this EP still has other queued TD
@@ -638,7 +660,7 @@ static void done_queue_isr(uint8_t hostid)
// --> HC will not process Control list (due to service ratio when Bulk list not empty)
// To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt
// the TailP must be set back to NULL for processing remaining TDs
- if ((event != XFER_RESULT_SUCCESS))
+ if (event != XFER_RESULT_SUCCESS)
{
ed->td_tail &= 0x0Ful;
ed->td_tail |= tu_align16(ed->td_head.address); // mark halted EP as empty queue
@@ -654,8 +676,9 @@ static void done_queue_isr(uint8_t hostid)
}
}
-void hcd_int_handler(uint8_t hostid)
-{
+void hcd_int_handler(uint8_t hostid, bool in_isr) {
+ (void) in_isr;
+
uint32_t const int_en = OHCI_REG->interrupt_enable;
uint32_t const int_status = OHCI_REG->interrupt_status & int_en;
diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h
index 2081ffabb..94bad5df7 100644
--- a/src/portable/ohci/ohci.h
+++ b/src/portable/ohci/ohci.h
@@ -45,6 +45,9 @@ enum {
#define ED_MAX (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX)
#define GTD_MAX ED_MAX
+// tinyUSB's OHCI implementation caps number of EDs to 8 bits
+TU_VERIFY_STATIC (ED_MAX <= 256, "Reduce CFG_TUH_DEVICE_MAX or CFG_TUH_ENDPOINT_MAX");
+
//--------------------------------------------------------------------+
// OHCI Data Structure
//--------------------------------------------------------------------+
@@ -70,9 +73,8 @@ typedef struct TU_ATTR_ALIGNED(16)
{
// Word 0
uint32_t used : 1;
- uint32_t index : 4; // endpoint index the td belongs to, or device address in case of control xfer
- uint32_t expected_bytes : 13; // TODO available for hcd
-
+ uint32_t index : 8; // endpoint index the gtd belongs to, or device address in case of control xfer
+ uint32_t : 9; // can be used
uint32_t buffer_rounding : 1;
uint32_t pid : 2;
uint32_t delay_interrupt : 3;
@@ -81,7 +83,7 @@ typedef struct TU_ATTR_ALIGNED(16)
volatile uint32_t condition_code : 4;
// Word 1
- volatile uint8_t* current_buffer_pointer;
+ uint8_t* volatile current_buffer_pointer;
// Word 2 : next TD
volatile uint32_t next;
@@ -152,9 +154,12 @@ typedef struct TU_ATTR_ALIGNED(32)
TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" );
+typedef struct {
+ uint16_t expected_bytes; // up to 8192 bytes so max is 13 bits
+} gtd_extra_data_t;
+
// structure with member alignment required from large to small
-typedef struct TU_ATTR_ALIGNED(256)
-{
+typedef struct TU_ATTR_ALIGNED(256) {
ohci_hcca_t hcca;
ohci_ed_t bulk_head_ed; // static bulk head (dummy)
@@ -164,14 +169,17 @@ typedef struct TU_ATTR_ALIGNED(256)
struct {
ohci_ed_t ed;
ohci_gtd_t gtd;
- }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1];
+ } control[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB + 1];
// ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32
ohci_ed_t ed_pool[ED_MAX];
ohci_gtd_t gtd_pool[GTD_MAX];
- volatile uint16_t frame_number_hi;
+ // extra data needed by TDs that can't fit in the TD struct
+ gtd_extra_data_t gtd_extra_control[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB + 1];
+ gtd_extra_data_t gtd_extra[GTD_MAX];
+ volatile uint16_t frame_number_hi;
} ohci_data_t;
//--------------------------------------------------------------------+
diff --git a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c
index 58b153ac3..f4de3c51d 100644
--- a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c
+++ b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c
@@ -48,16 +48,14 @@ static pio_usb_configuration_t pio_host_cfg = PIO_USB_DEFAULT_CONFIG;
//--------------------------------------------------------------------+
// HCD API
//--------------------------------------------------------------------+
-bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param)
-{
+bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param) {
(void) rhport;
TU_VERIFY(cfg_id == TUH_CFGID_RPI_PIO_USB_CONFIGURATION);
memcpy(&pio_host_cfg, cfg_param, sizeof(pio_usb_configuration_t));
return true;
}
-bool hcd_init(uint8_t rhport)
-{
+bool hcd_init(uint8_t rhport) {
(void) rhport;
// To run USB SOF interrupt in core1, call this init in core1
@@ -66,20 +64,17 @@ bool hcd_init(uint8_t rhport)
return true;
}
-void hcd_port_reset(uint8_t rhport)
-{
+void hcd_port_reset(uint8_t rhport) {
uint8_t const pio_rhport = RHPORT_PIO(rhport);
pio_usb_host_port_reset_start(pio_rhport);
}
-void hcd_port_reset_end(uint8_t rhport)
-{
+void hcd_port_reset_end(uint8_t rhport) {
uint8_t const pio_rhport = RHPORT_PIO(rhport);
pio_usb_host_port_reset_end(pio_rhport);
}
-bool hcd_port_connect_status(uint8_t rhport)
-{
+bool hcd_port_connect_status(uint8_t rhport) {
uint8_t const pio_rhport = RHPORT_PIO(rhport);
root_port_t *root = PIO_USB_ROOT_PORT(pio_rhport);
@@ -88,33 +83,28 @@ bool hcd_port_connect_status(uint8_t rhport)
return line_state != PORT_PIN_SE0;
}
-tusb_speed_t hcd_port_speed_get(uint8_t rhport)
-{
+tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
// TODO determine link speed
uint8_t const pio_rhport = RHPORT_PIO(rhport);
return PIO_USB_ROOT_PORT(pio_rhport)->is_fullspeed ? TUSB_SPEED_FULL : TUSB_SPEED_LOW;
}
// Close all opened endpoint belong to this device
-void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
-{
+void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
uint8_t const pio_rhport = RHPORT_PIO(rhport);
pio_usb_host_close_device(pio_rhport, dev_addr);
}
-uint32_t hcd_frame_number(uint8_t rhport)
-{
+uint32_t hcd_frame_number(uint8_t rhport) {
(void) rhport;
- return 0;
+ return pio_usb_host_get_frame_number();
}
-void hcd_int_enable(uint8_t rhport)
-{
+void hcd_int_enable(uint8_t rhport) {
(void) rhport;
}
-void hcd_int_disable(uint8_t rhport)
-{
+void hcd_int_disable(uint8_t rhport) {
(void) rhport;
}
@@ -122,24 +112,26 @@ void hcd_int_disable(uint8_t rhport)
// Endpoint API
//--------------------------------------------------------------------+
-bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
-{
+bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *desc_ep) {
hcd_devtree_info_t dev_tree;
hcd_devtree_get_info(dev_addr, &dev_tree);
bool const need_pre = (dev_tree.hub_addr && dev_tree.speed == TUSB_SPEED_LOW);
uint8_t const pio_rhport = RHPORT_PIO(rhport);
- return pio_usb_host_endpoint_open(pio_rhport, dev_addr, (uint8_t const*) desc_ep, need_pre);
+ return pio_usb_host_endpoint_open(pio_rhport, dev_addr, (uint8_t const *) desc_ep, need_pre);
}
-bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
-{
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) {
uint8_t const pio_rhport = RHPORT_PIO(rhport);
return pio_usb_host_endpoint_transfer(pio_rhport, dev_addr, ep_addr, buffer, buflen);
}
-bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
-{
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ uint8_t const pio_rhport = RHPORT_PIO(rhport);
+ return pio_usb_host_endpoint_abort_transfer(pio_rhport, dev_addr, ep_addr);
+}
+
+bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) {
uint8_t const pio_rhport = RHPORT_PIO(rhport);
return pio_usb_host_send_setup(pio_rhport, dev_addr, setup_packet);
}
@@ -150,34 +142,32 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
// // so if any transfer is active on epx, we are busy. Interrupt endpoints have their own
// // EPX so ep->active will only be busy if there is a pending transfer on that interrupt endpoint
// // on that device
-// pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\n", dev_addr, ep_addr);
+// pico_trace("hcd_edpt_busy dev addr %d ep_addr 0x%x\r\n", dev_addr, ep_addr);
// struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
// assert(ep);
// bool busy = ep->active;
-// pico_trace("busy == %d\n", busy);
+// pico_trace("busy == %d\r\n", busy);
// return busy;
//}
-bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
-{
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
(void) dev_addr;
(void) ep_addr;
return true;
}
-static void __no_inline_not_in_flash_func(handle_endpoint_irq)(root_port_t* rport, xfer_result_t result, volatile uint32_t* ep_reg)
-{
+static void __no_inline_not_in_flash_func(handle_endpoint_irq)(root_port_t *rport, xfer_result_t result,
+ volatile uint32_t *ep_reg) {
(void) rport;
const uint32_t ep_all = *ep_reg;
- for(uint8_t ep_idx = 0; ep_idx < PIO_USB_EP_POOL_CNT; ep_idx++)
- {
+ for ( uint8_t ep_idx = 0; ep_idx < PIO_USB_EP_POOL_CNT; ep_idx++ ) {
uint32_t const mask = (1u << ep_idx);
- if (ep_all & mask)
- {
- endpoint_t* ep = PIO_USB_ENDPOINT(ep_idx);
+ if ( ep_all & mask ) {
+ endpoint_t * ep = PIO_USB_ENDPOINT(ep_idx);
hcd_event_xfer_complete(ep->dev_addr, ep->ep_num, ep->actual_len, result, true);
}
}
@@ -187,35 +177,29 @@ static void __no_inline_not_in_flash_func(handle_endpoint_irq)(root_port_t* rpor
}
// IRQ Handler
-void __no_inline_not_in_flash_func(pio_usb_host_irq_handler)(uint8_t root_id)
-{
+void __no_inline_not_in_flash_func(pio_usb_host_irq_handler)(uint8_t root_id) {
uint8_t const tu_rhport = root_id + 1;
- root_port_t* rport = PIO_USB_ROOT_PORT(root_id);
+ root_port_t *rport = PIO_USB_ROOT_PORT(root_id);
uint32_t const ints = rport->ints;
- if ( ints & PIO_USB_INTS_CONNECT_BITS )
- {
- hcd_event_device_attach(tu_rhport, true);
+ if ( ints & PIO_USB_INTS_ENDPOINT_COMPLETE_BITS ) {
+ handle_endpoint_irq(rport, XFER_RESULT_SUCCESS, &rport->ep_complete);
}
- if ( ints & PIO_USB_INTS_DISCONNECT_BITS )
- {
- hcd_event_device_remove(tu_rhport, true);
+ if ( ints & PIO_USB_INTS_ENDPOINT_STALLED_BITS ) {
+ handle_endpoint_irq(rport, XFER_RESULT_STALLED, &rport->ep_stalled);
}
- if ( ints & PIO_USB_INTS_ENDPOINT_COMPLETE_BITS )
- {
- handle_endpoint_irq(rport, XFER_RESULT_SUCCESS, &rport->ep_complete);
+ if ( ints & PIO_USB_INTS_ENDPOINT_ERROR_BITS ) {
+ handle_endpoint_irq(rport, XFER_RESULT_FAILED, &rport->ep_error);
}
- if ( ints & PIO_USB_INTS_ENDPOINT_STALLED_BITS )
- {
- handle_endpoint_irq(rport, XFER_RESULT_STALLED, &rport->ep_stalled);
+ if ( ints & PIO_USB_INTS_CONNECT_BITS ) {
+ hcd_event_device_attach(tu_rhport, true);
}
- if ( ints & PIO_USB_INTS_ENDPOINT_ERROR_BITS )
- {
- handle_endpoint_irq(rport, XFER_RESULT_FAILED, &rport->ep_error);
+ if ( ints & PIO_USB_INTS_DISCONNECT_BITS ) {
+ hcd_event_device_remove(tu_rhport, true);
}
// clear all
diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
index 500a5373f..bc0deee32 100644
--- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
@@ -48,7 +48,7 @@
*------------------------------------------------------------------*/
// Init these in dcd_init
-static uint8_t *next_buffer_ptr;
+static uint8_t* next_buffer_ptr;
// USB_MAX_ENDPOINTS Endpoints, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in.
static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2];
@@ -56,79 +56,70 @@ static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2];
// SOF may be used by remote wakeup as RESUME, this indicate whether SOF is actually used by usbd
static bool _sof_enable = false;
-TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir)
-{
+TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir) {
return &hw_endpoints[num][dir];
}
-static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr)
-{
+TU_ATTR_ALWAYS_INLINE static inline struct hw_endpoint* hw_endpoint_get_by_addr(uint8_t ep_addr) {
uint8_t num = tu_edpt_number(ep_addr);
tusb_dir_t dir = tu_edpt_dir(ep_addr);
return hw_endpoint_get_by_num(num, dir);
}
-static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type)
-{
+static void _hw_endpoint_alloc(struct hw_endpoint* ep, uint8_t transfer_type) {
// size must be multiple of 64
uint size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u;
// double buffered Bulk endpoint
- if ( transfer_type == TUSB_XFER_BULK )
- {
+ if (transfer_type == TUSB_XFER_BULK) {
size *= 2u;
}
ep->hw_data_buf = next_buffer_ptr;
next_buffer_ptr += size;
- assert(((uintptr_t )next_buffer_ptr & 0b111111u) == 0);
+ assert(((uintptr_t) next_buffer_ptr & 0b111111u) == 0);
uint dpram_offset = hw_data_offset(ep->hw_data_buf);
hard_assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
pico_info(" Allocated %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf);
// Fill in endpoint control register with buffer offset
- uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint)transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset;
+ uint32_t const reg = EP_CTRL_ENABLE_BITS | ((uint) transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset;
*ep->endpoint_control = reg;
}
-static void _hw_endpoint_close(struct hw_endpoint *ep)
-{
- // Clear hardware registers and then zero the struct
- // Clears endpoint enable
- *ep->endpoint_control = 0;
- // Clears buffer available, etc
- *ep->buffer_control = 0;
- // Clear any endpoint state
- memset(ep, 0, sizeof(struct hw_endpoint));
+static void _hw_endpoint_close(struct hw_endpoint* ep) {
+ // Clear hardware registers and then zero the struct
+ // Clears endpoint enable
+ *ep->endpoint_control = 0;
+ // Clears buffer available, etc
+ *ep->buffer_control = 0;
+ // Clear any endpoint state
+ memset(ep, 0, sizeof(struct hw_endpoint));
- // Reclaim buffer space if all endpoints are closed
- bool reclaim_buffers = true;
- for ( uint8_t i = 1; i < USB_MAX_ENDPOINTS; i++ )
- {
- if (hw_endpoint_get_by_num(i, TUSB_DIR_OUT)->hw_data_buf != NULL || hw_endpoint_get_by_num(i, TUSB_DIR_IN)->hw_data_buf != NULL)
- {
- reclaim_buffers = false;
- break;
- }
- }
- if (reclaim_buffers)
- {
- next_buffer_ptr = &usb_dpram->epx_data[0];
+ // Reclaim buffer space if all endpoints are closed
+ bool reclaim_buffers = true;
+ for (uint8_t i = 1; i < USB_MAX_ENDPOINTS; i++) {
+ if (hw_endpoint_get_by_num(i, TUSB_DIR_OUT)->hw_data_buf != NULL ||
+ hw_endpoint_get_by_num(i, TUSB_DIR_IN)->hw_data_buf != NULL) {
+ reclaim_buffers = false;
+ break;
}
+ }
+ if (reclaim_buffers) {
+ next_buffer_ptr = &usb_dpram->epx_data[0];
+ }
}
-static void hw_endpoint_close(uint8_t ep_addr)
-{
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
- _hw_endpoint_close(ep);
+static void hw_endpoint_close(uint8_t ep_addr) {
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
+ _hw_endpoint_close(ep);
}
-static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type)
-{
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
+static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type) {
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
const uint8_t num = tu_edpt_number(ep_addr);
const tusb_dir_t dir = tu_edpt_dir(ep_addr);
@@ -143,35 +134,26 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t
ep->transfer_type = transfer_type;
// Every endpoint has a buffer control register in dpram
- if ( dir == TUSB_DIR_IN )
- {
+ if (dir == TUSB_DIR_IN) {
ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in;
- }
- else
- {
+ } else {
ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out;
}
// Clear existing buffer control state
*ep->buffer_control = 0;
- if ( num == 0 )
- {
+ if (num == 0) {
// EP0 has no endpoint control register because the buffer offsets are fixed
ep->endpoint_control = NULL;
// Buffer offset is fixed (also double buffered)
ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0];
- }
- else
- {
+ } else {
// Set the endpoint control register (starts at EP1, hence num-1)
- if ( dir == TUSB_DIR_IN )
- {
+ if (dir == TUSB_DIR_IN) {
ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].in;
- }
- else
- {
+ } else {
ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out;
}
@@ -180,76 +162,82 @@ static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t t
}
}
-static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
-{
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
- hw_endpoint_xfer_start(ep, buffer, total_bytes);
+static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
+ hw_endpoint_xfer_start(ep, buffer, total_bytes);
}
-static void __tusb_irq_path_func(hw_handle_buff_status)(void)
-{
- uint32_t remaining_buffers = usb_hw->buf_status;
- pico_trace("buf_status = 0x%08x\n", remaining_buffers);
- uint bit = 1u;
- for (uint8_t i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++)
- {
- if (remaining_buffers & bit)
- {
- // clear this in advance
- usb_hw_clear->buf_status = bit;
+static void __tusb_irq_path_func(hw_handle_buff_status)(void) {
+ uint32_t remaining_buffers = usb_hw->buf_status;
+ pico_trace("buf_status = 0x%08lx\r\n", remaining_buffers);
+ uint bit = 1u;
+ for (uint8_t i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++) {
+ if (remaining_buffers & bit) {
+ // clear this in advance
+ usb_hw_clear->buf_status = bit;
- // IN transfer for even i, OUT transfer for odd i
- struct hw_endpoint *ep = hw_endpoint_get_by_num(i >> 1u, (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN);
+ // IN transfer for even i, OUT transfer for odd i
+ struct hw_endpoint* ep = hw_endpoint_get_by_num(i >> 1u, (i & 1u) ? TUSB_DIR_OUT : TUSB_DIR_IN);
- // Continue xfer
- bool done = hw_endpoint_xfer_continue(ep);
- if (done)
- {
- // Notify
- dcd_event_xfer_complete(0, ep->ep_addr, ep->xferred_len, XFER_RESULT_SUCCESS, true);
- hw_endpoint_reset_transfer(ep);
- }
- remaining_buffers &= ~bit;
- }
- bit <<= 1u;
+ // Continue xfer
+ bool done = hw_endpoint_xfer_continue(ep);
+ if (done) {
+ // Notify
+ dcd_event_xfer_complete(0, ep->ep_addr, ep->xferred_len, XFER_RESULT_SUCCESS, true);
+ hw_endpoint_reset_transfer(ep);
+ }
+ remaining_buffers &= ~bit;
}
+ bit <<= 1u;
+ }
}
-TU_ATTR_ALWAYS_INLINE static inline void reset_ep0_pid(void)
-{
- // If we have finished this transfer on EP0 set pid back to 1 for next
- // setup transfer. Also clear a stall in case
- uint8_t addrs[] = {0x0, 0x80};
- for (uint i = 0 ; i < TU_ARRAY_SIZE(addrs); i++)
- {
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(addrs[i]);
- ep->next_pid = 1u;
+TU_ATTR_ALWAYS_INLINE static inline void reset_ep0(void) {
+ // If we have finished this transfer on EP0 set pid back to 1 for next
+ // setup transfer. Also clear a stall in case
+ for (uint8_t dir = 0; dir < 2; dir++) {
+ struct hw_endpoint* ep = hw_endpoint_get_by_num(0, dir);
+ if (ep->active) {
+ // Abort any pending transfer from a prior control transfer per USB specs
+ // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1).
+ // Which means we are not guaranteed to safely abort pending transfer on B0 and B1.
+ uint32_t const abort_mask = (dir ? USB_EP_ABORT_EP0_IN_BITS : USB_EP_ABORT_EP0_OUT_BITS);
+ if (rp2040_chip_version() >= 2) {
+ usb_hw_set->abort = abort_mask;
+ while ((usb_hw->abort_done & abort_mask) != abort_mask) {}
+ }
+
+ _hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_DATA1_PID | USB_BUF_CTRL_SEL);
+ hw_endpoint_reset_transfer(ep);
+
+ if (rp2040_chip_version() >= 2) {
+ usb_hw_clear->abort_done = abort_mask;
+ usb_hw_clear->abort = abort_mask;
+ }
}
+ ep->next_pid = 1u;
+ }
}
-static void __tusb_irq_path_func(reset_non_control_endpoints)(void)
-{
+static void __tusb_irq_path_func(reset_non_control_endpoints)(void) {
// Disable all non-control
- for ( uint8_t i = 0; i < USB_MAX_ENDPOINTS-1; i++ )
- {
+ for (uint8_t i = 0; i < USB_MAX_ENDPOINTS - 1; i++) {
usb_dpram->ep_ctrl[i].in = 0;
usb_dpram->ep_ctrl[i].out = 0;
}
// clear non-control hw endpoints
- tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2*sizeof(hw_endpoint_t));
+ tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2 * sizeof(hw_endpoint_t));
// reclaim buffer space
next_buffer_ptr = &usb_dpram->epx_data[0];
}
-static void __tusb_irq_path_func(dcd_rp2040_irq)(void)
-{
+static void __tusb_irq_path_func(dcd_rp2040_irq)(void) {
uint32_t const status = usb_hw->ints;
uint32_t handled = 0;
- if ( status & USB_INTF_DEV_SOF_BITS )
- {
+ if (status & USB_INTF_DEV_SOF_BITS) {
bool keep_sof_alive = false;
handled |= USB_INTF_DEV_SOF_BITS;
@@ -258,20 +246,17 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void)
// Errata 15 workaround for Device Bulk-In endpoint
e15_last_sof = time_us_32();
- for ( uint8_t i = 0; i < USB_MAX_ENDPOINTS; i++ )
- {
- struct hw_endpoint * ep = hw_endpoint_get_by_num(i, TUSB_DIR_IN);
+ for (uint8_t i = 0; i < USB_MAX_ENDPOINTS; i++) {
+ struct hw_endpoint* ep = hw_endpoint_get_by_num(i, TUSB_DIR_IN);
// Active Bulk IN endpoint requires SOF
- if ( (ep->transfer_type == TUSB_XFER_BULK) && ep->active )
- {
+ if ((ep->transfer_type == TUSB_XFER_BULK) && ep->active) {
keep_sof_alive = true;
hw_endpoint_lock_update(ep, 1);
// Deferred enable?
- if ( ep->pending )
- {
+ if (ep->pending) {
ep->pending = 0;
hw_endpoint_start_next_buffer(ep);
}
@@ -282,26 +267,24 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void)
#endif
// disable SOF interrupt if it is used for RESUME in remote wakeup
- if ( !keep_sof_alive && !_sof_enable ) usb_hw_clear->inte = USB_INTS_DEV_SOF_BITS;
+ if (!keep_sof_alive && !_sof_enable) usb_hw_clear->inte = USB_INTS_DEV_SOF_BITS;
dcd_event_sof(0, usb_hw->sof_rd & USB_SOF_RD_BITS, true);
}
// xfer events are handled before setup req. So if a transfer completes immediately
// before closing the EP, the events will be delivered in same order.
- if ( status & USB_INTS_BUFF_STATUS_BITS )
- {
+ if (status & USB_INTS_BUFF_STATUS_BITS) {
handled |= USB_INTS_BUFF_STATUS_BITS;
hw_handle_buff_status();
}
- if ( status & USB_INTS_SETUP_REQ_BITS )
- {
+ if (status & USB_INTS_SETUP_REQ_BITS) {
handled |= USB_INTS_SETUP_REQ_BITS;
- uint8_t const * setup = remove_volatile_cast(uint8_t const*, &usb_dpram->setup_packet);
+ uint8_t const* setup = remove_volatile_cast(uint8_t const*, &usb_dpram->setup_packet);
// reset pid to both 1 (data and ack)
- reset_ep0_pid();
+ reset_ep0();
// Pass setup packet to tiny usb
dcd_event_setup_received(0, setup, true);
@@ -329,9 +312,8 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void)
#endif
// SE0 for 2.5 us or more (will last at least 10ms)
- if ( status & USB_INTS_BUS_RESET_BITS )
- {
- pico_trace("BUS RESET\n");
+ if (status & USB_INTS_BUS_RESET_BITS) {
+ pico_trace("BUS RESET\r\n");
handled |= USB_INTS_BUS_RESET_BITS;
@@ -342,7 +324,7 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void)
#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
// Only run enumeration workaround if pull up is enabled
- if ( usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS ) rp2040_usb_device_enumeration_fix();
+ if (usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS) rp2040_usb_device_enumeration_fix();
#endif
}
@@ -354,22 +336,19 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void)
* because without VBUS detection, it is impossible to tell the difference between
* being disconnected and suspended.
*/
- if ( status & USB_INTS_DEV_SUSPEND_BITS )
- {
+ if (status & USB_INTS_DEV_SUSPEND_BITS) {
handled |= USB_INTS_DEV_SUSPEND_BITS;
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS;
}
- if ( status & USB_INTS_DEV_RESUME_FROM_HOST_BITS )
- {
+ if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS) {
handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS;
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS;
}
- if ( status ^ handled )
- {
+ if (status ^ handled) {
panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled));
}
}
@@ -390,10 +369,11 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void)
#define PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY 0xff
#endif
-void dcd_init (uint8_t rhport)
-{
+void dcd_init(uint8_t rhport) {
assert(rhport == 0);
+ TU_LOG(2, "Chip Version B%u\r\n", rp2040_chip_version());
+
// Reset hardware to default state
rp2040_usb_init();
@@ -405,7 +385,7 @@ void dcd_init (uint8_t rhport)
irq_add_shared_handler(USBCTRL_IRQ, dcd_rp2040_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
// Init control endpoints
- tu_memclr(hw_endpoints[0], 2*sizeof(hw_endpoint_t));
+ tu_memclr(hw_endpoints[0], 2 * sizeof(hw_endpoint_t));
hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL);
hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL);
@@ -420,27 +400,37 @@ void dcd_init (uint8_t rhport)
// for the global interrupt enable...
// Note: Force VBUS detect cause disconnection not detectable
usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS;
- usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
- USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS |
- (FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS);
+ usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
+ USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS |
+ (FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS);
dcd_connect(rhport);
}
-void dcd_int_enable(__unused uint8_t rhport)
-{
- assert(rhport == 0);
- irq_set_enabled(USBCTRL_IRQ, true);
+bool dcd_deinit(uint8_t rhport) {
+ (void) rhport;
+
+ reset_non_control_endpoints();
+ irq_remove_handler(USBCTRL_IRQ, dcd_rp2040_irq);
+
+ // reset usb hardware into initial state
+ reset_block(RESETS_RESET_USBCTRL_BITS);
+ unreset_block_wait(RESETS_RESET_USBCTRL_BITS);
+
+ return true;
+}
+
+void dcd_int_enable(__unused uint8_t rhport) {
+ assert(rhport == 0);
+ irq_set_enabled(USBCTRL_IRQ, true);
}
-void dcd_int_disable(__unused uint8_t rhport)
-{
- assert(rhport == 0);
- irq_set_enabled(USBCTRL_IRQ, false);
+void dcd_int_disable(__unused uint8_t rhport) {
+ assert(rhport == 0);
+ irq_set_enabled(USBCTRL_IRQ, false);
}
-void dcd_set_address (__unused uint8_t rhport, __unused uint8_t dev_addr)
-{
+void dcd_set_address(__unused uint8_t rhport, __unused uint8_t dev_addr) {
assert(rhport == 0);
// Can't set device address in hardware until status xfer has complete
@@ -448,8 +438,7 @@ void dcd_set_address (__unused uint8_t rhport, __unused uint8_t dev_addr)
hw_endpoint_xfer(0x80, NULL, 0);
}
-void dcd_remote_wakeup(__unused uint8_t rhport)
-{
+void dcd_remote_wakeup(__unused uint8_t rhport) {
pico_info("dcd_remote_wakeup %d\n", rhport);
assert(rhport == 0);
@@ -460,100 +449,88 @@ void dcd_remote_wakeup(__unused uint8_t rhport)
}
// disconnect by disabling internal pull-up resistor on D+/D-
-void dcd_disconnect(__unused uint8_t rhport)
-{
+void dcd_disconnect(__unused uint8_t rhport) {
(void) rhport;
usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
}
// connect by enabling internal pull-up resistor on D+/D-
-void dcd_connect(__unused uint8_t rhport)
-{
+void dcd_connect(__unused uint8_t rhport) {
(void) rhport;
usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
}
-void dcd_sof_enable(uint8_t rhport, bool en)
-{
+void dcd_sof_enable(uint8_t rhport, bool en) {
(void) rhport;
_sof_enable = en;
- if (en)
- {
+ if (en) {
usb_hw_set->inte = USB_INTS_DEV_SOF_BITS;
- }else
- {
+ }
+#if !TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
+ else {
// Don't clear immediately if the SOF workaround is in use.
// The SOF handler will conditionally disable the interrupt.
-#if !TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
usb_hw_clear->inte = USB_INTS_DEV_SOF_BITS;
-#endif
}
+#endif
}
/*------------------------------------------------------------------*/
/* DCD Endpoint port
*------------------------------------------------------------------*/
-void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request)
-{
+void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const* request) {
(void) rhport;
- if ( request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
- request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
- request->bRequest == TUSB_REQ_SET_ADDRESS )
- {
+ if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
+ request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
+ request->bRequest == TUSB_REQ_SET_ADDRESS) {
usb_hw->dev_addr_ctrl = (uint8_t) request->wValue;
}
}
-bool dcd_edpt_open (__unused uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
-{
- assert(rhport == 0);
- hw_endpoint_init(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), desc_edpt->bmAttributes.xfer);
- return true;
+bool dcd_edpt_open(__unused uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
+ assert(rhport == 0);
+ hw_endpoint_init(desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt), desc_edpt->bmAttributes.xfer);
+ return true;
}
-void dcd_edpt_close_all (uint8_t rhport)
-{
+void dcd_edpt_close_all(uint8_t rhport) {
(void) rhport;
// may need to use EP Abort
reset_non_control_endpoints();
}
-bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
-{
- assert(rhport == 0);
- hw_endpoint_xfer(ep_addr, buffer, total_bytes);
- return true;
+bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
+ assert(rhport == 0);
+ hw_endpoint_xfer(ep_addr, buffer, total_bytes);
+ return true;
}
-void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
-{
+void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
(void) rhport;
- if ( tu_edpt_number(ep_addr) == 0 )
- {
+ if (tu_edpt_number(ep_addr) == 0) {
// A stall on EP0 has to be armed so it can be cleared on the next setup packet
- usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS;
+ usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS
+ : USB_EP_STALL_ARM_EP0_OUT_BITS;
}
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
// stall and clear current pending buffer
// may need to use EP_ABORT
_hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_STALL);
}
-void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
-{
+void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
(void) rhport;
- if (tu_edpt_number(ep_addr))
- {
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
+ if (tu_edpt_number(ep_addr)) {
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
// clear stall also reset toggle to DATA0, ready for next transfer
ep->next_pid = 0;
@@ -561,16 +538,13 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
}
}
-void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
-{
- (void) rhport;
-
- pico_trace("dcd_edpt_close %02x\n", ep_addr);
- hw_endpoint_close(ep_addr);
+void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
+ (void) rhport;
+ pico_trace("dcd_edpt_close %02x\r\n", ep_addr);
+ hw_endpoint_close(ep_addr);
}
-void __tusb_irq_path_func(dcd_int_handler)(uint8_t rhport)
-{
+void __tusb_irq_path_func(dcd_int_handler)(uint8_t rhport) {
(void) rhport;
dcd_rp2040_irq();
}
diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
index 02f9968a7..222dbbbf0 100644
--- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
@@ -27,7 +27,7 @@
#include "tusb_option.h"
-#if CFG_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && !CFG_TUH_RPI_PIO_USB
+#if CFG_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && !CFG_TUH_RPI_PIO_USB && !CFG_TUH_MAX3421
#include "pico.h"
#include "rp2040_usb.h"
@@ -113,7 +113,7 @@ static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_en
static void __tusb_irq_path_func(hw_handle_buff_status)(void)
{
uint32_t remaining_buffers = usb_hw->buf_status;
- pico_trace("buf_status 0x%08x\n", remaining_buffers);
+ pico_trace("buf_status 0x%08lx\n", remaining_buffers);
// Check EPX first
uint bit = 0b1;
@@ -219,7 +219,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void)
if ( status & USB_INTS_BUFF_STATUS_BITS )
{
handled |= USB_INTS_BUFF_STATUS_BITS;
- TU_LOG(2, "Buffer complete\n");
+ TU_LOG(2, "Buffer complete\r\n");
hw_handle_buff_status();
}
@@ -227,7 +227,7 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void)
{
handled |= USB_INTS_TRANS_COMPLETE_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS;
- TU_LOG(2, "Transfer complete\n");
+ TU_LOG(2, "Transfer complete\r\n");
hw_trans_complete();
}
@@ -252,9 +252,9 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void)
}
}
-void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport)
-{
+void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) {
(void) rhport;
+ (void) in_isr;
hcd_rp2040_irq();
}
@@ -325,10 +325,8 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
ep->wMaxPacketSize = wMaxPacketSize;
ep->transfer_type = transfer_type;
- pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, tu_edpt_number(ep->ep_addr),
- ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->transfer_type);
- pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, tu_edpt_number(ep->ep_addr),
- ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->hw_data_buf);
+ pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->ep_addr, ep->transfer_type);
+ pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->ep_addr, ep->hw_data_buf);
uint dpram_offset = hw_data_offset(ep->hw_data_buf);
// Bits 0-5 should be 0
assert(!(dpram_offset & 0b111111));
@@ -343,7 +341,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
ep_reg |= (uint32_t) ((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB);
}
*ep->endpoint_control = ep_reg;
- pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg);
+ pico_trace("endpoint control (0x%p) <- 0x%lx\n", ep->endpoint_control, ep_reg);
ep->configured = true;
if ( ep != &epx )
@@ -411,6 +409,16 @@ bool hcd_init(uint8_t rhport)
return true;
}
+bool hcd_deinit(uint8_t rhport) {
+ (void) rhport;
+
+ irq_remove_handler(USBCTRL_IRQ, hcd_rp2040_irq);
+ reset_block(RESETS_RESET_USBCTRL_BITS);
+ unreset_block_wait(RESETS_RESET_USBCTRL_BITS);
+
+ return true;
+}
+
void hcd_port_reset(uint8_t rhport)
{
(void) rhport;
@@ -576,6 +584,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
return true;
}
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+ // TODO not implemented yet
+ return false;
+}
+
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
{
(void) rhport;
@@ -617,8 +633,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
return true;
}
-bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
-{
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
(void) dev_addr;
(void) ep_addr;
diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c
index cf37cba07..1ca711c77 100644
--- a/src/portable/raspberrypi/rp2040/rp2040_usb.c
+++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c
@@ -35,26 +35,18 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTOTYPE
//--------------------------------------------------------------------+
-
-// Direction strings for debug
-const char *ep_dir_string[] = {
- "out",
- "in",
-};
-
-static void _hw_endpoint_xfer_sync(struct hw_endpoint *ep);
+static void _hw_endpoint_xfer_sync(struct hw_endpoint* ep);
#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
- static bool e15_is_bulkin_ep(struct hw_endpoint *ep);
- static bool e15_is_critical_frame_period(struct hw_endpoint *ep);
+ static bool e15_is_bulkin_ep(struct hw_endpoint* ep);
+ static bool e15_is_critical_frame_period(struct hw_endpoint* ep);
#else
#define e15_is_bulkin_ep(x) (false)
#define e15_is_critical_frame_period(x) (false)
#endif
// if usb hardware is in host mode
-TU_ATTR_ALWAYS_INLINE static inline bool is_host_mode(void)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool is_host_mode(void) {
return (usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) ? true : false;
}
@@ -62,8 +54,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_host_mode(void)
// Implementation
//--------------------------------------------------------------------+
-void rp2040_usb_init(void)
-{
+void rp2040_usb_init(void) {
// Reset usb controller
reset_block(RESETS_RESET_USBCTRL_BITS);
unreset_block_wait(RESETS_RESET_USBCTRL_BITS);
@@ -88,46 +79,33 @@ void rp2040_usb_init(void)
TU_LOG2_INT(sizeof(hw_endpoint_t));
}
-void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint *ep)
-{
+void __tusb_irq_path_func(hw_endpoint_reset_transfer)(struct hw_endpoint* ep) {
ep->active = false;
ep->remaining_len = 0;
ep->xferred_len = 0;
ep->user_buf = 0;
}
-void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask)
-{
+void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoint* ep, uint32_t and_mask,
+ uint32_t or_mask) {
uint32_t value = 0;
- if ( and_mask )
- {
+ if (and_mask) {
value = *ep->buffer_control & and_mask;
}
- if ( or_mask )
- {
+ if (or_mask) {
value |= or_mask;
- if ( or_mask & USB_BUF_CTRL_AVAIL )
- {
- if ( *ep->buffer_control & USB_BUF_CTRL_AVAIL )
- {
- panic("ep %d %s was already available", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
+ if (or_mask & USB_BUF_CTRL_AVAIL) {
+ if (*ep->buffer_control & USB_BUF_CTRL_AVAIL) {
+ panic("ep %02X was already available", ep->ep_addr);
}
*ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL;
- // 12 cycle delay.. (should be good for 48*12Mhz = 576Mhz)
+ // 4.1.2.5.1 Con-current access: 12 cycles (should be good for 48*12Mhz = 576Mhz) after write to buffer control
// Don't need delay in host mode as host is in charge
-#if !CFG_TUH_ENABLED
- __asm volatile (
- "b 1f\n"
- "1: b 1f\n"
- "1: b 1f\n"
- "1: b 1f\n"
- "1: b 1f\n"
- "1: b 1f\n"
- "1:\n"
- : : : "memory");
-#endif
+ if ( !is_host_mode()) {
+ busy_wait_at_least_cycles(12);
+ }
}
}
@@ -135,10 +113,9 @@ void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoi
}
// prepare buffer, return buffer control
-static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep, uint8_t buf_id)
-{
+static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint* ep, uint8_t buf_id) {
uint16_t const buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize);
- ep->remaining_len = (uint16_t)(ep->remaining_len - buflen);
+ ep->remaining_len = (uint16_t) (ep->remaining_len - buflen);
uint32_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL;
@@ -146,10 +123,9 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep,
buf_ctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
ep->next_pid ^= 1u;
- if ( !ep->rx )
- {
+ if (!ep->rx) {
// Copy data from user buffer to hw buffer
- memcpy(ep->hw_data_buf + buf_id*64, ep->user_buf, buflen);
+ memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen);
ep->user_buf += buflen;
// Mark as full
@@ -159,8 +135,7 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep,
// Is this the last buffer? Only really matters for host mode. Will trigger
// the trans complete irq but also stop it polling. We only really care about
// trans complete for setup packets being sent
- if (ep->remaining_len == 0)
- {
+ if (ep->remaining_len == 0) {
buf_ctrl |= USB_BUF_CTRL_LAST;
}
@@ -170,8 +145,7 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint *ep,
}
// Prepare buffer control register value
-void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint *ep)
-{
+void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint* ep) {
uint32_t ep_ctrl = *ep->endpoint_control;
// always compute and start with buffer 0
@@ -186,8 +160,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint *ep)
bool const force_single = (!is_host && !tu_edpt_dir(ep->ep_addr)) ||
(is_host && tu_edpt_number(ep->ep_addr) != 0);
- if(ep->remaining_len && !force_single)
- {
+ if (ep->remaining_len && !force_single) {
// Use buffer 1 (double buffered) if there is still data
// TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt)
@@ -196,8 +169,7 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint *ep)
// Set endpoint control double buffered bit if needed
ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER;
ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER;
- }else
- {
+ } else {
// Single buffered since 1 is enough
ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER);
ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER;
@@ -212,35 +184,28 @@ void __tusb_irq_path_func(hw_endpoint_start_next_buffer)(struct hw_endpoint *ep)
_hw_endpoint_buffer_control_set_value32(ep, buf_ctrl);
}
-void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len)
-{
+void hw_endpoint_xfer_start(struct hw_endpoint* ep, uint8_t* buffer, uint16_t total_len) {
hw_endpoint_lock_update(ep, 1);
- if ( ep->active )
- {
+ if (ep->active) {
// TODO: Is this acceptable for interrupt packets?
- TU_LOG(1, "WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr),
- ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
-
+ TU_LOG(1, "WARN: starting new transfer on already active ep %02X\r\n", ep->ep_addr);
hw_endpoint_reset_transfer(ep);
}
// Fill in info now that we're kicking off the hw
ep->remaining_len = total_len;
- ep->xferred_len = 0;
- ep->active = true;
- ep->user_buf = buffer;
+ ep->xferred_len = 0;
+ ep->active = true;
+ ep->user_buf = buffer;
- if ( e15_is_bulkin_ep(ep) )
- {
+ if (e15_is_bulkin_ep(ep)) {
usb_hw_set->inte = USB_INTS_DEV_SOF_BITS;
}
- if ( e15_is_critical_frame_period(ep) )
- {
+ if (e15_is_critical_frame_period(ep)) {
ep->pending = 1;
- } else
- {
+ } else {
hw_endpoint_start_next_buffer(ep);
}
@@ -248,35 +213,31 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t to
}
// sync endpoint buffer and return transferred bytes
-static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint *ep, uint8_t buf_id)
-{
+static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint* ep, uint8_t buf_id) {
uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep);
- if (buf_id) buf_ctrl = buf_ctrl >> 16;
+ if (buf_id) buf_ctrl = buf_ctrl >> 16;
uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK;
- if ( !ep->rx )
- {
+ if (!ep->rx) {
// We are continuing a transfer here. If we are TX, we have successfully
// sent some data can increase the length we have sent
assert(!(buf_ctrl & USB_BUF_CTRL_FULL));
- ep->xferred_len = (uint16_t)(ep->xferred_len + xferred_bytes);
- }else
- {
+ ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes);
+ } else {
// If we have received some data, so can increase the length
// we have received AFTER we have copied it to the user buffer at the appropriate offset
assert(buf_ctrl & USB_BUF_CTRL_FULL);
- memcpy(ep->user_buf, ep->hw_data_buf + buf_id*64, xferred_bytes);
- ep->xferred_len = (uint16_t)(ep->xferred_len + xferred_bytes);
+ memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes);
+ ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes);
ep->user_buf += xferred_bytes;
}
// Short packet
- if (xferred_bytes < ep->wMaxPacketSize)
- {
- pico_trace(" Short packet on buffer %d with %u bytes\n", buf_id, xferred_bytes);
+ if (xferred_bytes < ep->wMaxPacketSize) {
+ pico_trace(" Short packet on buffer %d with %u bytes\r\n", buf_id, xferred_bytes);
// Reduce total length as this is last packet
ep->remaining_len = 0;
}
@@ -284,8 +245,7 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint *ep, uin
return xferred_bytes;
}
-static void __tusb_irq_path_func(_hw_endpoint_xfer_sync) (struct hw_endpoint *ep)
-{
+static void __tusb_irq_path_func(_hw_endpoint_xfer_sync)(struct hw_endpoint* ep) {
// Update hw endpoint struct with info from hardware
// after a buff status interrupt
@@ -296,14 +256,11 @@ static void __tusb_irq_path_func(_hw_endpoint_xfer_sync) (struct hw_endpoint *ep
uint16_t buf0_bytes = sync_ep_buffer(ep, 0);
// sync buffer 1 if double buffered
- if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS )
- {
- if (buf0_bytes == ep->wMaxPacketSize)
- {
+ if ((*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS) {
+ if (buf0_bytes == ep->wMaxPacketSize) {
// sync buffer 1 if not short packet
sync_ep_buffer(ep, 1);
- }else
- {
+ } else {
// short packet on buffer 0
// TODO couldn't figure out how to handle this case which happen with net_lwip_webserver example
// At this time (currently trigger per 2 buffer), the buffer1 is probably filled with data from
@@ -335,14 +292,12 @@ static void __tusb_irq_path_func(_hw_endpoint_xfer_sync) (struct hw_endpoint *ep
}
// Returns true if transfer is complete
-bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep)
-{
+bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint* ep) {
hw_endpoint_lock_update(ep, 1);
// Part way through a transfer
- if (!ep->active)
- {
- panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
+ if (!ep->active) {
+ panic("Can't continue xfer on inactive ep %02X", ep->ep_addr);
}
// Update EP struct from hardware state
@@ -350,21 +305,15 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep)
// Now we have synced our state with the hardware. Is there more data to transfer?
// If we are done then notify tinyusb
- if (ep->remaining_len == 0)
- {
- pico_trace("Completed transfer of %d bytes on ep %d %s\n",
- ep->xferred_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
+ if (ep->remaining_len == 0) {
+ pico_trace("Completed transfer of %d bytes on ep %02X\r\n", ep->xferred_len, ep->ep_addr);
// Notify caller we are done so it can notify the tinyusb stack
hw_endpoint_lock_update(ep, -1);
return true;
- }
- else
- {
- if ( e15_is_critical_frame_period(ep) )
- {
+ } else {
+ if (e15_is_critical_frame_period(ep)) {
ep->pending = 1;
- } else
- {
+ } else {
hw_endpoint_start_next_buffer(ep);
}
}
@@ -399,16 +348,14 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep)
volatile uint32_t e15_last_sof = 0;
// check if Errata 15 is needed for this endpoint i.e device bulk-in
-static bool __tusb_irq_path_func(e15_is_bulkin_ep) (struct hw_endpoint *ep)
-{
+static bool __tusb_irq_path_func(e15_is_bulkin_ep)(struct hw_endpoint* ep) {
return (!is_host_mode() && tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN &&
ep->transfer_type == TUSB_XFER_BULK);
}
// check if we need to apply Errata 15 workaround : i.e
// Endpoint is BULK IN and is currently in critical frame period i.e 20% of last usb frame
-static bool __tusb_irq_path_func(e15_is_critical_frame_period) (struct hw_endpoint *ep)
-{
+static bool __tusb_irq_path_func(e15_is_critical_frame_period)(struct hw_endpoint* ep) {
TU_VERIFY(e15_is_bulkin_ep(ep));
/* Avoid the last 200us (uframe 6.5-7) of a frame, up to the EOF2 point.
@@ -419,11 +366,10 @@ static bool __tusb_irq_path_func(e15_is_critical_frame_period) (struct hw_endpoi
if (delta < 800 || delta > 998) {
return false;
}
- TU_LOG(3, "Avoiding sof %u now %lu last %lu\n", (usb_hw->sof_rd + 1) & USB_SOF_RD_BITS, time_us_32(), e15_last_sof);
+ TU_LOG(3, "Avoiding sof %lu now %lu last %lu\r\n", (usb_hw->sof_rd + 1) & USB_SOF_RD_BITS, time_us_32(),
+ e15_last_sof);
return true;
}
-#endif
-
-
+#endif // TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
#endif
diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c
index 78584125f..24edc30e7 100644
--- a/src/portable/renesas/rusb2/dcd_rusb2.c
+++ b/src/portable/renesas/rusb2/dcd_rusb2.c
@@ -27,13 +27,12 @@
#include "tusb_option.h"
+#if CFG_TUD_ENABLED && defined(TUP_USBIP_RUSB2)
+
// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
// We disable SOF for now until needed later on
#define USE_SOF 0
-#if CFG_TUD_ENABLED && (TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) || \
- TU_CHECK_MCU(OPT_MCU_RAXXX))
-
#include "device/dcd.h"
#include "rusb2_type.h"
@@ -41,6 +40,16 @@
#include "rusb2_rx.h"
#elif TU_CHECK_MCU(OPT_MCU_RAXXX)
#include "rusb2_ra.h"
+ #if defined(RENESAS_CORTEX_M23)
+ #define D0FIFO CFIFO
+ #define D0FIFOSEL CFIFOSEL
+ #define D0FIFOSEL_b CFIFOSEL_b
+ #define D1FIFOSEL CFIFOSEL
+ #define D1FIFOSEL_b CFIFOSEL_b
+ #define D0FIFOCTR CFIFOCTR
+ #define D0FIFOCTR_b CFIFOCTR_b
+ #endif
+
#else
#error "Unsupported MCU"
#endif
@@ -49,38 +58,10 @@
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
-/* LINK core registers */
-#if defined(__CCRX__)
- #define RUSB2 ((RUSB2_REG_t __evenaccess*) RUSB2_REG_BASE)
-#else
- #define RUSB2 ((RUSB2_REG_t*) RUSB2_REG_BASE)
-#endif
-
/* Start of definition of packed structs (used by the CCRX toolchain) */
TU_ATTR_PACKED_BEGIN
TU_ATTR_BIT_FIELD_ORDER_BEGIN
-typedef struct TU_ATTR_PACKED {
- union {
- struct {
- uint16_t : 8;
- uint16_t TRCLR: 1;
- uint16_t TRENB: 1;
- uint16_t : 0;
- };
- uint16_t TRE;
- };
- uint16_t TRN;
-} reg_pipetre_t;
-
-typedef union TU_ATTR_PACKED {
- struct {
- volatile uint16_t u8: 8;
- volatile uint16_t : 0;
- };
- volatile uint16_t u16;
-} hw_fifo_t;
-
typedef struct TU_ATTR_PACKED
{
void *buf; /* the start address of a transfer data buffer */
@@ -102,310 +83,410 @@ typedef struct
uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */
} dcd_data_t;
+static dcd_data_t _dcd;
+
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-static dcd_data_t _dcd;
+
+// Transfer conditions specifiable for each pipe:
+// - Pipe 0: Control transfer with 64-byte single buffer
+// - Pipes 1 and 2: Bulk isochronous transfer continuous transfer mode with programmable buffer size up
+// to 2 KB and optional double buffer
+// - Pipes 3 to 5: Bulk transfer continuous transfer mode with programmable buffer size up to 2 KB and
+// optional double buffer
+// - Pipes 6 to 9: Interrupt transfer with 64-byte single buffer
+enum {
+ PIPE_1ST_BULK = 3,
+ PIPE_1ST_INTERRUPT = 6,
+ PIPE_COUNT = 10,
+};
static unsigned find_pipe(unsigned xfer)
{
switch (xfer) {
- case TUSB_XFER_ISOCHRONOUS:
- for (int i = 1; i <= 2; ++i) {
- if (0 == _dcd.pipe[i].ep) return i;
- }
- break;
- case TUSB_XFER_BULK:
- for (int i = 3; i <= 5; ++i) {
- if (0 == _dcd.pipe[i].ep) return i;
- }
- for (int i = 1; i <= 1; ++i) {
- if (0 == _dcd.pipe[i].ep) return i;
- }
- break;
- case TUSB_XFER_INTERRUPT:
- for (int i = 6; i <= 9; ++i) {
- if (0 == _dcd.pipe[i].ep) return i;
- }
- break;
- default:
- /* No support for control transfer */
- break;
+ case TUSB_XFER_ISOCHRONOUS:
+ for (int i = 1; i < PIPE_1ST_BULK; ++i) {
+ if (0 == _dcd.pipe[i].ep) return i;
+ }
+ break;
+
+ case TUSB_XFER_BULK:
+ for (int i = PIPE_1ST_BULK; i < PIPE_1ST_INTERRUPT; ++i) {
+ if (0 == _dcd.pipe[i].ep) return i;
+ }
+ for (int i = 1; i < PIPE_1ST_BULK; ++i) {
+ if (0 == _dcd.pipe[i].ep) return i;
+ }
+ break;
+
+ case TUSB_XFER_INTERRUPT:
+ for (int i = PIPE_1ST_INTERRUPT; i < PIPE_COUNT; ++i) {
+ if (0 == _dcd.pipe[i].ep) return i;
+ }
+ break;
+
+ default:
+ /* No support for control transfer */
+ break;
}
return 0;
}
-static volatile uint16_t* get_pipectr(unsigned num)
+static volatile uint16_t* get_pipectr(rusb2_reg_t *rusb, unsigned num)
{
if (num) {
- return (volatile uint16_t*)&(RUSB2->PIPE_CTR[num - 1]);
+ return (volatile uint16_t*)&(rusb->PIPE_CTR[num - 1]);
} else {
- return (volatile uint16_t*)&(RUSB2->DCPCTR);
+ return (volatile uint16_t*)&(rusb->DCPCTR);
}
}
-static volatile reg_pipetre_t* get_pipetre(unsigned num)
+static volatile reg_pipetre_t* get_pipetre(rusb2_reg_t *rusb, unsigned num)
{
volatile reg_pipetre_t* tre = NULL;
if ((1 <= num) && (num <= 5)) {
- tre = (volatile reg_pipetre_t*)&(RUSB2->PIPE_TR[num - 1].E);
+ tre = (volatile reg_pipetre_t*)&(rusb->PIPE_TR[num - 1].E);
}
return tre;
}
static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr)
{
- (void)rhport;
+ rusb2_reg_t *rusb = RUSB2_REG(rhport);
const unsigned epn = tu_edpt_number(ep_addr);
+
if (epn) {
const unsigned dir = tu_edpt_dir(ep_addr);
const unsigned num = _dcd.ep[dir][epn];
- return get_pipectr(num);
+ return get_pipectr(rusb, num);
} else {
- return get_pipectr(0);
+ return get_pipectr(rusb, 0);
}
}
-static unsigned edpt0_max_packet_size(void)
+static uint16_t edpt0_max_packet_size(rusb2_reg_t* rusb)
{
- return RUSB2->DCPMAXP_b.MXPS;
+ return rusb->DCPMAXP_b.MXPS;
}
-static unsigned edpt_max_packet_size(unsigned num)
+static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num)
{
- RUSB2->PIPESEL = num;
- return RUSB2->PIPEMAXP;
+ rusb->PIPESEL = num;
+ return rusb->PIPEMAXP;
}
-static inline void pipe_wait_for_ready(unsigned num)
+static inline void pipe_wait_for_ready(rusb2_reg_t * rusb, unsigned num)
{
- while (RUSB2->D0FIFOSEL_b.CURPIPE != num) ;
- while (!RUSB2->D0FIFOCTR_b.FRDY) ;
+ while ( rusb->D0FIFOSEL_b.CURPIPE != num ) {}
+ while ( !rusb->D0FIFOCTR_b.FRDY ) {}
}
-static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
+//--------------------------------------------------------------------+
+// Pipe FIFO
+//--------------------------------------------------------------------+
+
+// Write data buffer --> hw fifo
+static void pipe_write_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len)
{
- volatile hw_fifo_t *reg = (volatile hw_fifo_t*) fifo;
- uintptr_t addr = (uintptr_t)buf;
+ (void) rusb;
+
+ volatile uint16_t *ff16;
+ volatile uint8_t *ff8;
+
+ // Highspeed FIFO is 32-bit
+ if ( rusb2_is_highspeed_reg(rusb) ) {
+ // TODO 32-bit access for better performance
+ ff16 = (volatile uint16_t*) ((uintptr_t) fifo+2);
+ ff8 = (volatile uint8_t *) ((uintptr_t) fifo+3);
+ }else {
+ ff16 = (volatile uint16_t*) fifo;
+ ff8 = ((volatile uint8_t*) fifo);
+ }
+
+ uint8_t const* buf8 = (uint8_t const*) buf;
+
while (len >= 2) {
- reg->u16 = *(const uint16_t *)addr;
- addr += 2;
+ *ff16 = tu_unaligned_read16(buf8);
+ buf8 += 2;
len -= 2;
}
- if (len) {
- reg->u8 = *(const uint8_t *)addr;
- ++addr;
+
+ if (len > 0) {
+ *ff8 = *buf8;
+ ++buf8;
}
}
-static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
+// Read data buffer <-- hw fifo
+static void pipe_read_packet(rusb2_reg_t * rusb, void *buf, volatile void *fifo, unsigned len)
{
- uint8_t *p = (uint8_t*)buf;
+ (void) rusb;
+
+ // TODO 16/32-bit access for better performance
+
+ uint8_t *p = (uint8_t*)buf;
volatile uint8_t *reg = (volatile uint8_t*)fifo; /* byte access is always at base register address */
while (len--) *p++ = *reg;
}
-static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir)
-{
- static const struct {
- void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
- void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n);
- void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len);
- } ops[] = {
- /* OUT */ {tu_fifo_get_write_info,tu_fifo_advance_write_pointer,pipe_read_packet},
- /* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet},
- };
+// Write data sw fifo --> hw fifo
+static void pipe_write_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) {
tu_fifo_buffer_info_t info;
- ops[dir].tu_fifo_get_info(f, &info);
- unsigned total_len = len;
- len = TU_MIN(total_len, info.len_lin);
- ops[dir].pipe_read_write(info.ptr_lin, fifo, len);
- unsigned rem = total_len - len;
+ tu_fifo_get_read_info(f, &info);
+
+ uint16_t count = tu_min16(total_len, info.len_lin);
+ pipe_write_packet(rusb, info.ptr_lin, fifo, count);
+
+ uint16_t rem = total_len - count;
if (rem) {
- len = TU_MIN(rem, info.len_wrap);
- ops[dir].pipe_read_write(info.ptr_wrap, fifo, len);
- rem -= len;
+ rem = tu_min16(rem, info.len_wrap);
+ pipe_write_packet(rusb, info.ptr_wrap, fifo, rem);
+ count += rem;
}
- ops[dir].tu_fifo_advance(f, total_len - rem);
+
+ tu_fifo_advance_read_pointer(f, count);
+}
+
+// Read data sw fifo <-- hw fifo
+static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void *fifo, uint16_t total_len) {
+ tu_fifo_buffer_info_t info;
+ tu_fifo_get_write_info(f, &info);
+
+ uint16_t count = tu_min16(total_len, info.len_lin);
+ pipe_read_packet(rusb, info.ptr_lin, fifo, count);
+
+ uint16_t rem = total_len - count;
+ if (rem) {
+ rem = tu_min16(rem, info.len_wrap);
+ pipe_read_packet(rusb, info.ptr_wrap, fifo, rem);
+ count += rem;
+ }
+
+ tu_fifo_advance_write_pointer(f, count);
+}
+
+
+static bool wait_pipe_fifo_empty(rusb2_reg_t* rusb, uint8_t num) {
+ TU_ASSERT(num);
+ while( (rusb->PIPE_CTR[num-1] & RUSB2_PIPE_CTR_INBUFM_Msk) > 0 ) {}
+ return true;
}
-static bool pipe0_xfer_in(void)
+
+//--------------------------------------------------------------------+
+// Pipe Transfer
+//--------------------------------------------------------------------+
+
+static bool pipe0_xfer_in(rusb2_reg_t* rusb)
{
pipe_state_t *pipe = &_dcd.pipe[0];
const unsigned rem = pipe->remaining;
+
if (!rem) {
pipe->buf = NULL;
return true;
}
- const unsigned mps = edpt0_max_packet_size();
- const unsigned len = TU_MIN(mps, rem);
+
+ const uint16_t mps = edpt0_max_packet_size(rusb);
+ const uint16_t len = tu_min16(mps, rem);
void *buf = pipe->buf;
+
if (len) {
if (pipe->ff) {
- pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&RUSB2->CFIFO, len, TUSB_DIR_IN);
+ pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len);
} else {
- pipe_write_packet(buf, (volatile void*)&RUSB2->CFIFO, len);
+ pipe_write_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len);
pipe->buf = (uint8_t*)buf + len;
}
}
+
if (len < mps) {
- RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
+ rusb->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
}
+
pipe->remaining = rem - len;
return false;
}
-static bool pipe0_xfer_out(void)
+static bool pipe0_xfer_out(rusb2_reg_t* rusb)
{
pipe_state_t *pipe = &_dcd.pipe[0];
const unsigned rem = pipe->remaining;
- const unsigned mps = edpt0_max_packet_size();
- const unsigned vld = RUSB2->CFIFOCTR_b.DTLN;
- const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
+ const uint16_t mps = edpt0_max_packet_size(rusb);
+ const uint16_t vld = rusb->CFIFOCTR_b.DTLN;
+ const uint16_t len = tu_min16(tu_min16(rem, mps), vld);
void *buf = pipe->buf;
+
if (len) {
if (pipe->ff) {
- pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&RUSB2->CFIFO, len, TUSB_DIR_OUT);
+ pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->CFIFO, len);
} else {
- pipe_read_packet(buf, (volatile void*)&RUSB2->CFIFO, len);
+ pipe_read_packet(rusb, buf, (volatile void*)&rusb->CFIFO, len);
pipe->buf = (uint8_t*)buf + len;
}
}
+
if (len < mps) {
- RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
+ rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
}
+
pipe->remaining = rem - len;
if ((len < mps) || (rem == len)) {
pipe->buf = NULL;
return true;
}
+
return false;
}
-static bool pipe_xfer_in(unsigned num)
+static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num)
{
pipe_state_t *pipe = &_dcd.pipe[num];
const unsigned rem = pipe->remaining;
if (!rem) {
+ wait_pipe_fifo_empty(rusb, num);
pipe->buf = NULL;
return true;
}
- RUSB2->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
- const unsigned mps = edpt_max_packet_size(num);
- pipe_wait_for_ready(num);
- const unsigned len = TU_MIN(rem, mps);
+ rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
+ const uint16_t mps = edpt_max_packet_size(rusb, num);
+ pipe_wait_for_ready(rusb, num);
+ const uint16_t len = tu_min16(rem, mps);
void *buf = pipe->buf;
+
if (len) {
if (pipe->ff) {
- pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&RUSB2->D0FIFO, len, TUSB_DIR_IN);
+ pipe_write_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len);
} else {
- pipe_write_packet(buf, (volatile void*)&RUSB2->D0FIFO, len);
+ pipe_write_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len);
pipe->buf = (uint8_t*)buf + len;
}
}
+
if (len < mps) {
- RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
+ rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
}
- RUSB2->D0FIFOSEL = 0;
- while (RUSB2->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
+
+ rusb->D0FIFOSEL = 0;
+ while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
+
pipe->remaining = rem - len;
+
return false;
}
-static bool pipe_xfer_out(unsigned num)
+static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num)
{
pipe_state_t *pipe = &_dcd.pipe[num];
- const unsigned rem = pipe->remaining;
+ const uint16_t rem = pipe->remaining;
+
+ rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT;
+ const uint16_t mps = edpt_max_packet_size(rusb, num);
+ pipe_wait_for_ready(rusb, num);
- RUSB2->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT;
- const unsigned mps = edpt_max_packet_size(num);
- pipe_wait_for_ready(num);
- const unsigned vld = RUSB2->D0FIFOCTR_b.DTLN;
- const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
+ const uint16_t vld = rusb->D0FIFOCTR_b.DTLN;
+ const uint16_t len = tu_min16(tu_min16(rem, mps), vld);
void *buf = pipe->buf;
+
if (len) {
if (pipe->ff) {
- pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&RUSB2->D0FIFO, len, TUSB_DIR_OUT);
+ pipe_read_packet_ff(rusb, (tu_fifo_t*)buf, (volatile void*)&rusb->D0FIFO, len);
} else {
- pipe_read_packet(buf, (volatile void*)&RUSB2->D0FIFO, len);
+ pipe_read_packet(rusb, buf, (volatile void*)&rusb->D0FIFO, len);
pipe->buf = (uint8_t*)buf + len;
}
}
+
if (len < mps) {
- RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
+ rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
}
- RUSB2->D0FIFOSEL = 0;
- while (RUSB2->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
+
+ rusb->D0FIFOSEL = 0;
+ while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
+
pipe->remaining = rem - len;
if ((len < mps) || (rem == len)) {
pipe->buf = NULL;
return NULL != buf;
}
+
return false;
}
static void process_setup_packet(uint8_t rhport)
{
- uint16_t setup_packet[4];
- if (0 == (RUSB2->INTSTS0 & RUSB2_INTSTS0_VALID_Msk)) return;
- RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
- setup_packet[0] = tu_le16toh(RUSB2->USBREQ);
- setup_packet[1] = RUSB2->USBVAL;
- setup_packet[2] = RUSB2->USBINDX;
- setup_packet[3] = RUSB2->USBLENG;
- RUSB2->INTSTS0 = ~((uint16_t)RUSB2_INTSTS0_VALID_Msk);
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ if (0 == (rusb->INTSTS0 & RUSB2_INTSTS0_VALID_Msk)) return;
+
+ rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
+ uint16_t setup_packet[4] = {
+ tu_htole16(rusb->USBREQ),
+ tu_htole16(rusb->USBVAL),
+ tu_htole16(rusb->USBINDX),
+ tu_htole16(rusb->USBLENG)
+ };
+
+ rusb->INTSTS0 = ~((uint16_t) RUSB2_INTSTS0_VALID_Msk);
dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet[0], true);
}
static void process_status_completion(uint8_t rhport)
{
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
uint8_t ep_addr;
/* Check the data stage direction */
- if (RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {
+ if (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) {
/* IN transfer. */
ep_addr = tu_edpt_addr(0, TUSB_DIR_IN);
} else {
/* OUT transfer. */
ep_addr = tu_edpt_addr(0, TUSB_DIR_OUT);
}
+
dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true);
}
-static bool process_pipe0_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
+static bool process_pipe0_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
{
/* configure fifo direction and access unit settings */
- if (ep_addr) { /* IN, 2 bytes */
- RUSB2->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
- (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
- while (!(RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) ;
- } else { /* OUT, a byte */
- RUSB2->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT;
- while (RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ;
+ if ( ep_addr ) {
+ /* IN, 2 bytes */
+ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
+ (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
+ while ( !(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ) {}
+ } else {
+ /* OUT, a byte */
+ rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT;
+ while ( rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE ) {}
}
pipe_state_t *pipe = &_dcd.pipe[0];
pipe->ff = buffer_type;
pipe->length = total_bytes;
pipe->remaining = total_bytes;
- if (total_bytes) {
- pipe->buf = buffer;
- if (ep_addr) { /* IN */
- TU_ASSERT(RUSB2->DCPCTR_b.BSTS && (RUSB2->USBREQ & 0x80));
- pipe0_xfer_in();
+
+ if ( total_bytes ) {
+ pipe->buf = buffer;
+ if ( ep_addr ) {
+ /* IN */
+ TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80));
+ pipe0_xfer_in(rusb);
}
- RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
+ rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
} else {
/* ZLP */
- pipe->buf = NULL;
- RUSB2->DCPCTR = RUSB2_DCPCTR_CCPL_Msk | RUSB2_PIPE_CTR_PID_BUF;
+ pipe->buf = NULL;
+ rusb->DCPCTR = RUSB2_DCPCTR_CCPL_Msk | RUSB2_PIPE_CTR_PID_BUF;
}
+
return true;
}
-static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
+static bool process_pipe_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
{
const unsigned epn = tu_edpt_number(ep_addr);
const unsigned dir = tu_edpt_dir(ep_addr);
@@ -418,49 +499,55 @@ static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, ui
pipe->buf = buffer;
pipe->length = total_bytes;
pipe->remaining = total_bytes;
- if (dir) { /* IN */
+
+ if (dir) {
+ /* IN */
if (total_bytes) {
- pipe_xfer_in(num);
- } else { /* ZLP */
- RUSB2->D0FIFOSEL = num;
- pipe_wait_for_ready(num);
- RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
- RUSB2->D0FIFOSEL = 0;
- while (RUSB2->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
+ pipe_xfer_in(rusb, num);
+ } else {
+ /* ZLP */
+ rusb->D0FIFOSEL = num;
+ pipe_wait_for_ready(rusb, num);
+ rusb->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
+ rusb->D0FIFOSEL = 0;
+ /* if CURPIPE bits changes, check written value */
+ while (rusb->D0FIFOSEL_b.CURPIPE) {}
}
} else {
-#if defined(__CCRX__)
- __evenaccess volatile reg_pipetre_t *pt = get_pipetre(num);
-#else
- volatile reg_pipetre_t *pt = get_pipetre(num);
-#endif
+ // OUT
+ volatile reg_pipetre_t *pt = get_pipetre(rusb, num);
+
if (pt) {
- const unsigned mps = edpt_max_packet_size(num);
- volatile uint16_t *ctr = get_pipectr(num);
+ const uint16_t mps = edpt_max_packet_size(rusb, num);
+ volatile uint16_t *ctr = get_pipectr(rusb, num);
+
if (*ctr & 0x3) *ctr = RUSB2_PIPE_CTR_PID_NAK;
+
pt->TRE = TU_BIT(8);
pt->TRN = (total_bytes + mps - 1) / mps;
pt->TRENB = 1;
*ctr = RUSB2_PIPE_CTR_PID_BUF;
}
}
- // TU_LOG1("X %x %d %d\r\n", ep_addr, total_bytes, buffer_type);
+
+ // TU_LOG2("X %x %d %d\r\n", ep_addr, total_bytes, buffer_type);
return true;
}
-static bool process_edpt_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
+static bool process_edpt_xfer(rusb2_reg_t* rusb, int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
{
const unsigned epn = tu_edpt_number(ep_addr);
if (0 == epn) {
- return process_pipe0_xfer(buffer_type, ep_addr, buffer, total_bytes);
+ return process_pipe0_xfer(rusb, buffer_type, ep_addr, buffer, total_bytes);
} else {
- return process_pipe_xfer(buffer_type, ep_addr, buffer, total_bytes);
+ return process_pipe_xfer(rusb, buffer_type, ep_addr, buffer, total_bytes);
}
}
static void process_pipe0_bemp(uint8_t rhport)
{
- bool completed = pipe0_xfer_in();
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ bool completed = pipe0_xfer_in(rusb);
if (completed) {
pipe_state_t *pipe = &_dcd.pipe[0];
dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN),
@@ -470,17 +557,20 @@ static void process_pipe0_bemp(uint8_t rhport)
static void process_pipe_brdy(uint8_t rhport, unsigned num)
{
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
pipe_state_t *pipe = &_dcd.pipe[num];
const unsigned dir = tu_edpt_dir(pipe->ep);
bool completed;
- if (dir) { /* IN */
- completed = pipe_xfer_in(num);
+ if (dir) {
+ /* IN */
+ completed = pipe_xfer_in(rusb, num);
} else {
+ // OUT
if (num) {
- completed = pipe_xfer_out(num);
+ completed = pipe_xfer_out(rusb, num);
} else {
- completed = pipe0_xfer_out();
+ completed = pipe0_xfer_out(rusb);
}
}
if (completed) {
@@ -493,39 +583,68 @@ static void process_pipe_brdy(uint8_t rhport, unsigned num)
static void process_bus_reset(uint8_t rhport)
{
- RUSB2->BEMPENB = 1;
- RUSB2->BRDYENB = 1;
- RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
- RUSB2->D0FIFOSEL = 0;
- while (RUSB2->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
- RUSB2->D1FIFOSEL = 0;
- while (RUSB2->D1FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
- volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t) (&RUSB2->PIPE_CTR[0]));
- volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t) (&RUSB2->PIPE_TR[0].E));
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+
+ rusb->BEMPENB = 1;
+ rusb->BRDYENB = 1;
+ rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
+
+ rusb->D0FIFOSEL = 0;
+ while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
+
+ rusb->D1FIFOSEL = 0;
+ while (rusb->D1FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
+
+ volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t) (&rusb->PIPE_CTR[0]));
+ volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t) (&rusb->PIPE_TR[0].E));
+
for (int i = 1; i <= 5; ++i) {
- RUSB2->PIPESEL = i;
- RUSB2->PIPECFG = 0;
+ rusb->PIPESEL = i;
+ rusb->PIPECFG = 0;
*ctr = RUSB2_PIPE_CTR_ACLRM_Msk;
*ctr = 0;
++ctr;
*tre = TU_BIT(8);
tre += 2;
}
+
for (int i = 6; i <= 9; ++i) {
- RUSB2->PIPESEL = i;
- RUSB2->PIPECFG = 0;
+ rusb->PIPESEL = i;
+ rusb->PIPECFG = 0;
*ctr = RUSB2_PIPE_CTR_ACLRM_Msk;
*ctr = 0;
++ctr;
}
tu_varclr(&_dcd);
- dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true);
+
+ TU_LOG3("Bus reset, RHST = %u\r\n", rusb->DVSTCTR0_b.RHST);
+ tusb_speed_t speed;
+ switch(rusb->DVSTCTR0 & RUSB2_DVSTCTR0_RHST_Msk) {
+ case RUSB2_DVSTCTR0_RHST_LS:
+ speed = TUSB_SPEED_LOW;
+ break;
+
+ case RUSB2_DVSTCTR0_RHST_FS:
+ speed = TUSB_SPEED_FULL;
+ break;
+
+ case RUSB2_DVSTCTR0_RHST_HS:
+ speed = TUSB_SPEED_HIGH;
+ break;
+
+ default:
+ TU_ASSERT(false, );
+ }
+
+ dcd_event_bus_reset(rhport, speed, true);
}
static void process_set_address(uint8_t rhport)
{
- const uint32_t addr = RUSB2->USBADDR_b.USBADDR;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ const uint16_t addr = rusb->USBADDR_b.USBADDR;
if (!addr) return;
+
const tusb_control_request_t setup_packet = {
#if defined(__CCRX__)
.bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */
@@ -536,8 +655,9 @@ static void process_set_address(uint8_t rhport)
.wValue = addr,
.wIndex = 0,
.wLength = 0,
- };
- dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true);
+ };
+
+ dcd_event_setup_received(rhport, (const uint8_t *) &setup_packet, true);
}
/*------------------------------------------------------------------*/
@@ -570,73 +690,97 @@ static void enable_interrupt(uint32_t pswi)
void dcd_init(uint8_t rhport)
{
- (void)rhport;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ rusb2_module_start(rhport, true);
-#if 0 // previously present in the rx driver before generalization
- uint32_t pswi = disable_interrupt();
- SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1;
- MSTP(USB0) = 0;
- SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY;
- enable_interrupt(pswi);
-#endif
+#ifdef RUSB2_SUPPORT_HIGHSPEED
+ if ( rusb2_is_highspeed_rhport(rhport) ) {
+ rusb->SYSCFG_b.HSE = 1;
+
+ // leave CLKSEL as default (0x11) 24Mhz
+
+ // Power and reset UTMI Phy
+ uint16_t physet = (rusb->PHYSET | RUSB2_PHYSET_PLLRESET_Msk) & ~RUSB2_PHYSET_DIRPD_Msk;
+ rusb->PHYSET = physet;
+ R_BSP_SoftwareDelay((uint32_t) 1, BSP_DELAY_UNITS_MILLISECONDS);
+ rusb->PHYSET_b.PLLRESET = 0;
- RUSB2->SYSCFG_b.SCKE = 1;
- while (!RUSB2->SYSCFG_b.SCKE) ;
- RUSB2->SYSCFG_b.DRPD = 0;
- RUSB2->SYSCFG_b.DCFM = 0;
- RUSB2->SYSCFG_b.USBE = 1;
+ // set UTMI to operating mode and wait for PLL lock confirmation
+ rusb->LPSTS_b.SUSPENDM = 1;
+ while (!rusb->PLLSTA_b.PLLLOCK) {}
- // MCU specific PHY init
- rusb2_phy_init();
+ rusb->SYSCFG_b.DRPD = 0;
+ rusb->SYSCFG_b.USBE = 1;
+
+ // Set CPU bus wait time (fine tunne later)
+ // rusb2->BUSWAIT |= 0x0F00U;
+
+ rusb->PHYSET_b.REPSEL = 1;
+ } else
+#endif
+ {
+ rusb->SYSCFG_b.SCKE = 1;
+ while (!rusb->SYSCFG_b.SCKE) {}
+ rusb->SYSCFG_b.DRPD = 0;
+ rusb->SYSCFG_b.DCFM = 0;
+ rusb->SYSCFG_b.USBE = 1;
- RUSB2->PHYSLEW = 0x5;
- RUSB2->DPUSR0R_FS_b.FIXPHY0 = 0u; /* USB_BASE Transceiver Output fixed */
+ // MCU specific PHY init
+ rusb2_phy_init();
+
+ rusb->PHYSLEW = 0x5;
+ rusb->DPUSR0R_FS_b.FIXPHY0 = 0u; /* USB_BASE Transceiver Output fixed */
+ }
/* Setup default control pipe */
- RUSB2->DCPMAXP_b.MXPS = 64;
- RUSB2->INTENB0 = RUSB2_INTSTS0_VBINT_Msk | RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_BEMP_Msk |
- RUSB2_INTSTS0_DVST_Msk | RUSB2_INTSTS0_CTRT_Msk | (USE_SOF ? RUSB2_INTSTS0_SOFR_Msk : 0) |
- RUSB2_INTSTS0_RESM_Msk;
- RUSB2->BEMPENB = 1;
- RUSB2->BRDYENB = 1;
+ rusb->DCPMAXP_b.MXPS = 64;
+
+ rusb->INTSTS0 = 0;
+ rusb->INTENB0 = RUSB2_INTSTS0_VBINT_Msk | RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_BEMP_Msk |
+ RUSB2_INTSTS0_DVST_Msk | RUSB2_INTSTS0_CTRT_Msk | (USE_SOF ? RUSB2_INTSTS0_SOFR_Msk : 0) |
+ RUSB2_INTSTS0_RESM_Msk;
+ rusb->BEMPENB = 1;
+ rusb->BRDYENB = 1;
- if (RUSB2->INTSTS0_b.VBSTS) {
+ // If VBUS (detect) pin is not used, application need to call tud_connect() manually after tud_init()
+ if (rusb->INTSTS0_b.VBSTS) {
dcd_connect(rhport);
}
}
-void dcd_int_enable(uint8_t rhport)
-{
+void dcd_int_enable(uint8_t rhport) {
rusb2_int_enable(rhport);
}
-void dcd_int_disable(uint8_t rhport)
-{
+void dcd_int_disable(uint8_t rhport) {
rusb2_int_disable(rhport);
}
-void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
-{
- (void)rhport;
- (void)dev_addr;
+void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
+ (void) rhport;
+ (void) dev_addr;
}
void dcd_remote_wakeup(uint8_t rhport)
{
- (void)rhport;
- RUSB2->DVSTCTR0_b.WKUP = 1;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ rusb->DVSTCTR0_b.WKUP = 1;
}
void dcd_connect(uint8_t rhport)
{
- (void)rhport;
- RUSB2->SYSCFG_b.DPRPU = 1;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+
+ if ( rusb2_is_highspeed_rhport(rhport)) {
+ rusb->SYSCFG_b.CNEN = 1;
+ }
+ rusb->SYSCFG_b.DPRPU = 1;
}
void dcd_disconnect(uint8_t rhport)
{
- (void)rhport;
- RUSB2->SYSCFG_b.DPRPU = 0;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ rusb->SYSCFG_b.DPRPU = 0;
}
void dcd_sof_enable(uint8_t rhport, bool en)
@@ -654,30 +798,43 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
{
(void)rhport;
+ rusb2_reg_t * rusb = RUSB2_REG(rhport);
const unsigned ep_addr = ep_desc->bEndpointAddress;
const unsigned epn = tu_edpt_number(ep_addr);
const unsigned dir = tu_edpt_dir(ep_addr);
const unsigned xfer = ep_desc->bmAttributes.xfer;
const unsigned mps = tu_edpt_packet_size(ep_desc);
- if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) {
- /* USBa supports up to 256 bytes */
- return false;
+
+ if (xfer == TUSB_XFER_ISOCHRONOUS) {
+ // Fullspeed ISO is limit to 256 bytes
+ if ( !rusb2_is_highspeed_rhport(rhport) && mps > 256) {
+ return false;
+ }
}
const unsigned num = find_pipe(xfer);
- if (!num) return false;
+ TU_ASSERT(num);
+
_dcd.pipe[num].ep = ep_addr;
_dcd.ep[dir][epn] = num;
/* setup pipe */
dcd_int_disable(rhport);
- RUSB2->PIPESEL = num;
- RUSB2->PIPEMAXP = mps;
- volatile uint16_t *ctr = get_pipectr(num);
+
+ if ( rusb2_is_highspeed_rhport(rhport) ) {
+ // FIXME shouldn't be after pipe selection and config, also the BUFNMB should be changed
+ // depending on the allocation scheme
+ rusb->PIPEBUF = 0x7C08;
+ }
+
+ rusb->PIPESEL = num;
+ rusb->PIPEMAXP = mps;
+ volatile uint16_t *ctr = get_pipectr(rusb, num);
*ctr = RUSB2_PIPE_CTR_ACLRM_Msk | RUSB2_PIPE_CTR_SQCLR_Msk;
*ctr = 0;
unsigned cfg = (dir << 4) | epn;
+
if (xfer == TUSB_XFER_BULK) {
cfg |= (RUSB2_PIPECFG_TYPE_BULK | RUSB2_PIPECFG_SHTNAK_Msk | RUSB2_PIPECFG_DBLB_Msk);
} else if (xfer == TUSB_XFER_INTERRUPT) {
@@ -685,13 +842,16 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
} else {
cfg |= (RUSB2_PIPECFG_TYPE_ISO | RUSB2_PIPECFG_DBLB_Msk);
}
- RUSB2->PIPECFG = cfg;
- RUSB2->BRDYSTS = 0x1FFu ^ TU_BIT(num);
- RUSB2->BRDYENB |= TU_BIT(num);
+
+ rusb->PIPECFG = cfg;
+ rusb->BRDYSTS = 0x1FFu ^ TU_BIT(num);
+ rusb->BRDYENB |= TU_BIT(num);
+
if (dir || (xfer != TUSB_XFER_BULK)) {
*ctr = RUSB2_PIPE_CTR_PID_BUF;
}
- // TU_LOG1("O %d %x %x\r\n", RUSB2->PIPESEL, RUSB2->PIPECFG, RUSB2->PIPEMAXP);
+
+ // TU_LOG1("O %d %x %x\r\n", rusb->PIPESEL, rusb->PIPECFG, rusb->PIPEMAXP);
dcd_int_enable(rhport);
return true;
@@ -711,26 +871,28 @@ void dcd_edpt_close_all(uint8_t rhport)
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
{
- (void)rhport;
+ rusb2_reg_t * rusb = RUSB2_REG(rhport);
const unsigned epn = tu_edpt_number(ep_addr);
const unsigned dir = tu_edpt_dir(ep_addr);
const unsigned num = _dcd.ep[dir][epn];
- RUSB2->BRDYENB &= ~TU_BIT(num);
- volatile uint16_t *ctr = get_pipectr(num);
+ rusb->BRDYENB &= ~TU_BIT(num);
+ volatile uint16_t *ctr = get_pipectr(rusb, num);
*ctr = 0;
- RUSB2->PIPESEL = num;
- RUSB2->PIPECFG = 0;
+ rusb->PIPESEL = num;
+ rusb->PIPECFG = 0;
_dcd.pipe[num].ep = 0;
_dcd.ep[dir][epn] = 0;
}
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
{
- bool r;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+
dcd_int_disable(rhport);
- r = process_edpt_xfer(0, ep_addr, buffer, total_bytes);
+ bool r = process_edpt_xfer(rusb, 0, ep_addr, buffer, total_bytes);
dcd_int_enable(rhport);
+
return r;
}
@@ -738,10 +900,12 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_
{
// USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
TU_ASSERT(ff->item_size == 1);
- bool r;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+
dcd_int_disable(rhport);
- r = process_edpt_xfer(1, ep_addr, ff, total_bytes);
+ bool r = process_edpt_xfer(rusb, 1, ep_addr, ff, total_bytes);
dcd_int_enable(rhport);
+
return r;
}
@@ -758,8 +922,10 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
+ rusb2_reg_t * rusb = RUSB2_REG(rhport);
volatile uint16_t *ctr = ep_addr_to_pipectr(rhport, ep_addr);
if (!ctr) return;
+
dcd_int_disable(rhport);
*ctr = RUSB2_PIPE_CTR_SQCLR_Msk;
@@ -767,8 +933,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
*ctr = RUSB2_PIPE_CTR_PID_BUF;
} else {
const unsigned num = _dcd.ep[0][tu_edpt_number(ep_addr)];
- RUSB2->PIPESEL = num;
- if (RUSB2->PIPECFG_b.TYPE != 1) {
+ rusb->PIPESEL = num;
+ if (rusb->PIPECFG_b.TYPE != 1) {
*ctr = RUSB2_PIPE_CTR_PID_BUF;
}
}
@@ -780,73 +946,94 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
//--------------------------------------------------------------------+
void dcd_int_handler(uint8_t rhport)
{
- (void)rhport;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+
+ uint16_t is0 = rusb->INTSTS0;
- unsigned is0 = RUSB2->INTSTS0;
/* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */
- RUSB2->INTSTS0 = ~((RUSB2_INTSTS0_CTRT_Msk | RUSB2_INTSTS0_DVST_Msk | RUSB2_INTSTS0_SOFR_Msk |
- RUSB2_INTSTS0_RESM_Msk | RUSB2_INTSTS0_VBINT_Msk) & is0) | RUSB2_INTSTS0_VALID_Msk;
- if (is0 & RUSB2_INTSTS0_VBINT_Msk) {
- if (RUSB2->INTSTS0_b.VBSTS) {
+ rusb->INTSTS0 = ~((RUSB2_INTSTS0_CTRT_Msk | RUSB2_INTSTS0_DVST_Msk | RUSB2_INTSTS0_SOFR_Msk |
+ RUSB2_INTSTS0_RESM_Msk | RUSB2_INTSTS0_VBINT_Msk) & is0) | RUSB2_INTSTS0_VALID_Msk;
+
+ // VBUS changes
+ if ( is0 & RUSB2_INTSTS0_VBINT_Msk ) {
+ if ( rusb->INTSTS0_b.VBSTS ) {
dcd_connect(rhport);
} else {
dcd_disconnect(rhport);
}
}
- if (is0 & RUSB2_INTSTS0_RESM_Msk) {
+
+ // Resumed
+ if ( is0 & RUSB2_INTSTS0_RESM_Msk ) {
dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
-#if (0==USE_SOF)
- RUSB2->INTENB0_b.SOFE = 0;
+#if (0 == USE_SOF)
+ rusb->INTENB0_b.SOFE = 0;
#endif
}
- if ((is0 & RUSB2_INTSTS0_SOFR_Msk) && RUSB2->INTENB0_b.SOFE) {
+
+ // SOF received
+ if ( (is0 & RUSB2_INTSTS0_SOFR_Msk) && rusb->INTENB0_b.SOFE ) {
// USBD will exit suspended mode when SOF event is received
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
#if (0 == USE_SOF)
- RUSB2->INTENB0_b.SOFE = 0;
+ rusb->INTENB0_b.SOFE = 0;
#endif
}
- if (is0 & RUSB2_INTSTS0_DVST_Msk) {
+
+ // Device state changes
+ if ( is0 & RUSB2_INTSTS0_DVST_Msk ) {
switch (is0 & RUSB2_INTSTS0_DVSQ_Msk) {
- case RUSB2_INTSTS0_DVSQ_STATE_DEF:
- process_bus_reset(rhport);
- break;
- case RUSB2_INTSTS0_DVSQ_STATE_ADDR:
- process_set_address(rhport);
- break;
- case RUSB2_INTSTS0_DVSQ_STATE_SUSP0:
- case RUSB2_INTSTS0_DVSQ_STATE_SUSP1:
- case RUSB2_INTSTS0_DVSQ_STATE_SUSP2:
- case RUSB2_INTSTS0_DVSQ_STATE_SUSP3:
- dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
-#if (0==USE_SOF)
- RUSB2->INTENB0_b.SOFE = 1;
+ case RUSB2_INTSTS0_DVSQ_STATE_DEF:
+ process_bus_reset(rhport);
+ break;
+
+ case RUSB2_INTSTS0_DVSQ_STATE_ADDR:
+ process_set_address(rhport);
+ break;
+
+ case RUSB2_INTSTS0_DVSQ_STATE_SUSP0:
+ case RUSB2_INTSTS0_DVSQ_STATE_SUSP1:
+ case RUSB2_INTSTS0_DVSQ_STATE_SUSP2:
+ case RUSB2_INTSTS0_DVSQ_STATE_SUSP3:
+ dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
+#if (0 == USE_SOF)
+ rusb->INTENB0_b.SOFE = 1;
#endif
- default:
- break;
+
+ default: break;
}
}
- if (is0 & RUSB2_INTSTS0_CTRT_Msk) {
- if (is0 & RUSB2_INTSTS0_CTSQ_CTRL_RDATA) {
+
+// if ( is0 & RUSB2_INTSTS0_NRDY_Msk ) {
+// rusb->NRDYSTS = 0;
+// }
+
+ // Control transfer stage changes
+ if ( is0 & RUSB2_INTSTS0_CTRT_Msk ) {
+ if ( is0 & RUSB2_INTSTS0_CTSQ_CTRL_RDATA ) {
/* A setup packet has been received. */
process_setup_packet(rhport);
- } else if (0 == (is0 & RUSB2_INTSTS0_CTSQ_Msk)) {
+ } else if ( 0 == (is0 & RUSB2_INTSTS0_CTSQ_Msk) ) {
/* A ZLP has been sent/received. */
process_status_completion(rhport);
}
}
- if (is0 & RUSB2_INTSTS0_BEMP_Msk) {
- const unsigned s = RUSB2->BEMPSTS;
- RUSB2->BEMPSTS = 0;
- if (s & 1) {
+
+ // Buffer empty
+ if ( is0 & RUSB2_INTSTS0_BEMP_Msk ) {
+ const uint16_t s = rusb->BEMPSTS;
+ rusb->BEMPSTS = 0;
+ if ( s & 1 ) {
process_pipe0_bemp(rhport);
}
}
- if (is0 & RUSB2_INTSTS0_BRDY_Msk) {
- const unsigned m = RUSB2->BRDYENB;
- unsigned s = RUSB2->BRDYSTS & m;
+
+ // Buffer ready
+ if ( is0 & RUSB2_INTSTS0_BRDY_Msk ) {
+ const unsigned m = rusb->BRDYENB;
+ unsigned s = rusb->BRDYSTS & m;
/* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
- RUSB2->BRDYSTS = ~s;
+ rusb->BRDYSTS = ~s;
while (s) {
#if defined(__CCRX__)
static const int Mod37BitPosition[] = {
diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c
index e4743223e..bf95be707 100644
--- a/src/portable/renesas/rusb2/hcd_rusb2.c
+++ b/src/portable/renesas/rusb2/hcd_rusb2.c
@@ -27,8 +27,7 @@
#include "tusb_option.h"
-#if CFG_TUH_ENABLED && (TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) || \
- TU_CHECK_MCU(OPT_MCU_RAXXX))
+#if CFG_TUH_ENABLED && defined(TUP_USBIP_RUSB2)
#include "host/hcd.h"
#include "rusb2_type.h"
@@ -41,33 +40,15 @@
#error "Unsupported MCU"
#endif
+#define TU_RUSB2_HCD_DBG 2
+
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
-/* LINK core registers */
-#if defined(__CCRX__)
- #define RUSB2 ((RUSB2_REG_t __evenaccess*) RUSB2_REG_BASE)
-#else
- #define RUSB2 ((RUSB2_REG_t*) RUSB2_REG_BASE)
-#endif
-
TU_ATTR_PACKED_BEGIN
TU_ATTR_BIT_FIELD_ORDER_BEGIN
-typedef struct TU_ATTR_PACKED {
- union {
- struct {
- uint16_t : 8;
- uint16_t TRCLR: 1;
- uint16_t TRENB: 1;
- uint16_t : 0;
- };
- uint16_t TRE;
- };
- uint16_t TRN;
-} reg_pipetre_t;
-
typedef union TU_ATTR_PACKED {
struct {
volatile uint16_t u8: 8;
@@ -104,83 +85,102 @@ typedef struct
//--------------------------------------------------------------------+
static hcd_data_t _hcd;
-static unsigned find_pipe(unsigned xfer)
-{
- switch (xfer) {
- case TUSB_XFER_ISOCHRONOUS:
- for (int i = 1; i <= 2; ++i) {
- if (0 == _hcd.pipe[i].ep) return i;
- }
- break;
- case TUSB_XFER_BULK:
- for (int i = 3; i <= 5; ++i) {
- if (0 == _hcd.pipe[i].ep) return i;
- }
- for (int i = 1; i <= 1; ++i) {
- if (0 == _hcd.pipe[i].ep) return i;
- }
- break;
- case TUSB_XFER_INTERRUPT:
- for (int i = 6; i <= 9; ++i) {
- if (0 == _hcd.pipe[i].ep) return i;
- }
- break;
- default:
- /* No support for control transfer */
- break;
+// TODO merged with DCD
+// Transfer conditions specifiable for each pipe:
+// - Pipe 0: Control transfer with 64-byte single buffer
+// - Pipes 1 and 2: Bulk isochronous transfer continuous transfer mode with programmable buffer size up
+// to 2 KB and optional double buffer
+// - Pipes 3 to 5: Bulk transfer continuous transfer mode with programmable buffer size up to 2 KB and
+// optional double buffer
+// - Pipes 6 to 9: Interrupt transfer with 64-byte single buffer
+enum {
+ PIPE_1ST_BULK = 3,
+ PIPE_1ST_INTERRUPT = 6,
+ PIPE_COUNT = 10,
+};
+
+static unsigned find_pipe(unsigned xfer) {
+ switch ( xfer ) {
+ case TUSB_XFER_ISOCHRONOUS:
+ for (int i = 1; i < PIPE_1ST_BULK; ++i) {
+ if ( 0 == _hcd.pipe[i].ep ) return i;
+ }
+ break;
+
+ case TUSB_XFER_BULK:
+ for (int i = PIPE_1ST_BULK; i < PIPE_1ST_INTERRUPT; ++i) {
+ if ( 0 == _hcd.pipe[i].ep ) return i;
+ }
+ for (int i = 1; i < PIPE_1ST_BULK; ++i) {
+ if ( 0 == _hcd.pipe[i].ep ) return i;
+ }
+ break;
+
+ case TUSB_XFER_INTERRUPT:
+ for (int i = PIPE_1ST_INTERRUPT; i < PIPE_COUNT; ++i) {
+ if ( 0 == _hcd.pipe[i].ep ) return i;
+ }
+ break;
+
+ default:
+ /* No support for control transfer */
+ break;
}
return 0;
}
-static volatile uint16_t* get_pipectr(unsigned num)
+static volatile uint16_t* get_pipectr(rusb2_reg_t *rusb, unsigned num)
{
if (num) {
- return (volatile uint16_t*)&(RUSB2->PIPE_CTR[num - 1]);
+ return (volatile uint16_t*)&(rusb->PIPE_CTR[num - 1]);
} else {
- return (volatile uint16_t*)&(RUSB2->DCPCTR);
+ return (volatile uint16_t*)&(rusb->DCPCTR);
}
}
-static volatile reg_pipetre_t* get_pipetre(unsigned num)
+static volatile reg_pipetre_t* get_pipetre(rusb2_reg_t *rusb, unsigned num)
{
volatile reg_pipetre_t* tre = NULL;
if ((1 <= num) && (num <= 5)) {
- tre = (volatile reg_pipetre_t*)&(RUSB2->PIPE_TR[num - 1].E);
+ tre = (volatile reg_pipetre_t*)&(rusb->PIPE_TR[num - 1].E);
}
return tre;
}
-static volatile uint16_t* addr_to_pipectr(uint8_t dev_addr, unsigned ep_addr)
+static volatile uint16_t* addr_to_pipectr(uint8_t rhport, uint8_t dev_addr, unsigned ep_addr)
{
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
const unsigned epn = tu_edpt_number(ep_addr);
+
if (epn) {
const unsigned dir_in = tu_edpt_dir(ep_addr);
const unsigned num = _hcd.ep[dev_addr][dir_in][epn - 1];
- return get_pipectr(num);
+ return get_pipectr(rusb, num);
} else {
- return get_pipectr(0);
+ return get_pipectr(rusb, 0);
}
}
-static unsigned edpt0_max_packet_size(void)
+static uint16_t edpt0_max_packet_size(rusb2_reg_t* rusb)
{
- return RUSB2->DCPMAXP_b.MXPS;
+ return rusb->DCPMAXP_b.MXPS;
}
-static unsigned edpt_max_packet_size(unsigned num)
+static uint16_t edpt_max_packet_size(rusb2_reg_t *rusb, unsigned num)
{
- RUSB2->PIPESEL = num;
- return RUSB2->PIPEMAXP_b.MXPS;
+ rusb->PIPESEL = num;
+ return rusb->PIPEMAXP_b.MXPS;
}
-static inline void pipe_wait_for_ready(unsigned num)
+static inline void pipe_wait_for_ready(rusb2_reg_t* rusb, unsigned num)
{
- while (RUSB2->D0FIFOSEL_b.CURPIPE != num) ;
- while (!RUSB2->D0FIFOCTR_b.FRDY) ;
+ while (rusb->D0FIFOSEL_b.CURPIPE != num) ;
+ while (!rusb->D0FIFOCTR_b.FRDY) {}
}
static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
{
+ // NOTE: unlike DCD, Highspeed 32-bit FIFO does not need to adjust the fifo address
volatile hw_fifo_t *reg = (volatile hw_fifo_t*)fifo;
uintptr_t addr = (uintptr_t)buf;
while (len >= 2) {
@@ -201,33 +201,33 @@ static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
while (len--) *p++ = *reg;
}
-static bool pipe0_xfer_in(void)
+static bool pipe0_xfer_in(rusb2_reg_t* rusb)
{
pipe_state_t *pipe = &_hcd.pipe[0];
const unsigned rem = pipe->remaining;
- const unsigned mps = edpt0_max_packet_size();
- const unsigned vld = RUSB2->CFIFOCTR_b.DTLN;
+ const unsigned mps = edpt0_max_packet_size(rusb);
+ const unsigned vld = rusb->CFIFOCTR_b.DTLN;
const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
void *buf = pipe->buf;
if (len) {
- RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
- pipe_read_packet(buf, (volatile void*)&RUSB2->CFIFO, len);
+ rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
+ pipe_read_packet(buf, (volatile void*)&rusb->CFIFO, len);
pipe->buf = (uint8_t*)buf + len;
}
if (len < mps) {
- RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
+ rusb->CFIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
}
pipe->remaining = rem - len;
if ((len < mps) || (rem == len)) {
pipe->buf = NULL;
return true;
}
- RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
+ rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
return false;
}
-static bool pipe0_xfer_out(void)
+static bool pipe0_xfer_out(rusb2_reg_t* rusb)
{
pipe_state_t *pipe = &_hcd.pipe[0];
const unsigned rem = pipe->remaining;
@@ -235,40 +235,40 @@ static bool pipe0_xfer_out(void)
pipe->buf = NULL;
return true;
}
- const unsigned mps = edpt0_max_packet_size();
+ const unsigned mps = edpt0_max_packet_size(rusb);
const unsigned len = TU_MIN(mps, rem);
void *buf = pipe->buf;
if (len) {
- pipe_write_packet(buf, (volatile void*)&RUSB2->CFIFO, len);
+ pipe_write_packet(buf, (volatile void*)&rusb->CFIFO, len);
pipe->buf = (uint8_t*)buf + len;
}
if (len < mps) {
- RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
+ rusb->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
}
pipe->remaining = rem - len;
return false;
}
-static bool pipe_xfer_in(unsigned num)
+static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num)
{
pipe_state_t *pipe = &_hcd.pipe[num];
const unsigned rem = pipe->remaining;
- RUSB2->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT;
- const unsigned mps = edpt_max_packet_size(num);
- pipe_wait_for_ready(num);
- const unsigned vld = RUSB2->D0FIFOCTR_b.DTLN;
+ rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_8BIT;
+ const unsigned mps = edpt_max_packet_size(rusb, num);
+ pipe_wait_for_ready(rusb, num);
+ const unsigned vld = rusb->D0FIFOCTR_b.DTLN;
const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
void *buf = pipe->buf;
if (len) {
- pipe_read_packet(buf, (volatile void*)&RUSB2->D0FIFO, len);
+ pipe_read_packet(buf, (volatile void*)&rusb->D0FIFO, len);
pipe->buf = (uint8_t*)buf + len;
}
if (len < mps) {
- RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BCLR_Msk;
+ rusb->D0FIFOCTR = RUSB2_D0FIFOCTR_BCLR_Msk;
}
- RUSB2->D0FIFOSEL = 0;
- while (RUSB2->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
+ rusb->D0FIFOSEL = 0;
+ while (rusb->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
pipe->remaining = rem - len;
if ((len < mps) || (rem == len)) {
pipe->buf = NULL;
@@ -277,7 +277,7 @@ static bool pipe_xfer_in(unsigned num)
return false;
}
-static bool pipe_xfer_out(unsigned num)
+static bool pipe_xfer_out(rusb2_reg_t* rusb, unsigned num)
{
pipe_state_t *pipe = &_hcd.pipe[num];
const unsigned rem = pipe->remaining;
@@ -287,36 +287,39 @@ static bool pipe_xfer_out(unsigned num)
return true;
}
- RUSB2->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
- const unsigned mps = edpt_max_packet_size(num);
- pipe_wait_for_ready(num);
+ rusb->D0FIFOSEL = num | RUSB2_FIFOSEL_MBW_16BIT | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
+ const unsigned mps = edpt_max_packet_size(rusb, num);
+ pipe_wait_for_ready(rusb, num);
const unsigned len = TU_MIN(rem, mps);
void *buf = pipe->buf;
if (len) {
- pipe_write_packet(buf, (volatile void*)&RUSB2->D0FIFO, len);
+ pipe_write_packet(buf, (volatile void*)&rusb->D0FIFO, len);
pipe->buf = (uint8_t*)buf + len;
}
- if (len < mps)
- RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
- RUSB2->D0FIFOSEL = 0;
- while (RUSB2->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
+ if (len < mps) {
+ rusb->D0FIFOCTR = RUSB2_D0FIFOCTR_BVAL_Msk;
+ }
+ rusb->D0FIFOSEL = 0;
+ while (rusb->D0FIFOSEL_b.CURPIPE) ; /* if CURPIPE bits changes, check written value */
pipe->remaining = rem - len;
return false;
}
-static bool process_pipe0_xfer(uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen)
+static bool process_pipe0_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen)
{
(void)dev_addr;
+
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
const unsigned dir_in = tu_edpt_dir(ep_addr);
/* configure fifo direction and access unit settings */
if (dir_in) { /* IN, a byte */
- RUSB2->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT;
- while (RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ;
+ rusb->CFIFOSEL = RUSB2_FIFOSEL_MBW_8BIT;
+ while (rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE) ;
} else { /* OUT, 2 bytes */
- RUSB2->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
+ rusb->CFIFOSEL = RUSB2_CFIFOSEL_ISEL_WRITE | RUSB2_FIFOSEL_MBW_16BIT |
(TU_BYTE_ORDER == TU_BIG_ENDIAN ? RUSB2_FIFOSEL_BIGEND : 0);
- while (!(RUSB2->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) ;
+ while (!(rusb->CFIFOSEL & RUSB2_CFIFOSEL_ISEL_WRITE)) ;
}
pipe_state_t *pipe = &_hcd.pipe[0];
@@ -326,26 +329,28 @@ static bool process_pipe0_xfer(uint8_t dev_addr, uint8_t ep_addr, void* buffer,
if (buflen) {
pipe->buf = buffer;
if (!dir_in) { /* OUT */
- TU_ASSERT(RUSB2->DCPCTR_b.BSTS && (RUSB2->USBREQ & 0x80));
- pipe0_xfer_out();
+ TU_ASSERT(rusb->DCPCTR_b.BSTS && (rusb->USBREQ & 0x80));
+ pipe0_xfer_out(rusb);
}
} else { /* ZLP */
pipe->buf = NULL;
if (!dir_in) { /* OUT */
- RUSB2->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
+ rusb->CFIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
}
- if (dir_in == RUSB2->DCPCFG_b.DIR) {
- TU_ASSERT(RUSB2_PIPE_CTR_PID_NAK == RUSB2->DCPCTR_b.PID);
- RUSB2->DCPCTR_b.SQSET = 1;
- RUSB2->DCPCFG_b.DIR = dir_in ^ 1;
+ if (dir_in == rusb->DCPCFG_b.DIR) {
+ TU_ASSERT(RUSB2_PIPE_CTR_PID_NAK == rusb->DCPCTR_b.PID);
+ rusb->DCPCTR_b.SQSET = 1;
+ rusb->DCPCFG_b.DIR = dir_in ^ 1;
}
}
- RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
+ rusb->DCPCTR = RUSB2_PIPE_CTR_PID_BUF;
return true;
}
-static bool process_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, void *buffer, uint16_t buflen)
+static bool process_pipe_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void *buffer, uint16_t buflen)
{
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+
const unsigned epn = tu_edpt_number(ep_addr);
const unsigned dir_in = tu_edpt_dir(ep_addr);
const unsigned num = _hcd.ep[dev_addr - 1][dir_in][epn - 1];
@@ -358,19 +363,19 @@ static bool process_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, void *buffer, u
pipe->remaining = buflen;
if (!dir_in) { /* OUT */
if (buflen) {
- pipe_xfer_out(num);
+ pipe_xfer_out(rusb, num);
} else { /* ZLP */
- RUSB2->D0FIFOSEL = num;
- pipe_wait_for_ready(num);
- RUSB2->D0FIFOCTR = RUSB2_CFIFOCTR_BVAL_Msk;
- RUSB2->D0FIFOSEL = 0;
- while (RUSB2->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
+ rusb->D0FIFOSEL = num;
+ pipe_wait_for_ready(rusb, num);
+ rusb->D0FIFOCTR = RUSB2_D0FIFOCTR_BVAL_Msk;
+ rusb->D0FIFOSEL = 0;
+ while (rusb->D0FIFOSEL_b.CURPIPE) {} /* if CURPIPE bits changes, check written value */
}
} else {
- volatile uint16_t *ctr = get_pipectr(num);
- volatile reg_pipetre_t *pt = get_pipetre(num);
+ volatile uint16_t *ctr = get_pipectr(rusb, num);
+ volatile reg_pipetre_t *pt = get_pipetre(rusb, num);
if (pt) {
- const unsigned mps = edpt_max_packet_size(num);
+ const unsigned mps = edpt_max_packet_size(rusb, num);
if (*ctr & 0x3) *ctr = RUSB2_PIPE_CTR_PID_NAK;
pt->TRE = TU_BIT(8);
pt->TRN = (buflen + mps - 1) / mps;
@@ -381,20 +386,20 @@ static bool process_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, void *buffer, u
return true;
}
-static bool process_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen)
+static bool process_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, void* buffer, uint16_t buflen)
{
const unsigned epn = tu_edpt_number(ep_addr);
if (0 == epn) {
- return process_pipe0_xfer(dev_addr, ep_addr, buffer, buflen);
+ return process_pipe0_xfer(rhport, dev_addr, ep_addr, buffer, buflen);
} else {
- return process_pipe_xfer(dev_addr, ep_addr, buffer, buflen);
+ return process_pipe_xfer(rhport, dev_addr, ep_addr, buffer, buflen);
}
}
static void process_pipe0_bemp(uint8_t rhport)
{
- (void)rhport;
- bool completed = pipe0_xfer_out();
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ bool completed = pipe0_xfer_out(rusb);
if (completed) {
pipe_state_t *pipe = &_hcd.pipe[0];
hcd_event_xfer_complete(pipe->dev,
@@ -406,13 +411,14 @@ static void process_pipe0_bemp(uint8_t rhport)
static void process_pipe_nrdy(uint8_t rhport, unsigned num)
{
- (void)rhport;
- unsigned result;
- uint16_t volatile *ctr = get_pipectr(num);
- // TU_LOG1("NRDY %d %x\n", num, *ctr);
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ xfer_result_t result;
+ uint16_t volatile *ctr = get_pipectr(rusb, num);
+ TU_LOG(TU_RUSB2_HCD_DBG, "NRDY %d %x\r\n", num, *ctr);
switch (*ctr & RUSB2_PIPE_CTR_PID_Msk) {
default: return;
case RUSB2_PIPE_CTR_PID_STALL: result = XFER_RESULT_STALLED; break;
+ case RUSB2_PIPE_CTR_PID_STALL2: result = XFER_RESULT_STALLED; break;
case RUSB2_PIPE_CTR_PID_NAK: result = XFER_RESULT_FAILED; break;
}
pipe_state_t *pipe = &_hcd.pipe[num];
@@ -423,25 +429,25 @@ static void process_pipe_nrdy(uint8_t rhport, unsigned num)
static void process_pipe_brdy(uint8_t rhport, unsigned num)
{
- (void)rhport;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
pipe_state_t *pipe = &_hcd.pipe[num];
const unsigned dir_in = tu_edpt_dir(pipe->ep);
bool completed;
if (dir_in) { /* IN */
if (num) {
- completed = pipe_xfer_in(num);
+ completed = pipe_xfer_in(rusb, num);
} else {
- completed = pipe0_xfer_in();
+ completed = pipe0_xfer_in(rusb);
}
} else {
- completed = pipe_xfer_out(num);
+ completed = pipe_xfer_out(rusb, num);
}
if (completed) {
hcd_event_xfer_complete(pipe->dev, pipe->ep,
pipe->length - pipe->remaining,
XFER_RESULT_SUCCESS, true);
- // TU_LOG1("C %d %d\r\n", num, pipe->length - pipe->remaining);
+ TU_LOG(TU_RUSB2_HCD_DBG, "C %d %d\r\n", num, pipe->length - pipe->remaining);
}
}
@@ -475,126 +481,146 @@ static void enable_interrupt(uint32_t pswi)
bool hcd_init(uint8_t rhport)
{
- (void)rhport;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ rusb2_module_start(rhport, true);
-#if 0 // previously present in the rx driver before generalization
- uint32_t pswi = disable_interrupt();
- SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1;
- MSTP(USB0) = 0;
- SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY;
- enable_interrupt(pswi);
+#ifdef RUSB2_SUPPORT_HIGHSPEED
+ if (rusb2_is_highspeed_rhport(rhport) ) {
+ rusb->SYSCFG_b.HSE = 1;
+ rusb->PHYSET_b.HSEB = 0;
+ rusb->PHYSET_b.DIRPD = 0;
+ R_BSP_SoftwareDelay((uint32_t) 1, BSP_DELAY_UNITS_MILLISECONDS);
+ rusb->PHYSET_b.PLLRESET = 0;
+ rusb->LPSTS_b.SUSPENDM = 1;
+ while ( !rusb->PLLSTA_b.PLLLOCK );
+ rusb->SYSCFG_b.DRPD = 1;
+ rusb->SYSCFG_b.DCFM = 1;
+ rusb->SYSCFG_b.DPRPU = 0;
+ rusb->SYSCFG_b.CNEN = 1;
+ rusb->BUSWAIT |= 0x0F00U;
+ rusb->SOFCFG_b.INTL = 1;
+ rusb->DVSTCTR0_b.VBUSEN = 1;
+ rusb->CFIFOSEL_b.MBW = 1;
+ rusb->D0FIFOSEL_b.MBW = 1;
+ rusb->D1FIFOSEL_b.MBW = 1;
+ rusb->INTSTS0 = 0;
+ for ( volatile int i = 0; i < 30000; ++i );
+ rusb->SYSCFG_b.USBE = 1;
+ } else
#endif
+ {
+ rusb->SYSCFG_b.SCKE = 1;
+ while ( !rusb->SYSCFG_b.SCKE ) {}
+ rusb->SYSCFG_b.DCFM = 1; // Host function
+ rusb->SYSCFG_b.DPRPU = 0; // Disable D+ pull up
+ rusb->SYSCFG_b.DRPD = 1; // Enable D+/D- pull down
- RUSB2->SYSCFG_b.SCKE = 1;
- while (!RUSB2->SYSCFG_b.SCKE) ;
- RUSB2->SYSCFG_b.DPRPU = 0;
- RUSB2->SYSCFG_b.DRPD = 0;
- RUSB2->SYSCFG_b.DCFM = 1;
-
- RUSB2->DVSTCTR0_b.VBUSEN = 1;
-
- RUSB2->SYSCFG_b.DRPD = 1;
- for (volatile int i = 0; i < 30000; ++i) ;
- RUSB2->SYSCFG_b.USBE = 1;
+ rusb->DVSTCTR0_b.VBUSEN = 1;
+ for ( volatile int i = 0; i < 30000; ++i ) {} // FIXME do we need to wait here? how long ?
+ //R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
+ rusb->SYSCFG_b.USBE = 1;
- // MCU specific PHY init
- rusb2_phy_init();
+ // MCU specific PHY init
+ rusb2_phy_init();
- RUSB2->PHYSLEW = 0x5;
- RUSB2->DPUSR0R_FS_b.FIXPHY0 = 0u; /* Transceiver Output fixed */
+ rusb->PHYSLEW = 0x5;
+ rusb->DPUSR0R_FS_b.FIXPHY0 = 0u; /* Transceiver Output fixed */
+ }
/* Setup default control pipe */
- RUSB2->DCPCFG = RUSB2_PIPECFG_SHTNAK_Msk;
- RUSB2->DCPMAXP = 64;
- RUSB2->INTENB0 = RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_NRDY_Msk | RUSB2_INTSTS0_BEMP_Msk;
- RUSB2->INTENB1 = RUSB2_INTSTS1_SACK_Msk | RUSB2_INTSTS1_SIGN_Msk | RUSB2_INTSTS1_ATTCH_Msk | RUSB2_INTSTS1_DTCH_Msk;
- RUSB2->BEMPENB = 1;
- RUSB2->NRDYENB = 1;
- RUSB2->BRDYENB = 1;
+ rusb->DCPCFG = RUSB2_PIPECFG_SHTNAK_Msk;
+ rusb->DCPMAXP = 64;
+ rusb->INTENB0 = RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_NRDY_Msk | RUSB2_INTSTS0_BEMP_Msk;
+ rusb->INTENB1 = RUSB2_INTSTS1_SACK_Msk | RUSB2_INTSTS1_SIGN_Msk | RUSB2_INTSTS1_ATTCH_Msk | RUSB2_INTSTS1_DTCH_Msk;
+ rusb->BEMPENB = 1;
+ rusb->NRDYENB = 1;
+ rusb->BRDYENB = 1;
return true;
}
-void hcd_int_enable(uint8_t rhport)
-{
+void hcd_int_enable(uint8_t rhport) {
rusb2_int_enable(rhport);
}
-void hcd_int_disable(uint8_t rhport)
-{
+void hcd_int_disable(uint8_t rhport) {
rusb2_int_disable(rhport);
}
uint32_t hcd_frame_number(uint8_t rhport)
{
- (void)rhport;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+
/* The device must be reset at least once after connection
* in order to start the frame counter. */
if (_hcd.need_reset) hcd_port_reset(rhport);
- return RUSB2->FRMNUM_b.FRNM;
+ return rusb->FRMNUM_b.FRNM;
}
/*--------------------------------------------------------------------+
* Port API
*--------------------------------------------------------------------+*/
-bool hcd_port_connect_status(uint8_t rhport)
-{
- (void)rhport;
- return RUSB2->INTSTS1_b.ATTCH ? true : false;
+bool hcd_port_connect_status(uint8_t rhport) {
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ return rusb->INTSTS1_b.ATTCH ? true : false;
}
-void hcd_port_reset(uint8_t rhport)
-{
- RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
- while (RUSB2->DCPCTR_b.PBUSY) ;
+void hcd_port_reset(uint8_t rhport) {
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
+ while (rusb->DCPCTR_b.PBUSY) {}
+
hcd_int_disable(rhport);
- RUSB2->DVSTCTR0_b.UACT = 0;
- if (RUSB2->DCPCTR_b.SUREQ) {
- RUSB2->DCPCTR_b.SUREQCLR = 1;
+ rusb->DVSTCTR0_b.UACT = 0;
+ if (rusb->DCPCTR_b.SUREQ) {
+ rusb->DCPCTR_b.SUREQCLR = 1;
}
hcd_int_enable(rhport);
+
/* Reset should be asserted 10-20ms. */
- RUSB2->DVSTCTR0_b.USBRST = 1;
- for (volatile int i = 0; i < 2400000; ++i) ;
- RUSB2->DVSTCTR0_b.USBRST = 0;
- RUSB2->DVSTCTR0_b.UACT = 1;
+ rusb->DVSTCTR0_b.USBRST = 1;
+ for (volatile int i = 0; i < 2400000; ++i) {}
+ rusb->DVSTCTR0_b.USBRST = 0;
+
+ rusb->DVSTCTR0_b.UACT = 1;
_hcd.need_reset = false;
}
-void hcd_port_reset_end(uint8_t rhport)
-{
+void hcd_port_reset_end(uint8_t rhport) {
(void) rhport;
}
-tusb_speed_t hcd_port_speed_get(uint8_t rhport)
-{
- (void)rhport;
- switch (RUSB2->DVSTCTR0_b.RHST) {
- default: return TUSB_SPEED_INVALID;
+tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ switch (rusb->DVSTCTR0_b.RHST) {
+ case RUSB2_DVSTCTR0_RHST_HS: return TUSB_SPEED_HIGH;
case RUSB2_DVSTCTR0_RHST_FS: return TUSB_SPEED_FULL;
- case RUSB2_DVSTCTR0_RHST_LS: return TUSB_SPEED_LOW;
+ case RUSB2_DVSTCTR0_RHST_LS: return TUSB_SPEED_LOW;
+ default: return TUSB_SPEED_INVALID;
}
}
-void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
-{
- (void)rhport;
+void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
uint16_t volatile *ctr;
+
TU_ASSERT(dev_addr < 6,); /* USBa can only handle addresses from 0 to 5. */
if (!dev_addr) return;
+
_hcd.ctl_mps[dev_addr] = 0;
uint8_t *ep = &_hcd.ep[dev_addr - 1][0][0];
+
for (int i = 0; i < 2 * 15; ++i, ++ep) {
unsigned num = *ep;
- if (!num || dev_addr != _hcd.pipe[num].dev) continue;
+ if (!num || (dev_addr != _hcd.pipe[num].dev)) continue;
- ctr = (uint16_t volatile*)&RUSB2->PIPE_CTR[num - 1];
+ ctr = (uint16_t volatile*)&rusb->PIPE_CTR[num - 1];
*ctr = 0;
- RUSB2->NRDYENB &= ~TU_BIT(num);
- RUSB2->BRDYENB &= ~TU_BIT(num);
- RUSB2->PIPESEL = num;
- RUSB2->PIPECFG = 0;
- RUSB2->PIPEMAXP = 0;
+ rusb->NRDYENB &= ~TU_BIT(num);
+ rusb->BRDYENB &= ~TU_BIT(num);
+ rusb->PIPESEL = num;
+ rusb->PIPECFG = 0;
+ rusb->PIPEMAXP = 0;
_hcd.pipe[num].ep = 0;
_hcd.pipe[num].dev = 0;
@@ -607,52 +633,54 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
*--------------------------------------------------------------------+*/
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
{
- (void)rhport;
- // TU_LOG1("S %d %x\n", dev_addr, RUSB2->DCPCTR);
-
TU_ASSERT(dev_addr < 6); /* USBa can only handle addresses from 0 to 5. */
- TU_ASSERT(0 == RUSB2->DCPCTR_b.SUREQ);
- RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ TU_LOG(TU_RUSB2_HCD_DBG, "S %d %x\r\n", dev_addr, rusb->DCPCTR);
+
+ TU_ASSERT(0 == rusb->DCPCTR_b.SUREQ);
+
+ rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
_hcd.pipe[0].buf = NULL;
_hcd.pipe[0].length = 8;
_hcd.pipe[0].remaining = 0;
_hcd.pipe[0].dev = dev_addr;
- while (RUSB2->DCPCTR_b.PBUSY) ;
- RUSB2->DCPMAXP = (dev_addr << 12) | _hcd.ctl_mps[dev_addr];
+ while (rusb->DCPCTR_b.PBUSY) ;
+ rusb->DCPMAXP = (dev_addr << 12) | _hcd.ctl_mps[dev_addr];
/* Set direction in advance for DATA stage */
uint8_t const bmRequesttype = setup_packet[0];
- RUSB2->DCPCFG_b.DIR = tu_edpt_dir(bmRequesttype) ? 0: 1;
+ rusb->DCPCFG_b.DIR = tu_edpt_dir(bmRequesttype) ? 0: 1;
uint16_t const* p = (uint16_t const*)(uintptr_t)&setup_packet[0];
- RUSB2->USBREQ = tu_htole16(p[0]);
- RUSB2->USBVAL = p[1];
- RUSB2->USBINDX = p[2];
- RUSB2->USBLENG = p[3];
+ rusb->USBREQ = tu_htole16(p[0]);
+ rusb->USBVAL = p[1];
+ rusb->USBINDX = p[2];
+ rusb->USBLENG = p[3];
- RUSB2->DCPCTR_b.SUREQ = 1;
+ rusb->DCPCTR_b.SUREQ = 1;
return true;
}
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc)
{
- (void)rhport;
TU_ASSERT(dev_addr < 6); /* USBa can only handle addresses from 0 to 5. */
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
const unsigned ep_addr = ep_desc->bEndpointAddress;
const unsigned epn = tu_edpt_number(ep_addr);
const unsigned mps = tu_edpt_packet_size(ep_desc);
+
if (0 == epn) {
- RUSB2->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
+ rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
hcd_devtree_info_t devtree;
hcd_devtree_get_info(dev_addr, &devtree);
- uint16_t volatile *devadd = (uint16_t volatile *)(uintptr_t) &RUSB2->DEVADD[0];
+ uint16_t volatile *devadd = (uint16_t volatile *)(uintptr_t) &rusb->DEVADD[0];
devadd += dev_addr;
- while (RUSB2->DCPCTR_b.PBUSY) ;
- RUSB2->DCPMAXP = (dev_addr << 12) | mps;
+ while (rusb->DCPCTR_b.PBUSY) {}
+ rusb->DCPMAXP = (dev_addr << 12) | mps;
*devadd = (TUSB_SPEED_FULL == devtree.speed) ? RUSB2_DEVADD_USBSPD_FS : RUSB2_DEVADD_USBSPD_LS;
_hcd.ctl_mps[dev_addr] = mps;
return true;
@@ -666,17 +694,20 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
}
const unsigned num = find_pipe(xfer);
if (!num) return false;
+
_hcd.pipe[num].dev = dev_addr;
_hcd.pipe[num].ep = ep_addr;
_hcd.ep[dev_addr - 1][dir_in][epn - 1] = num;
/* setup pipe */
hcd_int_disable(rhport);
- RUSB2->PIPESEL = num;
- RUSB2->PIPEMAXP = (dev_addr << 12) | mps;
- volatile uint16_t *ctr = get_pipectr(num);
+
+ rusb->PIPESEL = num;
+ rusb->PIPEMAXP = (dev_addr << 12) | mps;
+ volatile uint16_t *ctr = get_pipectr(rusb, num);
*ctr = RUSB2_PIPE_CTR_ACLRM_Msk | RUSB2_PIPE_CTR_SQCLR_Msk;
*ctr = 0;
+
unsigned cfg = ((1 ^ dir_in) << 4) | epn;
if (xfer == TUSB_XFER_BULK) {
cfg |= RUSB2_PIPECFG_TYPE_BULK | RUSB2_PIPECFG_SHTNAK_Msk | RUSB2_PIPECFG_DBLB_Msk;
@@ -685,13 +716,16 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
} else {
cfg |= RUSB2_PIPECFG_TYPE_ISO | RUSB2_PIPECFG_DBLB_Msk;
}
- RUSB2->PIPECFG = cfg;
- RUSB2->BRDYSTS = 0x1FFu ^ TU_BIT(num);
- RUSB2->NRDYENB |= TU_BIT(num);
- RUSB2->BRDYENB |= TU_BIT(num);
+
+ rusb->PIPECFG = cfg;
+ rusb->BRDYSTS = 0x1FFu ^ TU_BIT(num);
+ rusb->NRDYENB |= TU_BIT(num);
+ rusb->BRDYENB |= TU_BIT(num);
+
if (!dir_in) {
*ctr = RUSB2_PIPE_CTR_PID_BUF;
}
+
hcd_int_enable(rhport);
return true;
@@ -701,15 +735,22 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b
{
bool r;
hcd_int_disable(rhport);
- // TU_LOG1("X %d %x %u\n", dev_addr, ep_addr, buflen);
- r = process_edpt_xfer(dev_addr, ep_addr, buffer, buflen);
+ TU_LOG(TU_RUSB2_HCD_DBG, "X %d %x %u\r\n", dev_addr, ep_addr, buflen);
+ r = process_edpt_xfer(rhport, dev_addr, ep_addr, buffer, buflen);
hcd_int_enable(rhport);
return r;
}
-bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
-{
- uint16_t volatile *ctr = addr_to_pipectr(dev_addr, ep_addr);
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+ // TODO not implemented yet
+ return false;
+}
+
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ uint16_t volatile *ctr = addr_to_pipectr(rhport, dev_addr, ep_addr);
TU_ASSERT(ctr);
const uint32_t pid = *ctr & 0x3;
@@ -730,59 +771,66 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
//--------------------------------------------------------------------+
// ISR
//--------------------------------------------------------------------+
-void hcd_int_handler(uint8_t rhport)
-{
- (void)rhport;
-#if defined(__CCRX__)
- static const int Mod37BitPosition[] = {
- -1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4,
- 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5,
- 20, 8, 19, 18};
-#endif
+void hcd_int_handler(uint8_t rhport, bool in_isr) {
+ (void) in_isr;
+
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ unsigned is0 = rusb->INTSTS0;
+ unsigned is1 = rusb->INTSTS1;
- unsigned is1 = RUSB2->INTSTS1;
- unsigned is0 = RUSB2->INTSTS0;
/* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */
- RUSB2->INTSTS1 = ~((RUSB2_INTSTS1_SACK_Msk | RUSB2_INTSTS1_SIGN_Msk | RUSB2_INTSTS1_ATTCH_Msk | RUSB2_INTSTS1_DTCH_Msk) & is1);
- RUSB2->INTSTS0 = ~((RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_NRDY_Msk | RUSB2_INTSTS0_BEMP_Msk) & is0);
- // TU_LOG1("IS %04x %04x\n", is0, is1);
- is1 &= RUSB2->INTENB1;
- is0 &= RUSB2->INTENB0;
+ rusb->INTSTS1 = ~((RUSB2_INTSTS1_SACK_Msk | RUSB2_INTSTS1_SIGN_Msk | RUSB2_INTSTS1_ATTCH_Msk | RUSB2_INTSTS1_DTCH_Msk) & is1);
+ rusb->INTSTS0 = ~((RUSB2_INTSTS0_BRDY_Msk | RUSB2_INTSTS0_NRDY_Msk | RUSB2_INTSTS0_BEMP_Msk) & is0);
+
+ TU_LOG3("IS %04x %04x\r\n", is0, is1);
+ is1 &= rusb->INTENB1;
+ is0 &= rusb->INTENB0;
if (is1 & RUSB2_INTSTS1_SACK_Msk) {
/* Set DATA1 in advance for the next transfer. */
- RUSB2->DCPCTR_b.SQSET = 1;
- hcd_event_xfer_complete(RUSB2->DCPMAXP_b.DEVSEL, tu_edpt_addr(0, TUSB_DIR_OUT), 8, XFER_RESULT_SUCCESS, true);
+ rusb->DCPCTR_b.SQSET = 1;
+ hcd_event_xfer_complete(rusb->DCPMAXP_b.DEVSEL, tu_edpt_addr(0, TUSB_DIR_OUT), 8, XFER_RESULT_SUCCESS, true);
}
+
if (is1 & RUSB2_INTSTS1_SIGN_Msk) {
- hcd_event_xfer_complete(RUSB2->DCPMAXP_b.DEVSEL, tu_edpt_addr(0, TUSB_DIR_OUT), 8, XFER_RESULT_FAILED, true);
+ hcd_event_xfer_complete(rusb->DCPMAXP_b.DEVSEL, tu_edpt_addr(0, TUSB_DIR_OUT), 8, XFER_RESULT_FAILED, true);
}
+
if (is1 & RUSB2_INTSTS1_ATTCH_Msk) {
- RUSB2->DVSTCTR0_b.UACT = 1;
+ rusb->DVSTCTR0_b.UACT = 1;
_hcd.need_reset = true;
- RUSB2->INTENB1 = (RUSB2->INTENB1 & ~RUSB2_INTSTS1_ATTCH_Msk) | RUSB2_INTSTS1_DTCH_Msk;
+ rusb->INTENB1 = (rusb->INTENB1 & ~RUSB2_INTSTS1_ATTCH_Msk) | RUSB2_INTSTS1_DTCH_Msk;
hcd_event_device_attach(rhport, true);
}
+
if (is1 & RUSB2_INTSTS1_DTCH_Msk) {
- RUSB2->DVSTCTR0_b.UACT = 0;
- if (RUSB2->DCPCTR_b.SUREQ) {
- RUSB2->DCPCTR_b.SUREQCLR = 1;
+ rusb->DVSTCTR0_b.UACT = 0;
+ if (rusb->DCPCTR_b.SUREQ) {
+ rusb->DCPCTR_b.SUREQCLR = 1;
}
- RUSB2->INTENB1 = (RUSB2->INTENB1 & ~RUSB2_INTSTS1_DTCH_Msk) | RUSB2_INTSTS1_ATTCH_Msk;
+ rusb->INTENB1 = (rusb->INTENB1 & ~RUSB2_INTSTS1_DTCH_Msk) | RUSB2_INTSTS1_ATTCH_Msk;
hcd_event_device_remove(rhport, true);
}
if (is0 & RUSB2_INTSTS0_BEMP_Msk) {
- const unsigned s = RUSB2->BEMPSTS;
- RUSB2->BEMPSTS = 0;
+ const unsigned s = rusb->BEMPSTS;
+ rusb->BEMPSTS = 0;
if (s & 1) {
process_pipe0_bemp(rhport);
}
}
+
+#if defined(__CCRX__)
+ static const int Mod37BitPosition[] = {
+ -1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4,
+ 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5,
+ 20, 8, 19, 18};
+#endif
+
if (is0 & RUSB2_INTSTS0_NRDY_Msk) {
- const unsigned m = RUSB2->NRDYENB;
- unsigned s = RUSB2->NRDYSTS & m;
- RUSB2->NRDYSTS = ~s;
+ const unsigned m = rusb->NRDYENB;
+ unsigned s = rusb->NRDYSTS & m;
+ rusb->NRDYSTS = ~s;
while (s) {
#if defined(__CCRX__)
const unsigned num = Mod37BitPosition[(-s & s) % 37];
@@ -794,10 +842,10 @@ void hcd_int_handler(uint8_t rhport)
}
}
if (is0 & RUSB2_INTSTS0_BRDY_Msk) {
- const unsigned m = RUSB2->BRDYENB;
- unsigned s = RUSB2->BRDYSTS & m;
+ const unsigned m = rusb->BRDYENB;
+ unsigned s = rusb->BRDYSTS & m;
/* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
- RUSB2->BRDYSTS = ~s;
+ rusb->BRDYSTS = ~s;
while (s) {
#if defined(__CCRX__)
const unsigned num = Mod37BitPosition[(-s & s) % 37];
diff --git a/src/portable/renesas/rusb2/rusb2_common.c b/src/portable/renesas/rusb2/rusb2_common.c
new file mode 100644
index 000000000..850060777
--- /dev/null
+++ b/src/portable/renesas/rusb2/rusb2_common.c
@@ -0,0 +1,61 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+#if defined(TUP_USBIP_RUSB2) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED)
+
+#include "rusb2_type.h"
+
+#if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N)
+#include "rusb2_rx.h"
+
+#elif TU_CHECK_MCU(OPT_MCU_RAXXX)
+#include "rusb2_ra.h"
+
+// USBFS_INT_IRQn and USBHS_USB_INT_RESUME_IRQn are generated by FSP
+rusb2_controller_t rusb2_controller[] = {
+ { .reg_base = R_USB_FS0_BASE, .irqnum = USBFS_INT_IRQn },
+ #ifdef RUSB2_SUPPORT_HIGHSPEED
+ { .reg_base = R_USB_HS0_BASE, .irqnum = USBHS_USB_INT_RESUME_IRQn },
+ #endif
+};
+
+// Application API for setting IRQ number. May throw warnings for missing prototypes.
+void tusb_rusb2_set_irqnum(uint8_t rhport, int32_t irqnum) {
+ rusb2_controller[rhport].irqnum = irqnum;
+}
+
+// void osal_task_delay(uint32_t msec) {
+// R_BSP_SoftwareDelay(msec, BSP_DELAY_UNITS_MILLISECONDS);
+// }
+
+#else
+ #error "Unsupported MCU"
+#endif
+
+
+#endif
diff --git a/src/portable/renesas/rusb2/rusb2_ra.h b/src/portable/renesas/rusb2/rusb2_ra.h
index 5785850cc..4774d2e2c 100644
--- a/src/portable/renesas/rusb2/rusb2_ra.h
+++ b/src/portable/renesas/rusb2/rusb2_ra.h
@@ -31,26 +31,75 @@
extern "C" {
#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#pragma GCC diagnostic ignored "-Wundef"
+
+// extra push due to https://github.com/renesas/fsp/pull/278
+#pragma GCC diagnostic push
+#endif
+
/* renesas fsp api */
#include "bsp_api.h"
-#define RUSB2_REG_BASE (0x40090000)
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+// IAR does not have __builtin_ctz
+#if defined(__ICCARM__)
+ #define __builtin_ctz(x) __iar_builtin_CLZ(__iar_builtin_RBIT(x))
+#endif
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+typedef struct {
+ uint32_t reg_base;
+ int32_t irqnum;
+}rusb2_controller_t;
+
+#if defined(BSP_MCU_GROUP_RA6M5) || defined(BSP_MCU_GROUP_RA6M3) || (BSP_CFG_MCU_PART_SERIES == 8)
+ #define RUSB2_SUPPORT_HIGHSPEED
+ #define RUSB2_CONTROLLER_COUNT 2
+
+ #define rusb2_is_highspeed_rhport(_p) (_p == 1)
+ #define rusb2_is_highspeed_reg(_reg) (_reg == RUSB2_REG(1))
+#else
+ #define RUSB2_CONTROLLER_COUNT 1
+
+ #define rusb2_is_highspeed_rhport(_p) (false)
+ #define rusb2_is_highspeed_reg(_reg) (false)
+#endif
+
+extern rusb2_controller_t rusb2_controller[];
+#define RUSB2_REG(_p) ((rusb2_reg_t*) rusb2_controller[_p].reg_base)
+
+//--------------------------------------------------------------------+
+// RUSB2 API
+//--------------------------------------------------------------------+
+
+TU_ATTR_ALWAYS_INLINE static inline void rusb2_module_start(uint8_t rhport, bool start) {
+ uint32_t const mask = 1U << (11+rhport);
+ if (start) {
+ R_MSTP->MSTPCRB &= ~mask;
+ }else {
+ R_MSTP->MSTPCRB |= mask;
+ }
+}
-TU_ATTR_ALWAYS_INLINE static inline void rusb2_int_enable(uint8_t rhport)
-{
- (void) rhport;
- NVIC_EnableIRQ(TU_IRQn);
+TU_ATTR_ALWAYS_INLINE static inline void rusb2_int_enable(uint8_t rhport) {
+ NVIC_EnableIRQ(rusb2_controller[rhport].irqnum);
}
-TU_ATTR_ALWAYS_INLINE static inline void rusb2_int_disable(uint8_t rhport)
-{
- (void) rhport;
- NVIC_DisableIRQ(TU_IRQn);
+TU_ATTR_ALWAYS_INLINE static inline void rusb2_int_disable(uint8_t rhport) {
+ NVIC_DisableIRQ(rusb2_controller[rhport].irqnum);
}
// MCU specific PHY init
-TU_ATTR_ALWAYS_INLINE static inline void rusb2_phy_init(void)
-{
+TU_ATTR_ALWAYS_INLINE static inline void rusb2_phy_init(void) {
}
#ifdef __cplusplus
diff --git a/src/portable/renesas/rusb2/rusb2_rx.h b/src/portable/renesas/rusb2/rusb2_rx.h
index 397c0d56c..7bf4be47e 100644
--- a/src/portable/renesas/rusb2/rusb2_rx.h
+++ b/src/portable/renesas/rusb2/rusb2_rx.h
@@ -37,6 +37,26 @@ extern "C" {
#define RUSB2_REG_BASE (0x000A0000)
+TU_ATTR_ALWAYS_INLINE static inline rusb2_reg_t* RUSB2_REG(uint8_t rhport) {
+ (void) rhport;
+ return (rusb2_reg_t *) RUSB2_REG_BASE;
+}
+
+
+#define rusb2_is_highspeed_rhport(_p) (false)
+#define rusb2_is_highspeed_reg(_reg) (false)
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+
+// Start/Stop MSTP TODO implement later
+TU_ATTR_ALWAYS_INLINE static inline void rusb2_module_start(uint8_t rhport, bool start) {
+ (void) rhport;
+ (void) start;
+}
+
TU_ATTR_ALWAYS_INLINE static inline void rusb2_int_enable(uint8_t rhport)
{
(void) rhport;
diff --git a/src/portable/renesas/rusb2/rusb2_type.h b/src/portable/renesas/rusb2/rusb2_type.h
index 7a2898366..dd88f66a7 100644
--- a/src/portable/renesas/rusb2/rusb2_type.h
+++ b/src/portable/renesas/rusb2/rusb2_type.h
@@ -28,11 +28,19 @@
#define _TUSB_RUSB2_TYPE_H_
#include <stdint.h>
+#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
+// CCRX specific attribute to generate a Code that Accesses Variables in the Declared Size
+#ifdef __CCRX__
+ #define _ccrx_evenaccess __evenaccess
+#else
+ #define _ccrx_evenaccess
+#endif
+
/*--------------------------------------------------------------------*/
/* Register Definitions */
/*--------------------------------------------------------------------*/
@@ -41,40 +49,55 @@ extern "C" {
TU_ATTR_PACKED_BEGIN
TU_ATTR_BIT_FIELD_ORDER_BEGIN
-typedef struct TU_ATTR_PACKED {
+// TODO same as RUSB2_PIPE_TR_t
+typedef struct TU_ATTR_PACKED _ccrx_evenaccess {
+ union {
+ struct {
+ uint16_t : 8;
+ uint16_t TRCLR: 1;
+ uint16_t TRENB: 1;
+ uint16_t : 0;
+ };
+ uint16_t TRE;
+ };
+ uint16_t TRN;
+} reg_pipetre_t;
+
+typedef struct {
union {
volatile uint16_t E; /* (@ 0x00000000) Pipe Transaction Counter Enable Register */
- struct {
- uint16_t : 8;
+ struct TU_ATTR_PACKED {
+ uint16_t : 8;
volatile uint16_t TRCLR : 1; /* [8..8] Transaction Counter Clear */
volatile uint16_t TRENB : 1; /* [9..9] Transaction Counter Enable */
- uint16_t : 6;
+ uint16_t : 6;
} E_b;
};
union {
volatile uint16_t N; /* (@ 0x00000002) Pipe Transaction Counter Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t TRNCNT : 16; /* [15..0] Transaction Counter */
} N_b;
};
} RUSB2_PIPE_TR_t; /* Size = 4 (0x4) */
-/* LINK_REG Structure */
-typedef struct TU_ATTR_PACKED {
+
+/* RUSB2 Registers Structure */
+typedef struct _ccrx_evenaccess {
union {
volatile uint16_t SYSCFG; /* (@ 0x00000000) System Configuration Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t USBE : 1; /* [0..0] USB Operation Enable */
uint16_t : 2;
volatile uint16_t DMRPU : 1; /* [3..3] D- Line Resistor Control */
volatile uint16_t DPRPU : 1; /* [4..4] D+ Line Resistor Control */
volatile uint16_t DRPD : 1; /* [5..5] D+/D- Line Resistor Control */
volatile uint16_t DCFM : 1; /* [6..6] Controller Function Select */
- uint16_t : 1;
+ volatile uint16_t HSE : 1; // [7..7] High-Speed Operation Enable
volatile uint16_t CNEN : 1; /* [8..8] CNEN Single End Receiver Enable */
uint16_t : 1;
volatile uint16_t SCKE : 1; /* [10..10] USB Clock Enable */
@@ -85,21 +108,20 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t BUSWAIT; /* (@ 0x00000002) CPU Bus Wait Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t BWAIT : 4; /* [3..0] CPU Bus Access Wait Specification BWAIT waits (BWAIT+2 access cycles) */
- uint16_t : 12;
+ uint16_t : 12;
} BUSWAIT_b;
};
union {
volatile const uint16_t SYSSTS0; /* (@ 0x00000004) System Configuration Status Register 0 */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t LNST : 2; /* [1..0] USB Data Line Status Monitor */
volatile const uint16_t IDMON : 1; /* [2..2] External ID0 Input Pin Monitor */
uint16_t : 2;
- volatile const uint16_t
- SOFEA : 1; /* [5..5] SOF Active Monitor While Host Controller Function is Selected. */
+ volatile const uint16_t SOFEA : 1; /* [5..5] SOF Active Monitor While Host Controller Function is Selected. */
volatile const uint16_t HTACT : 1; /* [6..6] USB Host Sequencer Status Monitor */
uint16_t : 7;
volatile const uint16_t OVCMON : 2; /* [15..14] External USB0_OVRCURA/ USB0_OVRCURB Input Pin Monitor */
@@ -109,16 +131,16 @@ typedef struct TU_ATTR_PACKED {
union {
volatile const uint16_t PLLSTA; /* (@ 0x00000006) PLL Status Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t PLLLOCK : 1; /* [0..0] PLL Lock Flag */
- uint16_t : 15;
+ uint16_t : 15;
} PLLSTA_b;
};
union {
volatile uint16_t DVSTCTR0; /* (@ 0x00000008) Device State Control Register 0 */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t RHST : 3; /* [2..0] USB Bus Reset Status */
uint16_t : 1;
volatile uint16_t UACT : 1; /* [4..4] USB Bus Enable */
@@ -137,9 +159,9 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t TESTMODE; /* (@ 0x0000000C) USB Test Mode Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t UTST : 4; /* [3..0] Test Mode */
- uint16_t : 12;
+ uint16_t : 12;
} TESTMODE_b;
};
volatile const uint16_t RESERVED1;
@@ -148,7 +170,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint32_t CFIFO; /* (@ 0x00000014) CFIFO Port Register */
- struct {
+ struct TU_ATTR_PACKED {
union {
volatile uint16_t CFIFOL; /* (@ 0x00000014) CFIFO Port Register L */
volatile uint8_t CFIFOLL; /* (@ 0x00000014) CFIFO Port Register LL */
@@ -157,7 +179,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t CFIFOH; /* (@ 0x00000016) CFIFO Port Register H */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint8_t RESERVED3;
volatile uint8_t CFIFOHH; /* (@ 0x00000017) CFIFO Port Register HH */
};
@@ -168,7 +190,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint32_t D0FIFO; /* (@ 0x00000018) D0FIFO Port Register */
- struct {
+ struct TU_ATTR_PACKED {
union {
volatile uint16_t D0FIFOL; /* (@ 0x00000018) D0FIFO Port Register L */
volatile uint8_t D0FIFOLL; /* (@ 0x00000018) D0FIFO Port Register LL */
@@ -177,7 +199,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t D0FIFOH; /* (@ 0x0000001A) D0FIFO Port Register H */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint8_t RESERVED4;
volatile uint8_t D0FIFOHH; /* (@ 0x0000001B) D0FIFO Port Register HH */
};
@@ -188,7 +210,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint32_t D1FIFO; /* (@ 0x0000001C) D1FIFO Port Register */
- struct {
+ struct TU_ATTR_PACKED {
union {
volatile uint16_t D1FIFOL; /* (@ 0x0000001C) D1FIFO Port Register L */
volatile uint8_t D1FIFOLL; /* (@ 0x0000001C) D1FIFO Port Register LL */
@@ -197,7 +219,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t D1FIFOH; /* (@ 0x0000001E) D1FIFO Port Register H */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint8_t RESERVED5;
volatile uint8_t D1FIFOHH; /* (@ 0x0000001F) D1FIFO Port Register HH */
};
@@ -208,7 +230,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t CFIFOSEL; /* (@ 0x00000020) CFIFO Port Select Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t CURPIPE : 4; /* [3..0] CFIFO Port Access Pipe Specification */
uint16_t : 1;
volatile uint16_t ISEL : 1; /* [5..5] CFIFO Port Access Direction When DCP is Selected */
@@ -225,12 +247,12 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t CFIFOCTR; /* (@ 0x00000022) CFIFO Port Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t DTLN : 12; /* [11..0] Receive Data LengthIndicates the length of the receive data. */
uint16_t : 1;
volatile const uint16_t FRDY : 1; /* [13..13] FIFO Port Ready */
- volatile uint16_t BCLR : 1; /* [14..14] CPU Buffer ClearNote: Only 0 can be read. */
- volatile uint16_t BVAL : 1; /* [15..15] Buffer Memory Valid Flag */
+ volatile uint16_t BCLR : 1; /* [14..14] CPU Buffer ClearNote: Only 0 can be read. */
+ volatile uint16_t BVAL : 1; /* [15..15] Buffer Memory Valid Flag */
} CFIFOCTR_b;
};
volatile const uint32_t RESERVED6;
@@ -238,7 +260,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t D0FIFOSEL; /* (@ 0x00000028) D0FIFO Port Select Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t CURPIPE : 4; /* [3..0] FIFO Port Access Pipe Specification */
uint16_t : 4;
volatile uint16_t BIGEND : 1; /* [8..8] FIFO Port Endian Control */
@@ -254,19 +276,19 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t D0FIFOCTR; /* (@ 0x0000002A) D0FIFO Port Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t DTLN : 12; /* [11..0] Receive Data LengthIndicates the length of the receive data. */
uint16_t : 1;
volatile const uint16_t FRDY : 1; /* [13..13] FIFO Port Ready */
- volatile uint16_t BCLR : 1; /* [14..14] CPU Buffer ClearNote: Only 0 can be read. */
- volatile uint16_t BVAL : 1; /* [15..15] Buffer Memory Valid Flag */
+ volatile uint16_t BCLR : 1; /* [14..14] CPU Buffer ClearNote: Only 0 can be read. */
+ volatile uint16_t BVAL : 1; /* [15..15] Buffer Memory Valid Flag */
} D0FIFOCTR_b;
};
union {
volatile uint16_t D1FIFOSEL; /* (@ 0x0000002C) D1FIFO Port Select Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t CURPIPE : 4; /* [3..0] FIFO Port Access Pipe Specification */
uint16_t : 4;
volatile uint16_t BIGEND : 1; /* [8..8] FIFO Port Endian Control */
@@ -282,7 +304,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t D1FIFOCTR; /* (@ 0x0000002E) D1FIFO Port Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t DTLN : 12; /* [11..0] Receive Data LengthIndicates the length of the receive data. */
uint16_t : 1;
volatile const uint16_t FRDY : 1; /* [13..13] FIFO Port Ready */
@@ -294,8 +316,8 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t INTENB0; /* (@ 0x00000030) Interrupt Enable Register 0 */
- struct {
- uint16_t : 8;
+ struct TU_ATTR_PACKED {
+ uint16_t : 8;
volatile uint16_t BRDYE : 1; /* [8..8] Buffer Ready Interrupt Enable */
volatile uint16_t NRDYE : 1; /* [9..9] Buffer Not Ready Response Interrupt Enable */
volatile uint16_t BEMPE : 1; /* [10..10] Buffer Empty Interrupt Enable */
@@ -310,13 +332,16 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t INTENB1; /* (@ 0x00000032) Interrupt Enable Register 1 */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PDDETINTE0 : 1; /* [0..0] PDDETINT0 Detection Interrupt Enable */
uint16_t : 3;
volatile uint16_t SACKE : 1; /* [4..4] Setup Transaction Normal Response Interrupt Enable */
volatile uint16_t SIGNE : 1; /* [5..5] Setup Transaction Error Interrupt Enable */
volatile uint16_t EOFERRE : 1; /* [6..6] EOF Error Detection Interrupt Enable */
- uint16_t : 4;
+ uint16_t : 1;
+ volatile uint16_t LPMENDE : 1; /*!< [8..8] LPM Transaction End Interrupt Enable */
+ volatile uint16_t L1RSMENDE : 1; /*!< [9..9] L1 Resume End Interrupt Enable */
+ uint16_t : 1;
volatile uint16_t ATTCHE : 1; /* [11..11] Connection Detection Interrupt Enable */
volatile uint16_t DTCHE : 1; /* [12..12] Disconnection Detection Interrupt Enable */
uint16_t : 1;
@@ -329,7 +354,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t BRDYENB; /* (@ 0x00000036) BRDY Interrupt Enable Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PIPE0BRDYE : 1; /* [0..0] BRDY Interrupt Enable for PIPE */
volatile uint16_t PIPE1BRDYE : 1; /* [1..1] BRDY Interrupt Enable for PIPE */
volatile uint16_t PIPE2BRDYE : 1; /* [2..2] BRDY Interrupt Enable for PIPE */
@@ -340,14 +365,14 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t PIPE7BRDYE : 1; /* [7..7] BRDY Interrupt Enable for PIPE */
volatile uint16_t PIPE8BRDYE : 1; /* [8..8] BRDY Interrupt Enable for PIPE */
volatile uint16_t PIPE9BRDYE : 1; /* [9..9] BRDY Interrupt Enable for PIPE */
- uint16_t : 6;
+ uint16_t : 6;
} BRDYENB_b;
};
union {
volatile uint16_t NRDYENB; /* (@ 0x00000038) NRDY Interrupt Enable Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PIPE0NRDYE : 1; /* [0..0] NRDY Interrupt Enable for PIPE */
volatile uint16_t PIPE1NRDYE : 1; /* [1..1] NRDY Interrupt Enable for PIPE */
volatile uint16_t PIPE2NRDYE : 1; /* [2..2] NRDY Interrupt Enable for PIPE */
@@ -358,14 +383,14 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t PIPE7NRDYE : 1; /* [7..7] NRDY Interrupt Enable for PIPE */
volatile uint16_t PIPE8NRDYE : 1; /* [8..8] NRDY Interrupt Enable for PIPE */
volatile uint16_t PIPE9NRDYE : 1; /* [9..9] NRDY Interrupt Enable for PIPE */
- uint16_t : 6;
+ uint16_t : 6;
} NRDYENB_b;
};
union {
volatile uint16_t BEMPENB; /* (@ 0x0000003A) BEMP Interrupt Enable Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PIPE0BEMPE : 1; /* [0..0] BEMP Interrupt Enable for PIPE */
volatile uint16_t PIPE1BEMPE : 1; /* [1..1] BEMP Interrupt Enable for PIPE */
volatile uint16_t PIPE2BEMPE : 1; /* [2..2] BEMP Interrupt Enable for PIPE */
@@ -376,28 +401,28 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t PIPE7BEMPE : 1; /* [7..7] BEMP Interrupt Enable for PIPE */
volatile uint16_t PIPE8BEMPE : 1; /* [8..8] BEMP Interrupt Enable for PIPE */
volatile uint16_t PIPE9BEMPE : 1; /* [9..9] BEMP Interrupt Enable for PIPE */
- uint16_t : 6;
+ uint16_t : 6;
} BEMPENB_b;
};
union {
volatile uint16_t SOFCFG; /* (@ 0x0000003C) SOF Output Configuration Register */
- struct {
+ struct TU_ATTR_PACKED {
uint16_t : 4;
volatile const uint16_t EDGESTS : 1; /* [4..4] Edge Interrupt Output Status Monitor */
volatile uint16_t INTL : 1; /* [5..5] Interrupt Output Sense Select */
volatile uint16_t BRDYM : 1; /* [6..6] BRDY Interrupt Status Clear Timing */
uint16_t : 1;
volatile uint16_t TRNENSEL : 1; /* [8..8] Transaction-Enabled Time Select */
- uint16_t : 7;
+ uint16_t : 7;
} SOFCFG_b;
};
union {
volatile uint16_t PHYSET; /* (@ 0x0000003E) PHY Setting Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t DIRPD : 1; /* [0..0] Power-Down Control */
volatile uint16_t PLLRESET : 1; /* [1..1] PLL Reset Control */
uint16_t : 1;
@@ -415,7 +440,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t INTSTS0; /* (@ 0x00000040) Interrupt Status Register 0 */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t CTSQ : 3; /* [2..0] Control Transfer Stage */
volatile uint16_t VALID : 1; /* [3..3] USB Request Reception */
volatile const uint16_t DVSQ : 3; /* [6..4] Device State */
@@ -434,7 +459,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t INTSTS1; /* (@ 0x00000042) Interrupt Status Register 1 */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PDDETINT0 : 1; /* [0..0] PDDET0 Detection Interrupt Status */
uint16_t : 3;
volatile uint16_t SACK : 1; /* [4..4] Setup Transaction Normal Response Interrupt Status */
@@ -456,7 +481,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t BRDYSTS; /* (@ 0x00000046) BRDY Interrupt Status Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PIPE0BRDY : 1; /* [0..0] BRDY Interrupt Status for PIPE */
volatile uint16_t PIPE1BRDY : 1; /* [1..1] BRDY Interrupt Status for PIPE */
volatile uint16_t PIPE2BRDY : 1; /* [2..2] BRDY Interrupt Status for PIPE */
@@ -467,14 +492,14 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t PIPE7BRDY : 1; /* [7..7] BRDY Interrupt Status for PIPE */
volatile uint16_t PIPE8BRDY : 1; /* [8..8] BRDY Interrupt Status for PIPE */
volatile uint16_t PIPE9BRDY : 1; /* [9..9] BRDY Interrupt Status for PIPE */
- uint16_t : 6;
+ uint16_t : 6;
} BRDYSTS_b;
};
union {
volatile uint16_t NRDYSTS; /* (@ 0x00000048) NRDY Interrupt Status Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PIPE0NRDY : 1; /* [0..0] NRDY Interrupt Status for PIPE */
volatile uint16_t PIPE1NRDY : 1; /* [1..1] NRDY Interrupt Status for PIPE */
volatile uint16_t PIPE2NRDY : 1; /* [2..2] NRDY Interrupt Status for PIPE */
@@ -485,14 +510,14 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t PIPE7NRDY : 1; /* [7..7] NRDY Interrupt Status for PIPE */
volatile uint16_t PIPE8NRDY : 1; /* [8..8] NRDY Interrupt Status for PIPE */
volatile uint16_t PIPE9NRDY : 1; /* [9..9] NRDY Interrupt Status for PIPE */
- uint16_t : 6;
+ uint16_t : 6;
} NRDYSTS_b;
};
union {
volatile uint16_t BEMPSTS; /* (@ 0x0000004A) BEMP Interrupt Status Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PIPE0BEMP : 1; /* [0..0] BEMP Interrupt Status for PIPE */
volatile uint16_t PIPE1BEMP : 1; /* [1..1] BEMP Interrupt Status for PIPE */
volatile uint16_t PIPE2BEMP : 1; /* [2..2] BEMP Interrupt Status for PIPE */
@@ -503,14 +528,14 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t PIPE7BEMP : 1; /* [7..7] BEMP Interrupt Status for PIPE */
volatile uint16_t PIPE8BEMP : 1; /* [8..8] BEMP Interrupt Status for PIPE */
volatile uint16_t PIPE9BEMP : 1; /* [9..9] BEMP Interrupt Status for PIPE */
- uint16_t : 6;
+ uint16_t : 6;
} BEMPSTS_b;
};
union {
volatile uint16_t FRMNUM; /* (@ 0x0000004C) Frame Number Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t FRNM : 11; /* [10..0] Frame NumberLatest frame number */
uint16_t : 3;
volatile uint16_t CRCE : 1; /* [14..14] Receive Data Error */
@@ -521,7 +546,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t UFRMNUM; /* (@ 0x0000004E) uFrame Number Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t UFRNM : 3; /* [2..0] MicroframeIndicate the microframe number. */
uint16_t : 12;
volatile uint16_t DVCHG : 1; /* [15..15] Device State Change */
@@ -531,7 +556,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t USBADDR; /* (@ 0x00000050) USB Address Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t USBADDR : 7; /* [6..0] USB Address In device controller mode */
uint16_t : 1;
volatile uint16_t STSRECOV0 : 3; /* [10..8] Status Recovery */
@@ -543,7 +568,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t USBREQ; /* (@ 0x00000054) USB Request Type Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t BMREQUESTTYPE : 8; /* [7..0] Request TypeThese bits store the USB request bmRequestType value. */
volatile uint16_t BREQUEST : 8; /* [15..8] RequestThese bits store the USB request bRequest value. */
} USBREQ_b;
@@ -552,7 +577,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t USBVAL; /* (@ 0x00000056) USB Request Value Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t WVALUE : 16; /* [15..0] ValueThese bits store the USB request Value value. */
} USBVAL_b;
};
@@ -560,7 +585,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t USBINDX; /* (@ 0x00000058) USB Request Index Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t WINDEX : 16; /* [15..0] IndexThese bits store the USB request wIndex value. */
} USBINDX_b;
};
@@ -568,7 +593,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t USBLENG; /* (@ 0x0000005A) USB Request Length Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t WLENGTH : 16; /* [15..0] LengthThese bits store the USB request wLength value. */
} USBLENG_b;
};
@@ -576,7 +601,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t DCPCFG; /* (@ 0x0000005C) DCP Configuration Register */
- struct {
+ struct TU_ATTR_PACKED {
uint16_t : 4;
volatile uint16_t DIR : 1; /* [4..4] Transfer Direction */
uint16_t : 2;
@@ -589,7 +614,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t DCPMAXP; /* (@ 0x0000005E) DCP Maximum Packet Size Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t MXPS : 7; /* [6..0] Maximum Packet Size */
uint16_t : 5;
volatile uint16_t DEVSEL : 4; /* [15..12] Device Select */
@@ -599,7 +624,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t DCPCTR; /* (@ 0x00000060) DCP Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PID : 2; /* [1..0] Response PID */
volatile uint16_t CCPL : 1; /* [2..2] Control Transfer End Enable */
uint16_t : 2;
@@ -609,7 +634,8 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t SQCLR : 1; /* [8..8] Sequence Toggle Bit Clear */
uint16_t : 2;
volatile uint16_t SUREQCLR : 1; /* [11..11] SUREQ Bit Clear */
- uint16_t : 2;
+ volatile uint16_t CSSTS : 1; /* [12..12] Split Transaction COMPLETE SPLIT(CSPLIT) Status */
+ volatile uint16_t CSCLR : 1; /* [13..13] Split Transaction CSPLIT Status Clear */
volatile uint16_t SUREQ : 1; /* [14..14] Setup Token Transmission */
volatile const uint16_t BSTS : 1; /* [15..15] Buffer Status */
} DCPCTR_b;
@@ -619,9 +645,9 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t PIPESEL; /* (@ 0x00000064) Pipe Window Select Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PIPESEL : 4; /* [3..0] Pipe Window Select */
- uint16_t : 12;
+ uint16_t : 12;
} PIPESEL_b;
};
volatile const uint16_t RESERVED11;
@@ -629,26 +655,36 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t PIPECFG; /* (@ 0x00000068) Pipe Configuration Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t EPNUM : 4; /* [3..0] Endpoint Number */
volatile uint16_t DIR : 1; /* [4..4] Transfer Direction */
uint16_t : 2;
volatile uint16_t SHTNAK : 1; /* [7..7] Pipe Disabled at End of Transfer */
- uint16_t : 1;
+ volatile uint16_t CNTMD : 1; /* [8..8] Continuous Transfer Mode */
volatile uint16_t DBLB : 1; /* [9..9] Double Buffer Mode */
volatile uint16_t BFRE : 1; /* [10..10] BRDY Interrupt Operation Specification */
uint16_t : 3;
volatile uint16_t TYPE : 2; /* [15..14] Transfer Type */
} PIPECFG_b;
};
- volatile const uint16_t RESERVED12;
union {
- volatile uint16_t PIPEMAXP; /* (@ 0x0000006C) Pipe Maximum Packet Size Register */
+ volatile uint16_t PIPEBUF; /*!< (@ 0x0000006A) Pipe Buffer Register */
struct {
- volatile uint16_t MXPS : 9; /* [8..0] Maximum Packet Size */
- uint16_t : 3;
+ volatile uint16_t BUFNMB : 8; // [7..0] Buffer NumberThese bits specify the FIFO buffer number of the selected pipe (04h to 87h)
+ uint16_t : 2;
+ volatile uint16_t BUFSIZE : 5; /*!< [14..10] Buffer Size 00h: 64 bytes 01h: 128 bytes : 1Fh: 2 Kbytes */
+ uint16_t : 1;
+ } PIPEBUF_b;
+ };
+
+ union {
+ volatile uint16_t PIPEMAXP; /* (@ 0x0000006C) Pipe Maximum Packet Size Register */
+
+ struct TU_ATTR_PACKED {
+ volatile uint16_t MXPS : 11; /* [10..0] Maximum Packet Size */
+ uint16_t : 1;
volatile uint16_t DEVSEL : 4; /* [15..12] Device Select */
} PIPEMAXP_b;
};
@@ -656,7 +692,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t PIPEPERI; /* (@ 0x0000006E) Pipe Cycle Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t IITV : 3; /* [2..0] Interval Error Detection Interval */
uint16_t : 9;
volatile uint16_t IFIS : 1; /* [12..12] Isochronous IN Buffer Flush */
@@ -667,7 +703,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t PIPE_CTR[9]; /* (@ 0x00000070) Pipe [0..8] Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t PID : 2; /* [1..0] Response PID */
uint16_t : 3;
volatile const uint16_t PBUSY : 1; /* [5..5] Pipe Busy */
@@ -691,14 +727,12 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t USBBCCTRL0; /* (@ 0x000000B0) BC Control Register 0 */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t RPDME0 : 1; /* [0..0] D- Pin Pull-Down Control */
volatile uint16_t IDPSRCE0 : 1; /* [1..1] D+ Pin IDPSRC Output Control */
- volatile uint16_t
- IDMSINKE0 : 1; /* [2..2] D- Pin 0.6 V Input Detection (Comparator and Sink) Control */
+ volatile uint16_t IDMSINKE0 : 1; /* [2..2] D- Pin 0.6 V Input Detection (Comparator and Sink) Control */
volatile uint16_t VDPSRCE0 : 1; /* [3..3] D+ Pin VDPSRC (0.6 V) Output Control */
- volatile uint16_t
- IDPSINKE0 : 1; /* [4..4] D+ Pin 0.6 V Input Detection (Comparator and Sink) Control */
+ volatile uint16_t IDPSINKE0 : 1; /* [4..4] D+ Pin 0.6 V Input Detection (Comparator and Sink) Control */
volatile uint16_t VDMSRCE0 : 1; /* [5..5] D- Pin VDMSRC (0.6 V) Output Control */
uint16_t : 1;
volatile uint16_t BATCHGE0 : 1; /* [7..7] BC (Battery Charger) Function Ch0 General Enable Control */
@@ -713,9 +747,9 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t UCKSEL; /* (@ 0x000000C4) USB Clock Selection Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t UCKSELC : 1; /* [0..0] USB Clock Selection */
- uint16_t : 15;
+ uint16_t : 15;
} UCKSEL_b;
};
volatile const uint16_t RESERVED18;
@@ -724,7 +758,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t USBMC; /* (@ 0x000000CC) USB Module Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t VDDUSBE : 1; /* [0..0] USB Reference Power Supply Circuit On/Off Control */
uint16_t : 6;
volatile uint16_t VDCEN : 1; /* [7..7] USB Regulator On/Off Control */
@@ -736,12 +770,12 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t DEVADD[10]; /* (@ 0x000000D0) Device Address Configuration Register */
- struct {
- uint16_t : 6;
+ struct TU_ATTR_PACKED {
+ uint16_t : 6;
volatile uint16_t USBSPD : 2; /* [7..6] Transfer Speed of Communication Target Device */
volatile uint16_t HUBPORT : 3; /* [10..8] Communication Target Connecting Hub Port */
volatile uint16_t UPPHUB : 4; /* [14..11] Communication Target Connecting Hub Register */
- uint16_t : 1;
+ uint16_t : 1;
} DEVADD_b[10];
};
volatile const uint32_t RESERVED21[3];
@@ -749,12 +783,12 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint32_t PHYSLEW; /* (@ 0x000000F0) PHY Cross Point Adjustment Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint32_t SLEWR00 : 1; /* [0..0] Receiver Cross Point Adjustment 00 */
volatile uint32_t SLEWR01 : 1; /* [1..1] Receiver Cross Point Adjustment 01 */
volatile uint32_t SLEWF00 : 1; /* [2..2] Receiver Cross Point Adjustment 00 */
volatile uint32_t SLEWF01 : 1; /* [3..3] Receiver Cross Point Adjustment 01 */
- uint32_t : 28;
+ uint32_t : 28;
} PHYSLEW_b;
};
volatile const uint32_t RESERVED22[3];
@@ -762,20 +796,20 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t LPCTRL; /* (@ 0x00000100) Low Power Control Register */
- struct {
- uint16_t : 7;
+ struct TU_ATTR_PACKED {
+ uint16_t : 7;
volatile uint16_t HWUPM : 1; /* [7..7] Resume Return Mode Setting */
- uint16_t : 8;
+ uint16_t : 8;
} LPCTRL_b;
};
union {
volatile uint16_t LPSTS; /* (@ 0x00000102) Low Power Status Register */
- struct {
- uint16_t : 14;
+ struct TU_ATTR_PACKED {
+ uint16_t : 14;
volatile uint16_t SUSPENDM : 1; /* [14..14] UTMI SuspendM Control */
- uint16_t : 1;
+ uint16_t : 1;
} LPSTS_b;
};
volatile const uint32_t RESERVED23[15];
@@ -783,7 +817,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t BCCTRL; /* (@ 0x00000140) Battery Charging Control Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t IDPSRCE : 1; /* [0..0] IDPSRC Control */
volatile uint16_t IDMSINKE : 1; /* [1..1] IDMSINK Control */
volatile uint16_t VDPSRCE : 1; /* [2..2] VDPSRC Control */
@@ -793,7 +827,7 @@ typedef struct TU_ATTR_PACKED {
uint16_t : 2;
volatile const uint16_t CHGDETSTS : 1; /* [8..8] CHGDET Status */
volatile const uint16_t PDDETSTS : 1; /* [9..9] PDDET Status */
- uint16_t : 6;
+ uint16_t : 6;
} BCCTRL_b;
};
volatile const uint16_t RESERVED24;
@@ -801,7 +835,7 @@ typedef struct TU_ATTR_PACKED {
union {
volatile uint16_t PL1CTRL1; /* (@ 0x00000144) Function L1 Control Register 1 */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t L1RESPEN : 1; /* [0..0] L1 Response Enable */
volatile uint16_t L1RESPMD : 2; /* [2..1] L1 Response Mode */
volatile uint16_t L1NEGOMD : 1; /* [3..3] L1 Response Negotiation Control. */
@@ -809,35 +843,35 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t HIRDTHR : 4; /* [11..8] L1 Response Negotiation Threshold Value */
uint16_t : 2;
volatile uint16_t L1EXTMD : 1; /* [14..14] PHY Control Mode at L1 Return */
- uint16_t : 1;
+ uint16_t : 1;
} PL1CTRL1_b;
};
union {
volatile uint16_t PL1CTRL2; /* (@ 0x00000146) Function L1 Control Register 2 */
- struct {
- uint16_t : 8;
+ struct TU_ATTR_PACKED {
+ uint16_t : 8;
volatile uint16_t HIRDMON : 4; /* [11..8] HIRD Value Monitor */
volatile uint16_t RWEMON : 1; /* [12..12] RWE Value Monitor */
- uint16_t : 3;
+ uint16_t : 3;
} PL1CTRL2_b;
};
union {
volatile uint16_t HL1CTRL1; /* (@ 0x00000148) Host L1 Control Register 1 */
- struct {
- volatile uint16_t L1REQ : 1; /* [0..0] L1 Transition Request */
+ struct TU_ATTR_PACKED {
+ volatile uint16_t L1REQ : 1; /* [0..0] L1 Transition Request */
volatile const uint16_t L1STATUS : 2; /* [2..1] L1 Request Completion Status */
- uint16_t : 13;
+ uint16_t : 13;
} HL1CTRL1_b;
};
union {
volatile uint16_t HL1CTRL2; /* (@ 0x0000014A) Host L1 Control Register 2 */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint16_t L1ADDR : 4; /* [3..0] LPM Token DeviceAddress */
uint16_t : 4;
volatile uint16_t HIRD : 4; /* [11..8] LPM Token HIRD */
@@ -846,26 +880,56 @@ typedef struct TU_ATTR_PACKED {
volatile uint16_t BESL : 1; /* [15..15] BESL & Alternate HIRD */
} HL1CTRL2_b;
};
- volatile const uint32_t RESERVED25[5];
+
+ volatile uint32_t RESERVED25_1;
union {
- volatile const uint32_t DPUSR0R; /* (@ 0x00000160) Deep Standby USB Transceiver Control/Pin Monitor Register */
+ volatile uint16_t PHYTRIM1; /*!< (@ 0x00000150) PHY Timing Register 1 */
+
+ struct {
+ volatile uint16_t DRISE : 2; /*!< [1..0] FS/LS Rising-Edge Output Waveform Adjustment Function */
+ volatile uint16_t DFALL : 2; /*!< [3..2] FS/LS Falling-Edge Output Waveform Adjustment Function */
+ uint16_t : 3;
+ volatile uint16_t PCOMPENB : 1; /*!< [7..7] PVDD Start-up Detection */
+ volatile uint16_t HSIUP : 4; /*!< [11..8] HS Output Level Setting */
+ volatile uint16_t IMPOFFSET : 3; /*!< [14..12] terminating resistance offset value setting.Offset value for adjusting the terminating resistance. */
+ uint16_t : 1;
+ } PHYTRIM1_b;
+ };
+
+ union {
+ volatile uint16_t PHYTRIM2; /*!< (@ 0x00000152) PHY Timing Register 2 */
struct {
- uint32_t : 20;
+ volatile uint16_t SQU : 4; /*!< [3..0] Squelch Detection Level */
+ uint16_t : 3;
+ volatile uint16_t HSRXENMO : 1; /*!< [7..7] HS Receive Enable Control Mode */
+ volatile uint16_t PDR : 2; /*!< [9..8] HS Output Adjustment Function */
+ uint16_t : 2;
+ volatile uint16_t DIS : 3; /*!< [14..12] Disconnect Detection Level */
+ uint16_t : 1;
+ } PHYTRIM2_b;
+ };
+ volatile uint32_t RESERVED25_2[3];
+
+ union {
+ volatile const uint32_t DPUSR0R; /* (@ 0x00000160) Deep Standby USB Transceiver Control/Pin Monitor Register */
+
+ struct TU_ATTR_PACKED {
+ uint32_t : 20;
volatile const uint32_t DOVCAHM : 1; /* [20..20] OVRCURA InputIndicates OVRCURA input signal on the HS side of USB port. */
volatile const uint32_t DOVCBHM : 1; /* [21..21] OVRCURB InputIndicates OVRCURB input signal on the HS side of USB port. */
uint32_t : 1;
volatile const uint32_t DVBSTSHM : 1; /* [23..23] VBUS InputIndicates VBUS input signal on the HS side of USB port. */
- uint32_t : 8;
+ uint32_t : 8;
} DPUSR0R_b;
};
union {
volatile uint32_t DPUSR1R; /* (@ 0x00000164) Deep Standby USB Suspend/Resume Interrupt Register */
- struct {
- uint32_t : 4;
+ struct TU_ATTR_PACKED {
+ uint32_t : 4;
volatile uint32_t DOVCAHE : 1; /* [4..4] OVRCURA Interrupt Enable Clear */
volatile uint32_t DOVCBHE : 1; /* [5..5] OVRCURB Interrupt Enable Clear */
uint32_t : 1;
@@ -875,14 +939,14 @@ typedef struct TU_ATTR_PACKED {
volatile const uint32_t DOVCBH : 1; /* [21..21] Indication of Return from OVRCURB Interrupt Source */
uint32_t : 1;
volatile const uint32_t DVBSTSH : 1; /* [23..23] Indication of Return from VBUS Interrupt Source */
- uint32_t : 8;
+ uint32_t : 8;
} DPUSR1R_b;
};
union {
volatile uint16_t DPUSR2R; /* (@ 0x00000168) Deep Standby USB Suspend/Resume Interrupt Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile const uint16_t DPINT : 1; /* [0..0] Indication of Return from DP Interrupt Source */
volatile const uint16_t DMINT : 1; /* [1..1] Indication of Return from DM Interrupt Source */
uint16_t : 2;
@@ -891,17 +955,17 @@ typedef struct TU_ATTR_PACKED {
uint16_t : 2;
volatile uint16_t DPINTE : 1; /* [8..8] DP Interrupt Enable Clear */
volatile uint16_t DMINTE : 1; /* [9..9] DM Interrupt Enable Clear */
- uint16_t : 6;
+ uint16_t : 6;
} DPUSR2R_b;
};
union {
volatile uint16_t DPUSRCR; /* (@ 0x0000016A) Deep Standby USB Suspend/Resume Command Register */
- struct {
- volatile uint16_t FIXPHY : 1; /* [0..0] USB Transceiver Control Fix */
+ struct TU_ATTR_PACKED {
+ volatile uint16_t FIXPHY : 1; /* [0..0] USB Transceiver Control Fix */
volatile uint16_t FIXPHYPD : 1; /* [1..1] USB Transceiver Control Fix for PLL */
- uint16_t : 14;
+ uint16_t : 14;
} DPUSRCR_b;
};
volatile const uint32_t RESERVED26[165];
@@ -910,7 +974,7 @@ typedef struct TU_ATTR_PACKED {
volatile uint32_t
DPUSR0R_FS; /* (@ 0x00000400) Deep Software Standby USB Transceiver Control/Pin Monitor Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint32_t SRPC0 : 1; /* [0..0] USB Single End Receiver Control */
volatile uint32_t RPUE0 : 1; /* [1..1] DP Pull-Up Resistor Control */
uint32_t : 1;
@@ -924,14 +988,14 @@ typedef struct TU_ATTR_PACKED {
volatile const uint32_t DOVCB0 : 1; /* [21..21] USB OVRCURB InputIndicates the OVRCURB input signal of the USB. */
uint32_t : 1;
volatile const uint32_t DVBSTS0 : 1; /* [23..23] USB VBUS InputIndicates the VBUS input signal of the USB. */
- uint32_t : 8;
+ uint32_t : 8;
} DPUSR0R_FS_b;
};
union {
volatile uint32_t DPUSR1R_FS; /* (@ 0x00000404) Deep Software Standby USB Suspend/Resume Interrupt Register */
- struct {
+ struct TU_ATTR_PACKED {
volatile uint32_t DPINTE0 : 1; /* [0..0] USB DP Interrupt Enable/Clear */
volatile uint32_t DMINTE0 : 1; /* [1..1] USB DM Interrupt Enable/Clear */
uint32_t : 2;
@@ -947,10 +1011,10 @@ typedef struct TU_ATTR_PACKED {
volatile const uint32_t DOVRCRB0 : 1; /* [21..21] USB OVRCURB Interrupt Source Recovery */
uint32_t : 1;
volatile const uint32_t DVBINT0 : 1; /* [23..23] USB VBUS Interrupt Source Recovery */
- uint32_t : 8;
+ uint32_t : 8;
} DPUSR1R_FS_b;
};
-} RUSB2_REG_t; /* Size = 1032 (0x408) */
+} rusb2_reg_t; /* Size = 1032 (0x408) */
TU_ATTR_PACKED_END /* End of definition of packed structs (used by the CCRX toolchain) */
TU_ATTR_BIT_FIELD_ORDER_END
@@ -970,13 +1034,15 @@ TU_ATTR_BIT_FIELD_ORDER_END
#define RUSB2_PIPE_TR_N_TRNCNT_Pos (0UL) /* TRNCNT (Bit 0) */
#define RUSB2_PIPE_TR_N_TRNCNT_Msk (0xffffUL) /* TRNCNT (Bitfield-Mask: 0xffff) */
-// LINK_REG
+// Core Registers
// SYSCFG
#define RUSB2_SYSCFG_SCKE_Pos (10UL) /* SCKE (Bit 10) */
#define RUSB2_SYSCFG_SCKE_Msk (0x400UL) /* SCKE (Bitfield-Mask: 0x01) */
#define RUSB2_SYSCFG_CNEN_Pos (8UL) /* CNEN (Bit 8) */
#define RUSB2_SYSCFG_CNEN_Msk (0x100UL) /* CNEN (Bitfield-Mask: 0x01) */
+#define RUSB2_SYSCFG_HSE_Pos (7UL) /*!< HSE (Bit 7) */
+#define RUSB2_SYSCFG_HSE_Msk (0x80UL) /*!< HSE (Bitfield-Mask: 0x01) */
#define RUSB2_SYSCFG_DCFM_Pos (6UL) /* DCFM (Bit 6) */
#define RUSB2_SYSCFG_DCFM_Msk (0x40UL) /* DCFM (Bitfield-Mask: 0x01) */
#define RUSB2_SYSCFG_DRPD_Pos (5UL) /* DRPD (Bit 5) */
@@ -1135,6 +1201,10 @@ TU_ATTR_BIT_FIELD_ORDER_END
#define RUSB2_INTENB1_DTCHE_Msk (0x1000UL) /* DTCHE (Bitfield-Mask: 0x01) */
#define RUSB2_INTENB1_ATTCHE_Pos (11UL) /* ATTCHE (Bit 11) */
#define RUSB2_INTENB1_ATTCHE_Msk (0x800UL) /* ATTCHE (Bitfield-Mask: 0x01) */
+#define RUSB2_INTENB1_L1RSMENDE_Pos (9UL) /*!< L1RSMENDE (Bit 9) */
+#define RUSB2_INTENB1_L1RSMENDE_Msk (0x200UL) /*!< L1RSMENDE (Bitfield-Mask: 0x01) */
+#define RUSB2_INTENB1_LPMENDE_Pos (8UL) /*!< LPMENDE (Bit 8) */
+#define RUSB2_INTENB1_LPMENDE_Msk (0x100UL) /*!< LPMENDE (Bitfield-Mask: 0x01) */
#define RUSB2_INTENB1_EOFERRE_Pos (6UL) /* EOFERRE (Bit 6) */
#define RUSB2_INTENB1_EOFERRE_Msk (0x40UL) /* EOFERRE (Bitfield-Mask: 0x01) */
#define RUSB2_INTENB1_SIGNE_Pos (5UL) /* SIGNE (Bit 5) */
@@ -1299,6 +1369,10 @@ TU_ATTR_BIT_FIELD_ORDER_END
#define RUSB2_DCPCTR_BSTS_Msk (0x8000UL) /* BSTS (Bitfield-Mask: 0x01) */
#define RUSB2_DCPCTR_SUREQ_Pos (14UL) /* SUREQ (Bit 14) */
#define RUSB2_DCPCTR_SUREQ_Msk (0x4000UL) /* SUREQ (Bitfield-Mask: 0x01) */
+#define R_USB_HS0_DCPCTR_CSCLR_Pos (13UL) /*!< CSCLR (Bit 13) */
+#define RUSB2_DCPCTR_CSCLR_Msk (0x2000UL) /*!< CSCLR (Bitfield-Mask: 0x01) */
+#define RUSB2_DCPCTR_CSSTS_Pos (12UL) /*!< CSSTS (Bit 12) */
+#define RUSB2_DCPCTR_CSSTS_Msk (0x1000UL) /*!< CSSTS (Bitfield-Mask: 0x01) */
#define RUSB2_DCPCTR_SUREQCLR_Pos (11UL) /* SUREQCLR (Bit 11) */
#define RUSB2_DCPCTR_SUREQCLR_Msk (0x800UL) /* SUREQCLR (Bitfield-Mask: 0x01) */
#define RUSB2_DCPCTR_SQCLR_Pos (8UL) /* SQCLR (Bit 8) */
@@ -1325,6 +1399,8 @@ TU_ATTR_BIT_FIELD_ORDER_END
#define RUSB2_PIPECFG_BFRE_Msk (0x400UL) /* BFRE (Bitfield-Mask: 0x01) */
#define RUSB2_PIPECFG_DBLB_Pos (9UL) /* DBLB (Bit 9) */
#define RUSB2_PIPECFG_DBLB_Msk (0x200UL) /* DBLB (Bitfield-Mask: 0x01) */
+#define RUSB2_PIPECFG_CNTMD_Pos (8UL) /*!< CNTMD (Bit 8) */
+#define RUSB2_PIPECFG_CNTMD_Msk (0x100UL) /*!< CNTMD (Bitfield-Mask: 0x01) */
#define RUSB2_PIPECFG_SHTNAK_Pos (7UL) /* SHTNAK (Bit 7) */
#define RUSB2_PIPECFG_SHTNAK_Msk (0x80UL) /* SHTNAK (Bitfield-Mask: 0x01) */
#define RUSB2_PIPECFG_DIR_Pos (4UL) /* DIR (Bit 4) */
@@ -1332,6 +1408,12 @@ TU_ATTR_BIT_FIELD_ORDER_END
#define RUSB2_PIPECFG_EPNUM_Pos (0UL) /* EPNUM (Bit 0) */
#define RUSB2_PIPECFG_EPNUM_Msk (0xfUL) /* EPNUM (Bitfield-Mask: 0x0f) */
+// PIPEBUF
+#define RUSB2_PIPEBUF_BUFSIZE_Pos (10UL) /*!< BUFSIZE (Bit 10) */
+#define RUSB2_PIPEBUF_BUFSIZE_Msk (0x7c00UL) /*!< BUFSIZE (Bitfield-Mask: 0x1f) */
+#define RUSB2_PIPEBUF_BUFNMB_Pos (0UL) /*!< BUFNMB (Bit 0) */
+#define RUSB2_PIPEBUF_BUFNMB_Msk (0xffUL) /*!< BUFNMB (Bitfield-Mask: 0xff) */
+
// PIPEMAXP
#define RUSB2_PIPEMAXP_DEVSEL_Pos (12UL) /* DEVSEL (Bit 12) */
#define RUSB2_PIPEMAXP_DEVSEL_Msk (0xf000UL) /* DEVSEL (Bitfield-Mask: 0x0f) */
@@ -1478,6 +1560,28 @@ TU_ATTR_BIT_FIELD_ORDER_END
#define RUSB2_HL1CTRL2_L1ADDR_Pos (0UL) /* L1ADDR (Bit 0) */
#define RUSB2_HL1CTRL2_L1ADDR_Msk (0xfUL) /* L1ADDR (Bitfield-Mask: 0x0f) */
+// PHYTRIM1
+#define RUSB2_PHYTRIM1_IMPOFFSET_Pos (12UL) /*!< IMPOFFSET (Bit 12) */
+#define RUSB2_PHYTRIM1_IMPOFFSET_Msk (0x7000UL) /*!< IMPOFFSET (Bitfield-Mask: 0x07) */
+#define RUSB2_PHYTRIM1_HSIUP_Pos (8UL) /*!< HSIUP (Bit 8) */
+#define RUSB2_PHYTRIM1_HSIUP_Msk (0xf00UL) /*!< HSIUP (Bitfield-Mask: 0x0f) */
+#define RUSB2_PHYTRIM1_PCOMPENB_Pos (7UL) /*!< PCOMPENB (Bit 7) */
+#define RUSB2_PHYTRIM1_PCOMPENB_Msk (0x80UL) /*!< PCOMPENB (Bitfield-Mask: 0x01) */
+#define RUSB2_PHYTRIM1_DFALL_Pos (2UL) /*!< DFALL (Bit 2) */
+#define RUSB2_PHYTRIM1_DFALL_Msk (0xcUL) /*!< DFALL (Bitfield-Mask: 0x03) */
+#define RUSB2_PHYTRIM1_DRISE_Pos (0UL) /*!< DRISE (Bit 0) */
+#define RUSB2_PHYTRIM1_DRISE_Msk (0x3UL) /*!< DRISE (Bitfield-Mask: 0x03) */
+
+// PHYTRIM2
+#define RUSB2_PHYTRIM2_DIS_Pos (12UL) /*!< DIS (Bit 12) */
+#define RUSB2_PHYTRIM2_DIS_Msk (0x7000UL) /*!< DIS (Bitfield-Mask: 0x07) */
+#define RUSB2_PHYTRIM2_PDR_Pos (8UL) /*!< PDR (Bit 8) */
+#define RUSB2_PHYTRIM2_PDR_Msk (0x300UL) /*!< PDR (Bitfield-Mask: 0x03) */
+#define RUSB2_PHYTRIM2_HSRXENMO_Pos (7UL) /*!< HSRXENMO (Bit 7) */
+#define RUSB2_PHYTRIM2_HSRXENMO_Msk (0x80UL) /*!< HSRXENMO (Bitfield-Mask: 0x01) */
+#define RUSB2_PHYTRIM2_SQU_Pos (0UL) /*!< SQU (Bit 0) */
+#define RUSB2_PHYTRIM2_SQU_Msk (0xfUL) /*!< SQU (Bitfield-Mask: 0x0f) */
+
// DPUSR0R
#define RUSB2_DPUSR0R_DVBSTSHM_Pos (23UL) /* DVBSTSHM (Bit 23) */
#define RUSB2_DPUSR0R_DVBSTSHM_Msk (0x800000UL) /* DVBSTSHM (Bitfield-Mask: 0x01) */
@@ -1568,9 +1672,11 @@ TU_ATTR_BIT_FIELD_ORDER_END
#define RUSB2_PIPE_CTR_PID_NAK (0U << RUSB2_PIPE_CTR_PID_Pos) /* NAK response */
#define RUSB2_PIPE_CTR_PID_BUF (1U << RUSB2_PIPE_CTR_PID_Pos) /* BUF response (depends buffer state) */
#define RUSB2_PIPE_CTR_PID_STALL (2U << RUSB2_PIPE_CTR_PID_Pos) /* STALL response */
+#define RUSB2_PIPE_CTR_PID_STALL2 (3U << RUSB2_PIPE_CTR_PID_Pos) /* Also STALL response */
#define RUSB2_DVSTCTR0_RHST_LS (1U << RUSB2_DVSTCTR0_RHST_Pos) /* Low-speed connection */
#define RUSB2_DVSTCTR0_RHST_FS (2U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */
+#define RUSB2_DVSTCTR0_RHST_HS (3U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */
#define RUSB2_DEVADD_USBSPD_LS (1U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Low-speed */
#define RUSB2_DEVADD_USBSPD_FS (2U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Full-speed */
@@ -1580,6 +1686,7 @@ TU_ATTR_BIT_FIELD_ORDER_END
#define RUSB2_FIFOSEL_BIGEND (1U << RUSB2_CFIFOSEL_BIGEND_Pos) /* FIFO Big Endian */
#define RUSB2_FIFOSEL_MBW_8BIT (0U << RUSB2_CFIFOSEL_MBW_Pos) /* 8-bit width */
#define RUSB2_FIFOSEL_MBW_16BIT (1U << RUSB2_CFIFOSEL_MBW_Pos) /* 16-bit width */
+#define RUSB2_FIFOSEL_MBW_32BIT (2U << RUSB2_CFIFOSEL_MBW_Pos) /* 32-bit width */
#define RUSB2_INTSTS0_CTSQ_CTRL_RDATA (1U << RUSB2_INTSTS0_CTSQ_Pos)
@@ -1599,68 +1706,72 @@ TU_ATTR_BIT_FIELD_ORDER_END
//--------------------------------------------------------------------+
TU_VERIFY_STATIC(sizeof(RUSB2_PIPE_TR_t) == 4, "incorrect size");
+TU_VERIFY_STATIC(sizeof(rusb2_reg_t) == 1032, "incorrect size");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, SYSCFG ) == 0x00000000, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, BUSWAIT ) == 0x00000002, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, SYSSTS0 ) == 0x00000004, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PLLSTA ) == 0x00000006, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DVSTCTR0 ) == 0x00000008, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, TESTMODE ) == 0x0000000C, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, CFIFO ) == 0x00000014, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, D0FIFO ) == 0x00000018, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, D1FIFO ) == 0x0000001C, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, CFIFOSEL ) == 0x00000020, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, CFIFOCTR ) == 0x00000022, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, D0FIFOSEL ) == 0x00000028, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, D0FIFOCTR ) == 0x0000002A, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, D1FIFOSEL ) == 0x0000002C, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, D1FIFOCTR ) == 0x0000002E, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, INTENB0 ) == 0x00000030, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, INTENB1 ) == 0x00000032, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, BRDYENB ) == 0x00000036, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, NRDYENB ) == 0x00000038, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, BEMPENB ) == 0x0000003A, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, SOFCFG ) == 0x0000003C, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PHYSET ) == 0x0000003E, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, INTSTS0 ) == 0x00000040, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, INTSTS1 ) == 0x00000042, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, BRDYSTS ) == 0x00000046, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, NRDYSTS ) == 0x00000048, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, BEMPSTS ) == 0x0000004A, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, FRMNUM ) == 0x0000004C, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, UFRMNUM ) == 0x0000004E, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, USBADDR ) == 0x00000050, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, USBREQ ) == 0x00000054, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, USBVAL ) == 0x00000056, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, USBINDX ) == 0x00000058, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, USBLENG ) == 0x0000005A, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DCPCFG ) == 0x0000005C, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DCPMAXP ) == 0x0000005E, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DCPCTR ) == 0x00000060, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PIPESEL ) == 0x00000064, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PIPECFG ) == 0x00000068, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PIPEMAXP ) == 0x0000006C, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PIPEPERI ) == 0x0000006E, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PIPE_CTR ) == 0x00000070, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PIPE_TR ) == 0x00000090, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, USBBCCTRL0 ) == 0x000000B0, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, UCKSEL ) == 0x000000C4, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, USBMC ) == 0x000000CC, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DEVADD ) == 0x000000D0, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PHYSLEW ) == 0x000000F0, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, LPCTRL ) == 0x00000100, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, LPSTS ) == 0x00000102, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, BCCTRL ) == 0x00000140, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PL1CTRL1 ) == 0x00000144, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, PL1CTRL2 ) == 0x00000146, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, HL1CTRL1 ) == 0x00000148, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, HL1CTRL2 ) == 0x0000014A, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DPUSR0R ) == 0x00000160, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DPUSR1R ) == 0x00000164, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DPUSR2R ) == 0x00000168, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DPUSRCR ) == 0x0000016A, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DPUSR0R_FS ) == 0x00000400, "incorrect offset");
-TU_VERIFY_STATIC(offsetof(RUSB2_REG_t, DPUSR1R_FS ) == 0x00000404, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, SYSCFG ) == 0x0000, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, BUSWAIT ) == 0x0002, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, SYSSTS0 ) == 0x0004, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PLLSTA ) == 0x0006, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DVSTCTR0 ) == 0x0008, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, TESTMODE ) == 0x000C, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, CFIFO ) == 0x0014, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, D0FIFO ) == 0x0018, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, D1FIFO ) == 0x001C, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, CFIFOSEL ) == 0x0020, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, CFIFOCTR ) == 0x0022, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, D0FIFOSEL ) == 0x0028, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, D0FIFOCTR ) == 0x002A, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, D1FIFOSEL ) == 0x002C, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, D1FIFOCTR ) == 0x002E, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, INTENB0 ) == 0x0030, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, INTENB1 ) == 0x0032, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, BRDYENB ) == 0x0036, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, NRDYENB ) == 0x0038, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, BEMPENB ) == 0x003A, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, SOFCFG ) == 0x003C, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PHYSET ) == 0x003E, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, INTSTS0 ) == 0x0040, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, INTSTS1 ) == 0x0042, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, BRDYSTS ) == 0x0046, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, NRDYSTS ) == 0x0048, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, BEMPSTS ) == 0x004A, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, FRMNUM ) == 0x004C, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, UFRMNUM ) == 0x004E, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, USBADDR ) == 0x0050, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, USBREQ ) == 0x0054, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, USBVAL ) == 0x0056, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, USBINDX ) == 0x0058, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, USBLENG ) == 0x005A, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DCPCFG ) == 0x005C, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DCPMAXP ) == 0x005E, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DCPCTR ) == 0x0060, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PIPESEL ) == 0x0064, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PIPECFG ) == 0x0068, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PIPEBUF ) == 0x006A, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PIPEMAXP ) == 0x006C, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PIPEPERI ) == 0x006E, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PIPE_CTR ) == 0x0070, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PIPE_TR ) == 0x0090, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, USBBCCTRL0 ) == 0x00B0, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, UCKSEL ) == 0x00C4, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, USBMC ) == 0x00CC, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DEVADD ) == 0x00D0, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PHYSLEW ) == 0x00F0, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, LPCTRL ) == 0x0100, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, LPSTS ) == 0x0102, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, BCCTRL ) == 0x0140, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PL1CTRL1 ) == 0x0144, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PL1CTRL2 ) == 0x0146, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, HL1CTRL1 ) == 0x0148, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, HL1CTRL2 ) == 0x014A, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PHYTRIM1 ) == 0x0150, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, PHYTRIM2 ) == 0x0152, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSR0R ) == 0x0160, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSR1R ) == 0x0164, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSR2R ) == 0x0168, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSRCR ) == 0x016A, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSR0R_FS ) == 0x0400, "incorrect offset");
+TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSR1R_FS ) == 0x0404, "incorrect offset");
#ifdef __cplusplus
}
diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c
index 6677891a5..41814370e 100644
--- a/src/portable/sony/cxd56/dcd_cxd56.c
+++ b/src/portable/sony/cxd56/dcd_cxd56.c
@@ -102,17 +102,25 @@ static int _dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_
usbdev = dev;
usbdcd_driver.ep[0] = dev->ep0;
+ #ifdef EP_ALLOCREQ
+ // SDK v2
usbdcd_driver.req[0] = EP_ALLOCREQ(usbdcd_driver.ep[0]);
- if (usbdcd_driver.req[0] != NULL)
- {
+ if (usbdcd_driver.req[0] != NULL) {
usbdcd_driver.req[0]->len = 64;
usbdcd_driver.req[0]->buf = EP_ALLOCBUFFER(usbdcd_driver.ep[0], 64);
- if (!usbdcd_driver.req[0]->buf)
- {
+ if (!usbdcd_driver.req[0]->buf) {
EP_FREEREQ(usbdcd_driver.ep[0], usbdcd_driver.req[0]);
usbdcd_driver.req[0] = NULL;
+ return ENOMEM;
}
}
+ #else
+ // SDK v3
+ usbdcd_driver.req[0] = usbdev_allocreq(usbdcd_driver.ep[0], 64);
+ if (usbdcd_driver.req[0] == NULL) {
+ return ENOMEM;
+ }
+ #endif
usbdcd_driver.req[0]->callback = usbdcd_ep0incomplete;
@@ -295,13 +303,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
}
usbdcd_driver.req[epnum] = NULL;
+
+ #ifdef EP_ALLOCREQ
+ // sdk v2
usbdcd_driver.req[epnum] = EP_ALLOCREQ(usbdcd_driver.ep[epnum]);
- if (usbdcd_driver.req[epnum] != NULL)
- {
+ if (usbdcd_driver.req[epnum] != NULL) {
usbdcd_driver.req[epnum]->len = ep_mps;
}
- else
- {
+ #else
+ // sdk v3
+ usbdcd_driver.req[epnum] = usbdev_allocreq(usbdcd_driver.ep[epnum], ep_mps);
+ #endif
+
+ if(usbdcd_driver.req[epnum] == NULL) {
return false;
}
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index 98d3d0829..7bf726f3f 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -44,6 +44,7 @@
* L0x2, L0x3 1024 byte buffer
* L1 512 byte buffer
* L4x2, L4x3 1024 byte buffer
+ * G0 2048 byte buffer
*
* To use this driver, you must:
* - If you are using a device with crystal-less USB, set up the clock recovery system (CRS)
@@ -108,7 +109,7 @@
#ifdef TUP_USBIP_FSDEV_STM32
// Undefine to reduce the dependence on HAL
#undef USE_HAL_DRIVER
- #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h"
+ #include "portable/st/stm32_fsdev/dcd_stm32_fsdev.h"
#endif
/*****************************************************
@@ -127,8 +128,8 @@
# define DCD_STM32_BTABLE_BASE 0U
#endif
-#ifndef DCD_STM32_BTABLE_LENGTH
-# define DCD_STM32_BTABLE_LENGTH (PMA_LENGTH - DCD_STM32_BTABLE_BASE)
+#ifndef DCD_STM32_BTABLE_SIZE
+# define DCD_STM32_BTABLE_SIZE (FSDEV_PMA_SIZE - DCD_STM32_BTABLE_BASE)
#endif
/***************************************************
@@ -136,7 +137,7 @@
*/
TU_VERIFY_STATIC((MAX_EP_COUNT) <= STFSDEV_EP_COUNT, "Only 8 endpoints supported on the hardware");
-TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_LENGTH))<=(PMA_LENGTH), "BTABLE does not fit in PMA RAM");
+TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_SIZE)) <= (FSDEV_PMA_SIZE), "BTABLE does not fit in PMA RAM");
TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes");
//--------------------------------------------------------------------+
@@ -185,12 +186,12 @@ static void dcd_ep_ctr_handler(void);
static uint8_t open_ep_count;
static uint16_t ep_buf_ptr; ///< Points to first free memory location
static void dcd_pma_alloc_reset(void);
-static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length);
+static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length);
static void dcd_pma_free(uint8_t ep_addr);
static void dcd_ep_free(uint8_t ep_addr);
static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type);
-static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes);
-static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes);
+static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes);
+static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes);
static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes);
static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes);
@@ -199,8 +200,7 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB
// Inline helper
//--------------------------------------------------------------------+
-TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr)
-{
+TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr) {
uint8_t epnum = tu_edpt_number(ep_addr);
uint8_t dir = tu_edpt_dir(ep_addr);
// Fix -Werror=null-dereference
@@ -209,17 +209,6 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t* xfer_ctl_ptr(uint32_t ep_addr)
return &xfer_status[epnum][dir];
}
-// Using a function due to better type checks
-// This seems better than having to do type casts everywhere else
-TU_ATTR_ALWAYS_INLINE static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) {
- *reg = (uint16_t)(*reg & ~mask);
-}
-
-// Bits in ISTR are cleared upon writing 0
-TU_ATTR_ALWAYS_INLINE static inline void clear_istr_bits(uint16_t mask) {
- USB->ISTR = ~mask;
-}
-
//--------------------------------------------------------------------+
// Controller API
//--------------------------------------------------------------------+
@@ -242,7 +231,9 @@ void dcd_init (uint8_t rhport)
{
asm("NOP");
}
- reg16_clear_bits(&USB->CNTR, USB_CNTR_PDWN);// Remove powerdown
+
+ USB->CNTR &= ~USB_CNTR_PDWN;
+
// Wait startup time, for F042 and F070, this is <= 1 us.
for(uint32_t i = 0; i<200; i++) // should be a few us
{
@@ -250,8 +241,9 @@ void dcd_init (uint8_t rhport)
}
USB->CNTR = 0; // Enable USB
+#if !defined(STM32G0) && !defined(STM32H5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address
USB->BTABLE = DCD_STM32_BTABLE_BASE;
-
+#endif
USB->ISTR = 0; // Clear pending interrupts
// Reset endpoints to disabled
@@ -312,7 +304,7 @@ void dcd_sof_enable(uint8_t rhport, bool en)
}
else
{
- USB->CNTR &= (uint16_t) ~USB_CNTR_SOFM;
+ USB->CNTR &= ~USB_CNTR_SOFM;
}
}
@@ -358,6 +350,16 @@ void dcd_int_enable (uint8_t rhport)
NVIC_EnableIRQ(USB_LP_IRQn);
NVIC_EnableIRQ(USBWakeUp_IRQn);
+#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
+ #ifdef STM32G0B0xx
+ NVIC_EnableIRQ(USB_IRQn);
+ #else
+ NVIC_EnableIRQ(USB_UCPD1_2_IRQn);
+ #endif
+
+#elif CFG_TUSB_MCU == OPT_MCU_STM32H5
+ NVIC_EnableIRQ(USB_DRD_FS_IRQn);
+
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
NVIC_EnableIRQ(USB_HP_IRQn);
NVIC_EnableIRQ(USB_LP_IRQn);
@@ -408,6 +410,16 @@ void dcd_int_disable(uint8_t rhport)
NVIC_DisableIRQ(USB_LP_IRQn);
NVIC_DisableIRQ(USBWakeUp_IRQn);
+#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
+ #ifdef STM32G0B0xx
+ NVIC_DisableIRQ(USB_IRQn);
+ #else
+ NVIC_DisableIRQ(USB_UCPD1_2_IRQn);
+ #endif
+
+#elif CFG_TUSB_MCU == OPT_MCU_STM32H5
+ NVIC_DisableIRQ(USB_DRD_FS_IRQn);
+
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
NVIC_DisableIRQ(USB_HP_IRQn);
NVIC_DisableIRQ(USB_LP_IRQn);
@@ -439,7 +451,7 @@ void dcd_remote_wakeup(uint8_t rhport)
{
(void) rhport;
- USB->CNTR |= (uint16_t) USB_CNTR_RESUME;
+ USB->CNTR |= USB_CNTR_RESUME;
remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms.
}
@@ -470,7 +482,6 @@ static void dcd_handle_bus_reset(void)
//__IO uint16_t * const epreg = &(EPREG(0));
USB->DADDR = 0u; // disable USB peripheral by clearing the EF flag
-
for(uint32_t i=0; i<STFSDEV_EP_COUNT; i++)
{
// Clear all EPREG (or maybe this is automatic? I'm not sure)
@@ -512,7 +523,7 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr)
xfer_ctl_t * xfer = xfer_ctl_ptr(ep_addr);
if((xfer->total_len != xfer->queued_len)) /* TX not complete */
{
- dcd_transmit_packet(xfer, EPindex);
+ dcd_transmit_packet(xfer, EPindex);
}
else /* TX Complete */
{
@@ -521,10 +532,29 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr)
}
// Handle CTR interrupt for the RX/OUT direction
-//
// Upon call, (wIstr & USB_ISTR_DIR) == 0U
-static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
-{
+static void dcd_ep_ctr_rx_handler(uint32_t wIstr) {
+ #ifdef FSDEV_BUS_32BIT
+ /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf
+ * From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers
+ * Description:
+ * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses
+ * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct.
+ * Workaround:
+ * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay
+ * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode
+ * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code
+ * also takes time, so we'll wait 40 cycles (count = 20).
+ * - Since Low Speed mode is not supported/popular, we will ignore it for now.
+ *
+ * Note: this errata also seems to apply to G0, U5, H5 etc.
+ */
+ volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver
+ while (cycle_count > 0U) {
+ cycle_count--; // each count take 2 cycle (1 cycle for sub, 1 cycle for compare/jump)
+ }
+ #endif
+
uint32_t EPindex = wIstr & USB_ISTR_EP_ID;
uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex);
uint8_t ep_addr = wEPRegVal & USB_EPADDR_FIELD;
@@ -533,16 +563,12 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
// Verify the CTR_RX bit is set. This was in the ST Micro code,
// but I'm not sure it's actually necessary?
- if((wEPRegVal & USB_EP_CTR_RX) == 0U)
- {
+ if((wEPRegVal & USB_EP_CTR_RX) == 0U) {
return;
}
if((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) /* Setup packet */
{
- // The setup_received function uses memcpy, so this must first copy the setup data into
- // user memory, to allow for the 32-bit access that memcpy performs.
- uint8_t userMemBuf[8];
uint32_t count = pcd_get_ep_rx_cnt(USB, EPindex);
/* Get SETUP Packet*/
if(count == 8) // Setup packet should always be 8 bytes. If not, ignore it, and try again.
@@ -550,8 +576,15 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
// Must reset EP to NAK (in case it had been stalling) (though, maybe too late here)
pcd_set_ep_rx_status(USB,0u,USB_EP_RX_NAK);
pcd_set_ep_tx_status(USB,0u,USB_EP_TX_NAK);
- dcd_read_packet_memory(userMemBuf, *pcd_ep_rx_address_ptr(USB,EPindex), 8);
+#ifdef FSDEV_BUS_32BIT
+ dcd_event_setup_received(0, (uint8_t*)(USB_PMAADDR + pcd_get_ep_rx_address(USB, EPindex)), true);
+#else
+ // The setup_received function uses memcpy, so this must first copy the setup data into
+ // user memory, to allow for the 32-bit access that memcpy performs.
+ uint8_t userMemBuf[8];
+ dcd_read_packet_memory(userMemBuf, pcd_get_ep_rx_address(USB,EPindex), 8);
dcd_event_setup_received(0, (uint8_t*)userMemBuf, true);
+#endif
}
}
else
@@ -574,7 +607,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
if (count != 0U)
{
- uint16_t addr = *pcd_ep_rx_address_ptr(USB, EPindex);
+ uint16_t addr = pcd_get_ep_rx_address(USB, EPindex);
if (xfer->ff)
{
@@ -617,26 +650,22 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr)
// (Based on the docs, it seems SETUP will always be accepted after CTR is cleared)
if(ep_addr == 0u)
{
- // Always be prepared for a status packet...
+ // Always be prepared for a status packet...
pcd_set_ep_rx_bufsize(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE);
pcd_clear_rx_ep_ctr(USB, EPindex);
}
}
-static void dcd_ep_ctr_handler(void)
-{
+static void dcd_ep_ctr_handler(void) {
uint32_t wIstr;
/* stay in loop while pending interrupts */
- while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U)
- {
-
- if ((wIstr & USB_ISTR_DIR) == 0U) /* TX/IN */
- {
+ while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) {
+ if ((wIstr & USB_ISTR_DIR) == 0U) {
+ /* TX/IN */
dcd_ep_ctr_tx_handler(wIstr);
- }
- else /* RX/OUT*/
- {
+ } else {
+ /* RX/OUT*/
dcd_ep_ctr_rx_handler(wIstr);
}
}
@@ -657,13 +686,13 @@ void dcd_int_handler(uint8_t rhport) {
/* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */
if(int_status & USB_ISTR_SOF) {
- clear_istr_bits(USB_ISTR_SOF);
+ USB->ISTR = (fsdev_bus_t)~USB_ISTR_SOF;
dcd_event_sof(0, USB->FNR & USB_FNR_FN, true);
}
if(int_status & USB_ISTR_RESET) {
// USBRST is start of reset.
- clear_istr_bits(USB_ISTR_RESET);
+ USB->ISTR = (fsdev_bus_t)~USB_ISTR_RESET;
dcd_handle_bus_reset();
dcd_event_bus_reset(0, TUSB_SPEED_FULL, true);
return; // Don't do the rest of the things here; perhaps they've been cleared?
@@ -678,9 +707,10 @@ void dcd_int_handler(uint8_t rhport) {
if (int_status & USB_ISTR_WKUP)
{
- reg16_clear_bits(&USB->CNTR, USB_CNTR_LPMODE);
- reg16_clear_bits(&USB->CNTR, USB_CNTR_FSUSP);
- clear_istr_bits(USB_ISTR_WKUP);
+ USB->CNTR &= ~USB_CNTR_LPMODE;
+ USB->CNTR &= ~USB_CNTR_FSUSP;
+
+ USB->ISTR = (fsdev_bus_t)~USB_ISTR_WKUP;
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
}
@@ -694,20 +724,20 @@ void dcd_int_handler(uint8_t rhport) {
USB->CNTR |= USB_CNTR_LPMODE;
/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
- clear_istr_bits(USB_ISTR_SUSP);
+ USB->ISTR = (fsdev_bus_t)~USB_ISTR_SUSP;
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
}
if(int_status & USB_ISTR_ESOF) {
if(remoteWakeCountdown == 1u)
{
- USB->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
+ USB->CNTR &= ~USB_CNTR_RESUME;
}
if(remoteWakeCountdown > 0u)
{
remoteWakeCountdown--;
}
- clear_istr_bits(USB_ISTR_ESOF);
+ USB->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF;
}
}
@@ -728,8 +758,8 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re
uint8_t const dev_addr = (uint8_t) request->wValue;
// Setting new address after the whole request is complete
- reg16_clear_bits(&USB->DADDR, USB_DADDR_ADD);
- USB->DADDR = (uint16_t)(USB->DADDR | dev_addr); // leave the enable bit set
+ USB->DADDR &= ~USB_DADDR_ADD;
+ USB->DADDR |= dev_addr; // leave the enable bit set
}
}
@@ -756,7 +786,7 @@ static void dcd_pma_alloc_reset(void)
*
* During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually.
*/
-static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length)
+static uint16_t dcd_pma_alloc(uint8_t ep_addr, uint16_t length)
{
xfer_ctl_t* epXferCtl = xfer_ctl_ptr(ep_addr);
@@ -768,17 +798,24 @@ static uint16_t dcd_pma_alloc(uint8_t ep_addr, size_t length)
return epXferCtl->pma_ptr;
}
+ // Ensure allocated buffer is aligned
+#ifdef FSDEV_BUS_32BIT
+ length = (length + 3) & ~0x03;
+#else
+ length = (length + 1) & ~0x01;
+#endif
+
open_ep_count++;
uint16_t addr = ep_buf_ptr;
ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer
// Verify no overflow
- TU_ASSERT(ep_buf_ptr <= PMA_LENGTH, 0xFFFF);
+ TU_ASSERT(ep_buf_ptr <= FSDEV_PMA_SIZE, 0xFFFF);
epXferCtl->pma_ptr = addr;
epXferCtl->pma_alloc_size = length;
- //TU_LOG2("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr);
+ //TU_LOG1("dcd_pma_alloc(%x,%x)=%x\r\n",ep_addr,length,addr);
return addr;
}
@@ -931,14 +968,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc
if( (dir == TUSB_DIR_IN) || (wType == USB_EP_ISOCHRONOUS) )
{
- *pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr;
+ pcd_set_ep_tx_address(USB, ep_idx, pma_addr);
pcd_set_ep_tx_bufsize(USB, ep_idx, buffer_size);
pcd_clear_tx_dtog(USB, ep_idx);
}
if( (dir == TUSB_DIR_OUT) || (wType == USB_EP_ISOCHRONOUS) )
{
- *pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr;
+ pcd_set_ep_rx_address(USB, ep_idx, pma_addr);
pcd_set_ep_rx_bufsize(USB, ep_idx, buffer_size);
pcd_clear_rx_dtog(USB, ep_idx);
}
@@ -1018,8 +1055,8 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet
pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS);
- *pcd_ep_tx_address_ptr(USB, ep_idx) = pma_addr;
- *pcd_ep_rx_address_ptr(USB, ep_idx) = pma_addr;
+ pcd_set_ep_tx_address(USB, ep_idx, pma_addr);
+ pcd_set_ep_rx_address(USB, ep_idx, pma_addr);
return true;
}
@@ -1069,7 +1106,7 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix)
}
uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix);
- uint16_t addr_ptr = *pcd_ep_tx_address_ptr(USB,ep_ix);
+ uint16_t addr_ptr = pcd_get_ep_tx_address(USB, ep_ix);
if (xfer->ff)
{
@@ -1203,6 +1240,40 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
}
}
+#ifdef FSDEV_BUS_32BIT
+static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes)
+{
+ const uint8_t* srcVal = src;
+ volatile uint32_t* dst32 = (volatile uint32_t*)(USB_PMAADDR + dst);
+
+ for (uint32_t n = wNBytes / 4; n > 0; --n) {
+ *dst32++ = tu_unaligned_read32(srcVal);
+ srcVal += 4;
+ }
+
+ wNBytes = wNBytes & 0x03;
+ if (wNBytes)
+ {
+ uint32_t wrVal = *srcVal;
+ wNBytes--;
+
+ if (wNBytes)
+ {
+ wrVal |= *++srcVal << 8;
+ wNBytes--;
+
+ if (wNBytes)
+ {
+ wrVal |= *++srcVal << 16;
+ }
+ }
+
+ *dst32 = wrVal;
+ }
+
+ return true;
+}
+#else
// Packet buffer access can only be 8- or 16-bit.
/**
* @brief Copy a buffer from user memory area to packet memory area (PMA).
@@ -1214,7 +1285,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
* @param wNBytes no. of bytes to be copied.
* @retval None
*/
-static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes)
+static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes)
{
uint32_t n = (uint32_t)wNBytes >> 1U;
uint16_t temp1, temp2;
@@ -1225,7 +1296,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si
__IO uint16_t *pdwVal;
srcVal = src;
- pdwVal = &pma[PMA_STRIDE*(dst>>1)];
+ pdwVal = &pma[FSDEV_PMA_STRIDE * (dst >> 1)];
while (n--)
{
@@ -1233,11 +1304,11 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si
srcVal++;
temp2 = temp1 | ((uint16_t)(((uint16_t)(*srcVal)) << 8U)) ;
*pdwVal = temp2;
- pdwVal += PMA_STRIDE;
+ pdwVal += FSDEV_PMA_STRIDE;
srcVal++;
}
- if (wNBytes & 0x01)
+ if (wNBytes)
{
temp1 = *srcVal;
*pdwVal = temp1;
@@ -1245,6 +1316,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si
return true;
}
+#endif
/**
* @brief Copy from FIFO to packet memory area (PMA).
@@ -1263,7 +1335,37 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN
// We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
// last lin byte will be combined with wrapped part
- // To ensure PMA is always access 16bit aligned (dst aligned to 16 bit)
+ // To ensure PMA is always access aligned (dst aligned to 16 or 32 bit)
+#ifdef FSDEV_BUS_32BIT
+ if((cnt_lin & 0x03) && cnt_wrap)
+ {
+ // Copy first linear part
+ dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin &~0x03);
+ dst += cnt_lin &~0x03;
+
+ // Copy last linear bytes & first wrapped bytes to buffer
+ uint32_t i;
+ uint8_t tmp[4];
+ for (i = 0; i < (cnt_lin & 0x03); i++)
+ {
+ tmp[i] = ((uint8_t*)info.ptr_lin)[(cnt_lin &~0x03) + i];
+ }
+ uint32_t wCnt = cnt_wrap;
+ for (; i < 4 && wCnt > 0; i++, wCnt--)
+ {
+ tmp[i] = *(uint8_t*)info.ptr_wrap;
+ info.ptr_wrap = (uint8_t*)info.ptr_wrap + 1;
+ }
+
+ // Write unaligned buffer
+ dcd_write_packet_memory(dst, &tmp, 4);
+ dst += 4;
+
+ // Copy rest of wrapped byte
+ if (wCnt)
+ dcd_write_packet_memory(dst, info.ptr_wrap, wCnt);
+ }
+#else
if((cnt_lin & 0x01) && cnt_wrap)
{
// Copy first linear part
@@ -1278,6 +1380,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN
// Copy rest of wrapped byte
dcd_write_packet_memory(dst, ((uint8_t*)info.ptr_wrap) + 1, cnt_wrap - 1);
}
+#endif
else
{
// Copy linear part
@@ -1296,13 +1399,47 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wN
return true;
}
+#ifdef FSDEV_BUS_32BIT
+static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes)
+{
+ uint8_t* dstVal = dst;
+ volatile uint32_t* src32 = (volatile uint32_t*)(USB_PMAADDR + src);
+
+ for (uint32_t n = wNBytes / 4; n > 0; --n) {
+ tu_unaligned_write32(dstVal, *src32++);
+ dstVal += 4;
+ }
+
+ wNBytes = wNBytes & 0x03;
+ if (wNBytes)
+ {
+ uint32_t rdVal = *src32;
+
+ *dstVal = tu_u32_byte0(rdVal);
+ wNBytes--;
+
+ if (wNBytes)
+ {
+ *++dstVal = tu_u32_byte1(rdVal);
+ wNBytes--;
+
+ if (wNBytes)
+ {
+ *++dstVal = tu_u32_byte2(rdVal);
+ }
+ }
+ }
+
+ return true;
+}
+#else
/**
* @brief Copy a buffer from packet memory area (PMA) to user memory area.
* Uses byte-access of system memory and 16-bit access of packet memory
* @param wNBytes no. of bytes to be copied.
* @retval None
*/
-static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes)
+static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes)
{
uint32_t n = (uint32_t)wNBytes >> 1U;
// The GCC optimizer will combine access to 32-bit sizes if we let it. Force
@@ -1310,13 +1447,13 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN
__IO const uint16_t *pdwVal;
uint32_t temp;
- pdwVal = &pma[PMA_STRIDE*(src>>1)];
+ pdwVal = &pma[FSDEV_PMA_STRIDE * (src >> 1)];
uint8_t *dstVal = (uint8_t*)dst;
while (n--)
{
temp = *pdwVal;
- pdwVal += PMA_STRIDE;
+ pdwVal += FSDEV_PMA_STRIDE;
*dstVal++ = ((temp >> 0) & 0xFF);
*dstVal++ = ((temp >> 8) & 0xFF);
}
@@ -1324,11 +1461,12 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN
if (wNBytes & 0x01)
{
temp = *pdwVal;
- pdwVal += PMA_STRIDE;
+ pdwVal += FSDEV_PMA_STRIDE;
*dstVal++ = ((temp >> 0) & 0xFF);
}
return true;
}
+#endif
/**
* @brief Copy a buffer from user packet memory area (PMA) to FIFO.
@@ -1346,9 +1484,39 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB
uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin);
uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap);
+
// We want to read from PMA and write it into the FIFO, if LIN part is ODD and has WRAPPED part,
// last lin byte will be combined with wrapped part
- // To ensure PMA is always access 16bit aligned (src aligned to 16 bit)
+ // To ensure PMA is always access aligned (src aligned to 16 or 32 bit)
+#ifdef FSDEV_BUS_32BIT
+ if((cnt_lin & 0x03) && cnt_wrap)
+ {
+ // Copy first linear part
+ dcd_read_packet_memory(info.ptr_lin, src, cnt_lin &~0x03);
+ src += cnt_lin &~0x03;
+
+ // Copy last linear bytes & first wrapped bytes
+ uint8_t tmp[4];
+ dcd_read_packet_memory(tmp, src, 4);
+ src += 4;
+
+ uint32_t i;
+ for (i = 0; i < (cnt_lin & 0x03); i++)
+ {
+ ((uint8_t*)info.ptr_lin)[(cnt_lin &~0x03) + i] = tmp[i];
+ }
+ uint32_t wCnt = cnt_wrap;
+ for (; i < 4 && wCnt > 0; i++, wCnt--)
+ {
+ *(uint8_t*)info.ptr_wrap = tmp[i];
+ info.ptr_wrap = (uint8_t*)info.ptr_wrap + 1;
+ }
+
+ // Copy rest of wrapped byte
+ if (wCnt)
+ dcd_read_packet_memory(info.ptr_wrap, src, wCnt);
+ }
+#else
if((cnt_lin & 0x01) && cnt_wrap)
{
// Copy first linear part
@@ -1356,16 +1524,17 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNB
src += cnt_lin &~0x01;
// Copy last linear byte & first wrapped byte
- uint16_t tmp;
- dcd_read_packet_memory(&tmp, src, 2);
-
- ((uint8_t*)info.ptr_lin)[cnt_lin - 1] = (uint8_t)tmp;
- ((uint8_t*)info.ptr_wrap)[0] = (uint8_t)(tmp >> 8U);
+ uint8_t tmp[2];
+ dcd_read_packet_memory(tmp, src, 2);
src += 2;
+ ((uint8_t*)info.ptr_lin)[cnt_lin - 1] = tmp[0];
+ ((uint8_t*)info.ptr_wrap)[0] = tmp[1];
+
// Copy rest of wrapped byte
dcd_read_packet_memory(((uint8_t*)info.ptr_wrap) + 1, src, cnt_wrap - 1);
}
+#endif
else
{
// Copy linear part
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h
index e3fc8aeb5..946ad2c7c 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h
@@ -1,34 +1,36 @@
-/**
- * Copyright(c) 2016 STMicroelectronics
- * Copyright(c) N Conrad
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
+/*
+ * Copyright(c) 2016 STMicroelectronics
+ * Copyright(c) N Conrad
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
// This file contains source copied from ST's HAL, and thus should have their copyright statement.
-// PMA_LENGTH is PMA buffer size in bytes.
+// FSDEV_PMA_SIZE is PMA buffer size in bytes.
// On 512-byte devices, access with a stride of two words (use every other 16-bit address)
// On 1024-byte devices, access with a stride of one word (use every 16-bit address)
@@ -37,7 +39,7 @@
#if CFG_TUSB_MCU == OPT_MCU_STM32F0
#include "stm32f0xx.h"
- #define PMA_LENGTH (1024u)
+ #define FSDEV_PMA_SIZE (1024u)
// F0x2 models are crystal-less
// All have internal D+ pull-up
// 070RB: 2 x 16 bits/word memory LPM Support, BCD Support
@@ -45,7 +47,7 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
#include "stm32f1xx.h"
- #define PMA_LENGTH (512u)
+ #define FSDEV_PMA_SIZE (512u)
// NO internal Pull-ups
// *B, and *C: 2 x 16 bits/word
@@ -56,7 +58,7 @@
defined(STM32F303xB) || defined(STM32F303xC) || \
defined(STM32F373xC)
#include "stm32f3xx.h"
- #define PMA_LENGTH (512u)
+ #define FSDEV_PMA_SIZE (512u)
// NO internal Pull-ups
// *B, and *C: 1 x 16 bits/word
// PMA dedicated to USB (no sharing with CAN)
@@ -65,37 +67,98 @@
defined(STM32F302xD) || defined(STM32F302xE) || \
defined(STM32F303xD) || defined(STM32F303xE)
#include "stm32f3xx.h"
- #define PMA_LENGTH (1024u)
+ #define FSDEV_PMA_SIZE (1024u)
// NO internal Pull-ups
// *6, *8, *D, and *E: 2 x 16 bits/word LPM Support
// When CAN clock is enabled, USB can use first 768 bytes ONLY.
#elif CFG_TUSB_MCU == OPT_MCU_STM32L0
#include "stm32l0xx.h"
- #define PMA_LENGTH (1024u)
+ #define FSDEV_PMA_SIZE (1024u)
#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
#include "stm32l1xx.h"
- #define PMA_LENGTH (512u)
+ #define FSDEV_PMA_SIZE (512u)
#elif CFG_TUSB_MCU == OPT_MCU_STM32G4
#include "stm32g4xx.h"
- #define PMA_LENGTH (1024u)
+ #define FSDEV_PMA_SIZE (1024u)
+
+#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
+ #include "stm32g0xx.h"
+ #define FSDEV_BUS_32BIT
+ #define FSDEV_PMA_SIZE (2048u)
+ #undef USB_PMAADDR
+ #define USB_PMAADDR USB_DRD_PMAADDR
+ #define USB_TypeDef USB_DRD_TypeDef
+ #define EP0R CHEP0R
+ #define USB_EP_CTR_RX USB_EP_VTRX
+ #define USB_EP_CTR_TX USB_EP_VTTX
+ #define USB_EP_T_FIELD USB_CHEP_UTYPE
+ #define USB_EPREG_MASK USB_CHEP_REG_MASK
+ #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK
+ #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK
+ #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1
+ #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2
+ #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1
+ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2
+ #define USB_EPRX_STAT USB_CH_RX_VALID
+ #define USB_EPKIND_MASK USB_EP_KIND_MASK
+ #define USB USB_DRD_FS
+ #define USB_CNTR_FRES USB_CNTR_USBRST
+ #define USB_CNTR_RESUME USB_CNTR_L2RES
+ #define USB_ISTR_EP_ID USB_ISTR_IDN
+ #define USB_EPADDR_FIELD USB_CHEP_ADDR
+ #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY
+ #define USB_CNTR_FSUSP USB_CNTR_SUSPEN
+
+#elif CFG_TUSB_MCU == OPT_MCU_STM32H5
+ #include "stm32h5xx.h"
+ #define FSDEV_BUS_32BIT
+
+ #if !defined(USB_DRD_BASE) && defined(USB_DRD_FS_BASE)
+ #define USB_DRD_BASE USB_DRD_FS_BASE
+ #endif
+
+ #define FSDEV_PMA_SIZE (2048u)
+ #undef USB_PMAADDR
+ #define USB_PMAADDR USB_DRD_PMAADDR
+ #define USB_TypeDef USB_DRD_TypeDef
+ #define EP0R CHEP0R
+ #define USB_EP_CTR_RX USB_EP_VTRX
+ #define USB_EP_CTR_TX USB_EP_VTTX
+ #define USB_EP_T_FIELD USB_CHEP_UTYPE
+ #define USB_EPREG_MASK USB_CHEP_REG_MASK
+ #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK
+ #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK
+ #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1
+ #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2
+ #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1
+ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2
+ #define USB_EPRX_STAT USB_CH_RX_VALID
+ #define USB_EPKIND_MASK USB_EP_KIND_MASK
+ #define USB USB_DRD_FS
+ #define USB_CNTR_FRES USB_CNTR_USBRST
+ #define USB_CNTR_RESUME USB_CNTR_L2RES
+ #define USB_ISTR_EP_ID USB_ISTR_IDN
+ #define USB_EPADDR_FIELD USB_CHEP_ADDR
+ #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY
+ #define USB_CNTR_FSUSP USB_CNTR_SUSPEN
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
#include "stm32wbxx.h"
- #define PMA_LENGTH (1024u)
+ #define FSDEV_PMA_SIZE (1024u)
/* ST provided header has incorrect value */
#undef USB_PMAADDR
#define USB_PMAADDR USB1_PMAADDR
#elif CFG_TUSB_MCU == OPT_MCU_STM32L4
#include "stm32l4xx.h"
- #define PMA_LENGTH (1024u)
+ #define FSDEV_PMA_SIZE (1024u)
#elif CFG_TUSB_MCU == OPT_MCU_STM32L5
#include "stm32l5xx.h"
- #define PMA_LENGTH (1024u)
+ #define FSDEV_PMA_SIZE (1024u)
#ifndef USB_PMAADDR
#define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS))
@@ -107,25 +170,41 @@
#endif
// For purposes of accessing the packet
-#if ((PMA_LENGTH) == 512u)
- #define PMA_STRIDE (2u)
-#elif ((PMA_LENGTH) == 1024u)
- #define PMA_STRIDE (1u)
+#if ((FSDEV_PMA_SIZE) == 512u)
+ #define FSDEV_PMA_STRIDE (2u)
+#elif ((FSDEV_PMA_SIZE) == 1024u)
+ #define FSDEV_PMA_STRIDE (1u)
#endif
-// And for type-safety create a new macro for the volatile address of PMAADDR
+// The fsdev_bus_t type can be used for both register and PMA access necessities
+// For type-safety create a new macro for the volatile address of PMAADDR
// The compiler should warn us if we cast it to a non-volatile type?
+#ifdef FSDEV_BUS_32BIT
+typedef uint32_t fsdev_bus_t;
+static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR;
+
+#else
+typedef uint16_t fsdev_bus_t;
// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden)
static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR;
-// prototypes
-TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx);
-TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx);
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue);
+TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) {
+ size_t total_word_offset = (((USBx)->BTABLE)>>1) + x;
+ total_word_offset *= FSDEV_PMA_STRIDE;
+ return &(pma[total_word_offset]);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) {
+ return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) {
+ return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u);
+}
+#endif
/* Aligned buffer size according to hardware */
-TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) {
/* The STM32 full speed USB peripheral supports only a limited set of
* buffer sizes given by the RX buffer entry format in the USB_BTABLE. */
uint16_t blocksize = (size > 62) ? 32 : 2;
@@ -136,21 +215,28 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si
return numblocks * blocksize;
}
-/* SetENDPOINT */
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ __O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4);
+ *reg = wRegValue;
+#else
__O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
*reg = (uint16_t)wRegValue;
+#endif
}
-/* GetENDPOINT */
-TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) {
+TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ __I uint32_t *reg = (__I uint32_t *)(USB_DRD_BASE + bEpIdx*4);
+#else
__I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
+#endif
return *reg;
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= (uint32_t)USB_EP_T_MASK;
regVal |= wType;
@@ -158,20 +244,19 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
-TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EP_T_FIELD;
return regVal;
}
+
/**
* @brief Clears bit CTR_RX / CTR_TX in the endpoint register.
* @param USBx USB peripheral instance register address.
* @param bEpIdx Endpoint Number.
* @retval None
*/
-TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal &= ~USB_EP_CTR_RX;
@@ -179,50 +264,38 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx,
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal &= ~USB_EP_CTR_TX;
regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0)
pcd_set_endpoint(USBx, bEpIdx,regVal);
}
+
/**
* @brief gets counter of the tx buffer.
* @param USBx USB peripheral instance register address.
* @param bEpIdx Endpoint Number.
* @retval Counter value
*/
-TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ return (pma32[2*bEpIdx] & 0x03FF0000) >> 16;
+#else
__I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
return *regPtr & 0x3ffU;
+#endif
}
-TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16;
+#else
__I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
return *regPtr & 0x3ffU;
-}
-
-/**
- * @brief Sets counter of rx buffer with no. of blocks.
- * @param dwReg Register
- * @param wCount Counter.
- * @param wNBlocks no. of Blocks.
- * @retval None
- */
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_cnt_reg(__O uint16_t * pdwReg, size_t wCount)
-{
- /* We assume that the buffer size is already aligned to hardware requirements. */
- uint16_t blocksize = (wCount > 62) ? 1 : 0;
- uint16_t numblocks = wCount / (blocksize ? 32 : 2);
-
- /* There should be no remainder in the above calculation */
- TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/);
-
- /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
- *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10);
+#endif
}
/**
@@ -232,8 +305,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_cnt_reg(__O uint16_t * pdwRe
* @param bAddr Address.
* @retval None
*/
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal |= bAddr;
@@ -241,57 +313,94 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx,
pcd_set_endpoint(USBx, bEpIdx,regVal);
}
-TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x)
-{
- size_t total_word_offset = (((USBx)->BTABLE)>>1) + x;
- total_word_offset *= PMA_STRIDE;
- return &(pma[total_word_offset]);
+TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ return pma32[2*bEpIdx] & 0x0000FFFFu ;
+#else
+ return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u);
+#endif
}
-// Pointers to the PMA table entries (using the ARM address space)
-TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
- return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u);
-}
-TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
- return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u);
+TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ return pma32[2*bEpIdx + 1] & 0x0000FFFFu;
+#else
+ return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u);
+#endif
}
-TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_address_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
- return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u);
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu);
+#else
+ *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr;
+#endif
}
-TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
- return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u);
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu);
+#else
+ *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr;
+#endif
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16);
+#else
__IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
+#endif
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) {
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16);
+#else
__IO uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
+#endif
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
-{
- __IO uint16_t *pdwReg = pcd_ep_tx_cnt_ptr((USBx),(bEpIdx));
- wCount = pcd_aligned_buffer_size(wCount);
- pcd_set_ep_cnt_reg(pdwReg, wCount);
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx,
+ uint32_t blocksize, uint32_t numblocks) {
+ /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
+#ifdef FSDEV_BUS_32BIT
+ (void) USBx;
+ pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26);
+#else
+ __IO uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u);
+ *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10);
+#endif
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount)
-{
- __IO uint16_t *pdwReg = pcd_ep_rx_cnt_ptr((USBx),(bEpIdx));
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount) {
wCount = pcd_aligned_buffer_size(wCount);
- pcd_set_ep_cnt_reg(pdwReg, wCount);
+
+ /* We assume that the buffer size is already aligned to hardware requirements. */
+ uint16_t blocksize = (wCount > 62) ? 1 : 0;
+ uint16_t numblocks = wCount / (blocksize ? 32 : 2);
+
+ /* There should be no remainder in the above calculation */
+ TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/);
+
+ /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
+ pcd_set_ep_blsize_num_blocks(USBx, rxtx_idx, blocksize, numblocks);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) {
+ pcd_set_ep_bufsize(USBx, 2*bEpIdx, wCount);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) {
+ pcd_set_ep_bufsize(USBx, 2*bEpIdx + 1, wCount);
}
/**
@@ -301,8 +410,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_bufsize(USB_TypeDef * USB
* @param wState new state
* @retval None
*/
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPTX_DTOGMASK;
@@ -319,7 +427,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
-} /* pcd_set_ep_tx_status */
+}
/**
* @brief sets the status for rx transfer (bits STAT_TX[1:0])
@@ -329,31 +437,27 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx
* @retval None
*/
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPRX_DTOGMASK;
/* toggle first bit ? */
- if((USB_EPRX_DTOG1 & wState)!= 0U)
- {
+ if((USB_EPRX_DTOG1 & wState)!= 0U) {
regVal ^= USB_EPRX_DTOG1;
}
/* toggle second bit ? */
- if((USB_EPRX_DTOG2 & wState)!= 0U)
- {
+ if((USB_EPRX_DTOG2 & wState)!= 0U) {
regVal ^= USB_EPRX_DTOG2;
}
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
-} /* pcd_set_ep_rx_status */
+}
-TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
return (regVal & USB_EPRX_STAT) >> (12u);
-} /* pcd_get_ep_rx_status */
+}
/**
@@ -362,16 +466,14 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef *
* @param bEpIdx Endpoint Number.
* @retval None
*/
-TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX;
@@ -384,21 +486,16 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32
* @param bEpIdx Endpoint Number.
* @retval None
*/
-
-TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
- if((regVal & USB_EP_DTOG_RX) != 0)
- {
+ if((regVal & USB_EP_DTOG_RX) != 0) {
pcd_rx_dtog(USBx,bEpIdx);
}
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
- if((regVal & USB_EP_DTOG_TX) != 0)
- {
+ if((regVal & USB_EP_DTOG_TX) != 0) {
pcd_tx_dtog(USBx,bEpIdx);
}
}
@@ -409,17 +506,15 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx,
* @param bEpIdx Endpoint Number.
* @retval None
*/
-
-TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal |= USB_EP_KIND;
regVal &= USB_EPREG_MASK;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
-TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx)
-{
+
+TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPKIND_MASK;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c
deleted file mode 100644
index 2fc3adb4f..000000000
--- a/src/portable/st/synopsys/dcd_synopsys.c
+++ /dev/null
@@ -1,1240 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- * Copyright (c) 2020 Jan Duempelmann
- * Copyright (c) 2020 Reinhard Panhuber
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "tusb_option.h"
-
-// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
-// We disable SOF for now until needed later on
-#define USE_SOF 0
-
-#if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \
- defined (STM32F107xB) || defined (STM32F107xC)
-#define STM32F1_SYNOPSYS
-#endif
-
-#if defined (STM32L475xx) || defined (STM32L476xx) || \
- defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \
- defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \
- defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
-#define STM32L4_SYNOPSYS
-#endif
-
-#if CFG_TUD_ENABLED && \
- ( (CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_SYNOPSYS)) || \
- CFG_TUSB_MCU == OPT_MCU_STM32F2 || \
- CFG_TUSB_MCU == OPT_MCU_STM32F4 || \
- CFG_TUSB_MCU == OPT_MCU_STM32F7 || \
- CFG_TUSB_MCU == OPT_MCU_STM32H7 || \
- (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS) || \
- CFG_TUSB_MCU == OPT_MCU_GD32VF103 ) \
- )
-
-// EP_MAX : Max number of bi-directional endpoints including EP0
-// EP_FIFO_SIZE : Size of dedicated USB SRAM
-#if CFG_TUSB_MCU == OPT_MCU_STM32F1
-#include "stm32f1xx.h"
-#define EP_MAX_FS 4
-#define EP_FIFO_SIZE_FS 1280
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F2
-#include "stm32f2xx.h"
-#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS
-#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F4
-#include "stm32f4xx.h"
-#define EP_MAX_FS USB_OTG_FS_MAX_IN_ENDPOINTS
-#define EP_FIFO_SIZE_FS USB_OTG_FS_TOTAL_FIFO_SIZE
-#define EP_MAX_HS USB_OTG_HS_MAX_IN_ENDPOINTS
-#define EP_FIFO_SIZE_HS USB_OTG_HS_TOTAL_FIFO_SIZE
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32H7
-#include "stm32h7xx.h"
-#define EP_MAX_FS 9
-#define EP_FIFO_SIZE_FS 4096
-#define EP_MAX_HS 9
-#define EP_FIFO_SIZE_HS 4096
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F7
-#include "stm32f7xx.h"
-#define EP_MAX_FS 6
-#define EP_FIFO_SIZE_FS 1280
-#define EP_MAX_HS 9
-#define EP_FIFO_SIZE_HS 4096
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L4
-#include "stm32l4xx.h"
-#define EP_MAX_FS 6
-#define EP_FIFO_SIZE_FS 1280
-
-#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103
-#include "synopsys_common.h"
-
-// for remote wakeup delay
-#define __NOP() __asm volatile ("nop")
-
-// These numbers are the same for the whole GD32VF103 family.
-#define OTG_FS_IRQn 86
-#define EP_MAX_FS 4
-#define EP_FIFO_SIZE_FS 1280
-
-// The GD32VF103 is a RISC-V MCU, which implements the ECLIC Core-Local
-// Interrupt Controller by Nuclei. It is nearly API compatible to the
-// NVIC used by ARM MCUs.
-#define ECLIC_INTERRUPT_ENABLE_BASE 0xD2001001UL
-
-#define NVIC_EnableIRQ __eclic_enable_interrupt
-#define NVIC_DisableIRQ __eclic_disable_interrupt
-
-static inline void __eclic_enable_interrupt (uint32_t irq) {
- *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 1;
-}
-
-static inline void __eclic_disable_interrupt (uint32_t irq){
- *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 0;
-}
-
-#else
-#error "Unsupported MCUs"
-#endif
-
-#include "device/dcd.h"
-
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM
-//--------------------------------------------------------------------+
-
-// On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS
-#if TUD_OPT_RHPORT == 0
-#define EP_MAX EP_MAX_FS
-#define EP_FIFO_SIZE EP_FIFO_SIZE_FS
-#define RHPORT_REGS_BASE USB_OTG_FS_PERIPH_BASE
-#define RHPORT_IRQn OTG_FS_IRQn
-
-#else
-#define EP_MAX EP_MAX_HS
-#define EP_FIFO_SIZE EP_FIFO_SIZE_HS
-#define RHPORT_REGS_BASE USB_OTG_HS_PERIPH_BASE
-#define RHPORT_IRQn OTG_HS_IRQn
-
-#endif
-
-#define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) RHPORT_REGS_BASE)
-#define DEVICE_BASE(_port) (USB_OTG_DeviceTypeDef *) (RHPORT_REGS_BASE + USB_OTG_DEVICE_BASE)
-#define OUT_EP_BASE(_port) (USB_OTG_OUTEndpointTypeDef *) (RHPORT_REGS_BASE + USB_OTG_OUT_ENDPOINT_BASE)
-#define IN_EP_BASE(_port) (USB_OTG_INEndpointTypeDef *) (RHPORT_REGS_BASE + USB_OTG_IN_ENDPOINT_BASE)
-#define FIFO_BASE(_port, _x) ((volatile uint32_t *) (RHPORT_REGS_BASE + USB_OTG_FIFO_BASE + (_x) * USB_OTG_FIFO_SIZE))
-
-enum
-{
- DCD_HIGH_SPEED = 0, // Highspeed mode
- DCD_FULL_SPEED_USE_HS = 1, // Full speed in Highspeed port (probably with internal PHY)
- DCD_FULL_SPEED = 3, // Full speed with internal PHY
-};
-
-static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2];
-
-typedef struct {
- uint8_t * buffer;
- tu_fifo_t * ff;
- uint16_t total_len;
- uint16_t max_size;
- uint8_t interval;
-} xfer_ctl_t;
-
-typedef volatile uint32_t * usb_fifo_t;
-
-xfer_ctl_t xfer_status[EP_MAX][2];
-#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir]
-
-// EP0 transfers are limited to 1 packet - larger sizes has to be split
-static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type
-
-// TX FIFO RAM allocation so far in words - RX FIFO size is readily available from usb_otg->GRXFSIZ
-static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs)
-static bool _out_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size)
-
-// Calculate the RX FIFO size according to recommendations from reference manual
-static inline uint16_t calc_rx_ff_size(uint16_t ep_size)
-{
- return 15 + 2*(ep_size/4) + 2*EP_MAX;
-}
-
-static void update_grxfsiz(uint8_t rhport)
-{
- (void) rhport;
-
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
-
- // Determine largest EP size for RX FIFO
- uint16_t max_epsize = 0;
- for (uint8_t epnum = 0; epnum < EP_MAX; epnum++)
- {
- max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size);
- }
-
- // Update size of RX FIFO
- usb_otg->GRXFSIZ = calc_rx_ff_size(max_epsize);
-}
-
-// Setup the control endpoint 0.
-static void bus_reset(uint8_t rhport)
-{
- (void) rhport;
-
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
- USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
-
- tu_memclr(xfer_status, sizeof(xfer_status));
- _out_ep_closed = false;
-
- // clear device address
- dev->DCFG &= ~USB_OTG_DCFG_DAD_Msk;
-
- // 1. NAK for all OUT endpoints
- for(uint8_t n = 0; n < EP_MAX; n++) {
- out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
- }
-
- // 2. Un-mask interrupt bits
- dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos);
- dev->DOEPMSK = USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM;
- dev->DIEPMSK = USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM;
-
- // "USB Data FIFOs" section in reference manual
- // Peripheral FIFO architecture
- //
- // The FIFO is split up in a lower part where the RX FIFO is located and an upper part where the TX FIFOs start.
- // We do this to allow the RX FIFO to grow dynamically which is possible since the free space is located
- // between the RX and TX FIFOs. This is required by ISO OUT EPs which need a bigger FIFO than the standard
- // configuration done below.
- //
- // Dynamically FIFO sizes are of interest only for ISO EPs since all others are usually not opened and closed.
- // All EPs other than ISO are opened as soon as the driver starts up i.e. when the host sends a
- // configure interface command. Hence, all IN EPs other the ISO will be located at the top. IN ISO EPs are usually
- // opened when the host sends an additional command: setInterface. At this point in time
- // the ISO EP will be located next to the free space and can change its size. In case more IN EPs change its size
- // an additional memory
- //
- // --------------- 320 or 1024 ( 1280 or 4096 bytes )
- // | IN FIFO 0 |
- // --------------- (320 or 1024) - 16
- // | IN FIFO 1 |
- // --------------- (320 or 1024) - 16 - x
- // | . . . . |
- // --------------- (320 or 1024) - 16 - x - y - ... - z
- // | IN FIFO MAX |
- // ---------------
- // | FREE |
- // --------------- GRXFSIZ
- // | OUT FIFO |
- // | ( Shared ) |
- // --------------- 0
- //
- // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits):
- // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN
- //
- // - All EP OUT shared a unique OUT FIFO which uses
- // - 13 for setup packets + control words (up to 3 setup packets).
- // - 1 for global NAK (not required/used here).
- // - Largest-EPsize / 4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4) + 1"
- // - 2 for each used OUT endpoint
- //
- // Therefore GRXFSIZ = 13 + 1 + 1 + 2 x (Largest-EPsize/4) + 2 x EPOUTnum
- // - FullSpeed (64 Bytes ): GRXFSIZ = 15 + 2 x 16 + 2 x EP_MAX = 47 + 2 x EP_MAX
- // - Highspeed (512 bytes): GRXFSIZ = 15 + 2 x 128 + 2 x EP_MAX = 271 + 2 x EP_MAX
- //
- // NOTE: Largest-EPsize & EPOUTnum is actual used endpoints in configuration. Since DCD has no knowledge
- // of the overall picture yet. We will use the worst scenario: largest possible + EP_MAX
- //
- // For Isochronous, largest EP size can be 1023/1024 for FS/HS respectively. In addition if multiple ISO
- // are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended. Maybe provide a macro for application to
- // overwrite this.
-
- usb_otg->GRXFSIZ = calc_rx_ff_size(TUD_OPT_HIGH_SPEED ? 512 : 64);
-
- _allocated_fifo_words_tx = 16;
-
- // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word )
- usb_otg->DIEPTXF0_HNPTXFSIZ = (16 << USB_OTG_TX0FD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx);
-
- // Fixed control EP0 size to 64 bytes
- in_ep[0].DIEPCTL &= ~(0x03 << USB_OTG_DIEPCTL_MPSIZ_Pos);
- xfer_status[0][TUSB_DIR_OUT].max_size = xfer_status[0][TUSB_DIR_IN].max_size = 64;
-
- out_ep[0].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos);
-
- usb_otg->GINTMSK |= USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT;
-}
-
-// Set turn-around timeout according to link speed
-extern uint32_t SystemCoreClock;
-static void set_turnaround(USB_OTG_GlobalTypeDef * usb_otg, tusb_speed_t speed)
-{
- usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
-
- if ( speed == TUSB_SPEED_HIGH )
- {
- // Use fixed 0x09 for Highspeed
- usb_otg->GUSBCFG |= (0x09 << USB_OTG_GUSBCFG_TRDT_Pos);
- }
- else
- {
- // Turnaround timeout depends on the MCU clock
- uint32_t turnaround;
-
- if ( SystemCoreClock >= 32000000U )
- turnaround = 0x6U;
- else if ( SystemCoreClock >= 27500000U )
- turnaround = 0x7U;
- else if ( SystemCoreClock >= 24000000U )
- turnaround = 0x8U;
- else if ( SystemCoreClock >= 21800000U )
- turnaround = 0x9U;
- else if ( SystemCoreClock >= 20000000U )
- turnaround = 0xAU;
- else if ( SystemCoreClock >= 18500000U )
- turnaround = 0xBU;
- else if ( SystemCoreClock >= 17200000U )
- turnaround = 0xCU;
- else if ( SystemCoreClock >= 16000000U )
- turnaround = 0xDU;
- else if ( SystemCoreClock >= 15000000U )
- turnaround = 0xEU;
- else
- turnaround = 0xFU;
-
- // Fullspeed depends on MCU clocks, but we will use 0x06 for 32+ Mhz
- usb_otg->GUSBCFG |= (turnaround << USB_OTG_GUSBCFG_TRDT_Pos);
- }
-}
-
-static tusb_speed_t get_speed(uint8_t rhport)
-{
- (void) rhport;
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- uint32_t const enum_spd = (dev->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >> USB_OTG_DSTS_ENUMSPD_Pos;
- return (enum_spd == DCD_HIGH_SPEED) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL;
-}
-
-static void set_speed(uint8_t rhport, tusb_speed_t speed)
-{
- uint32_t bitvalue;
-
- if ( rhport == 1 )
- {
- bitvalue = ((TUSB_SPEED_HIGH == speed) ? DCD_HIGH_SPEED : DCD_FULL_SPEED_USE_HS);
- }
- else
- {
- bitvalue = DCD_FULL_SPEED;
- }
-
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
-
- // Clear and set speed bits
- dev->DCFG &= ~(3 << USB_OTG_DCFG_DSPD_Pos);
- dev->DCFG |= (bitvalue << USB_OTG_DCFG_DSPD_Pos);
-}
-
-#if defined(USB_HS_PHYC)
-static bool USB_HS_PHYCInit(void)
-{
- USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef*) USB_HS_PHYC_CONTROLLER_BASE;
-
- // Enable LDO: Note STM32F72/3xx Reference Manual rev 3 June 2018 incorrectly defined this bit as Disabled !!
- usb_hs_phyc->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE;
-
- // Wait until LDO ready
- while ( 0 == (usb_hs_phyc->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) ) {}
-
- uint32_t phyc_pll = 0;
-
- // TODO Try to get HSE_VALUE from registers instead of depending CFLAGS
- switch ( HSE_VALUE )
- {
- case 12000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ ; break;
- case 12500000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ ; break;
- case 16000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ ; break;
- case 24000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ ; break;
- case 25000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ ; break;
- case 32000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk ; break; // Value not defined in header
- default:
- TU_ASSERT(0);
- }
- usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll;
-
- // Control the tuning interface of the High Speed PHY
- // Use magic value (USB_HS_PHYC_TUNE_VALUE) from ST driver
- usb_hs_phyc->USB_HS_PHYC_TUNE |= 0x00000F13U;
-
- // Enable PLL internal PHY
- usb_hs_phyc->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN;
-
- // Original ST code has 2 ms delay for PLL stabilization.
- // Primitive test shows that more than 10 USB un/replug cycle showed no error with enumeration
-
- return true;
-}
-#endif
-
-static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes)
-{
- (void) rhport;
-
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
- USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
-
- // EP0 is limited to one packet each xfer
- // We use multiple transaction of xfer->max_size length to get a whole transfer done
- if(epnum == 0) {
- xfer_ctl_t * const xfer = XFER_CTL_BASE(epnum, dir);
- total_bytes = tu_min16(ep0_pending[dir], xfer->max_size);
- ep0_pending[dir] -= total_bytes;
- }
-
- // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here.
- if(dir == TUSB_DIR_IN) {
- // A full IN transfer (multiple packets, possibly) triggers XFRC.
- in_ep[epnum].DIEPTSIZ = (num_packets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) |
- ((total_bytes << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) & USB_OTG_DIEPTSIZ_XFRSIZ_Msk);
-
- in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
- // For ISO endpoint set correct odd/even bit for next frame.
- if ((in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP) == USB_OTG_DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1)
- {
- // Take odd/even bit from frame counter.
- uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos));
- in_ep[epnum].DIEPCTL |= (odd_frame_now ? USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk : USB_OTG_DIEPCTL_SODDFRM_Msk);
- }
- // Enable fifo empty interrupt only if there are something to put in the fifo.
- if(total_bytes != 0) {
- dev->DIEPEMPMSK |= (1 << epnum);
- }
- } else {
- // A full OUT transfer (multiple packets, possibly) triggers XFRC.
- out_ep[epnum].DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT_Msk | USB_OTG_DOEPTSIZ_XFRSIZ);
- out_ep[epnum].DOEPTSIZ |= (num_packets << USB_OTG_DOEPTSIZ_PKTCNT_Pos) |
- ((total_bytes << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) & USB_OTG_DOEPTSIZ_XFRSIZ_Msk);
-
- out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
- if ((out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP) == USB_OTG_DOEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1)
- {
- // Take odd/even bit from frame counter.
- uint32_t const odd_frame_now = (dev->DSTS & (1u << USB_OTG_DSTS_FNSOF_Pos));
- out_ep[epnum].DOEPCTL |= (odd_frame_now ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk : USB_OTG_DOEPCTL_SODDFRM_Msk);
- }
- }
-}
-
-/*------------------------------------------------------------------*/
-/* Controller API
- *------------------------------------------------------------------*/
-void dcd_init (uint8_t rhport)
-{
- // Programming model begins in the last section of the chapter on the USB
- // peripheral in each Reference Manual.
-
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
-
- // No HNP/SRP (no OTG support), program timeout later.
- if ( rhport == 1 )
- {
- // On selected MCUs HS port1 can be used with external PHY via ULPI interface
-#if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED
- // deactivate internal PHY
- usb_otg->GCCFG &= ~USB_OTG_GCCFG_PWRDWN;
-
- // Init The UTMI Interface
- usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL);
-
- // Select default internal VBUS Indicator and Drive for ULPI
- usb_otg->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
-#else
- usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
-#endif
-
-#if defined(USB_HS_PHYC)
- // Highspeed with embedded UTMI PHYC
-
- // Select UTMI Interface
- usb_otg->GUSBCFG &= ~USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
- usb_otg->GCCFG |= USB_OTG_GCCFG_PHYHSEN;
-
- // Enables control of a High Speed USB PHY
- USB_HS_PHYCInit();
-#endif
- } else
- {
- // Enable internal PHY
- usb_otg->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
- }
-
- // Reset core after selecting PHY
- // Wait AHB IDLE, reset then wait until it is cleared
- while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U) {}
- usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
- while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {}
-
- // Restart PHY clock
- *((volatile uint32_t *)(RHPORT_REGS_BASE + USB_OTG_PCGCCTL_BASE)) = 0;
-
- // Clear all interrupts
- usb_otg->GINTSTS |= usb_otg->GINTSTS;
-
- // Required as part of core initialization.
- // TODO: How should mode mismatch be handled? It will cause
- // the core to stop working/require reset.
- usb_otg->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM;
-
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
-
- // If USB host misbehaves during status portion of control xfer
- // (non zero-length packet), send STALL back and discard.
- dev->DCFG |= USB_OTG_DCFG_NZLSOHSK;
-
- set_speed(rhport, TUD_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL);
-
- // Enable internal USB transceiver, unless using HS core (port 1) with external PHY.
- if (!(rhport == 1 && (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HIGH_SPEED))) usb_otg->GCCFG |= USB_OTG_GCCFG_PWRDWN;
-
- usb_otg->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM |
- USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM |
- USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0);
-
- // Enable global interrupt
- usb_otg->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
-
- dcd_connect(rhport);
-}
-
-void dcd_int_enable (uint8_t rhport)
-{
- (void) rhport;
- NVIC_EnableIRQ(RHPORT_IRQn);
-}
-
-void dcd_int_disable (uint8_t rhport)
-{
- (void) rhport;
- NVIC_DisableIRQ(RHPORT_IRQn);
-}
-
-void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
-{
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- dev->DCFG = (dev->DCFG & ~USB_OTG_DCFG_DAD_Msk) | (dev_addr << USB_OTG_DCFG_DAD_Pos);
-
- // Response with status after changing device address
- dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
-}
-
-static void remote_wakeup_delay(void)
-{
- // try to delay for 1 ms
- uint32_t count = SystemCoreClock / 1000;
- while ( count-- )
- {
- __NOP();
- }
-}
-
-void dcd_remote_wakeup(uint8_t rhport)
-{
- (void) rhport;
-
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
-
- // set remote wakeup
- dev->DCTL |= USB_OTG_DCTL_RWUSIG;
-
- // enable SOF to detect bus resume
- usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF;
- usb_otg->GINTMSK |= USB_OTG_GINTMSK_SOFM;
-
- // Per specs: remote wakeup signal bit must be clear within 1-15ms
- remote_wakeup_delay();
-
- dev->DCTL &= ~USB_OTG_DCTL_RWUSIG;
-}
-
-void dcd_connect(uint8_t rhport)
-{
- (void) rhport;
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- dev->DCTL &= ~USB_OTG_DCTL_SDIS;
-}
-
-void dcd_disconnect(uint8_t rhport)
-{
- (void) rhport;
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- dev->DCTL |= USB_OTG_DCTL_SDIS;
-}
-
-void dcd_sof_enable(uint8_t rhport, bool en)
-{
- (void) rhport;
- (void) en;
-
- // TODO implement later
-}
-
-/*------------------------------------------------------------------*/
-/* DCD Endpoint port
- *------------------------------------------------------------------*/
-
-bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
-{
- (void) rhport;
-
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
- USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
-
- uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
- uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
-
- TU_ASSERT(epnum < EP_MAX);
-
- xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
- xfer->max_size = tu_edpt_packet_size(desc_edpt);
- xfer->interval = desc_edpt->bInterval;
-
- uint16_t const fifo_size = (xfer->max_size + 3) / 4; // Round up to next full word
-
- if(dir == TUSB_DIR_OUT)
- {
- // Calculate required size of RX FIFO
- uint16_t const sz = calc_rx_ff_size(4*fifo_size);
-
- // If size_rx needs to be extended check if possible and if so enlarge it
- if (usb_otg->GRXFSIZ < sz)
- {
- TU_ASSERT(sz + _allocated_fifo_words_tx <= EP_FIFO_SIZE/4);
-
- // Enlarge RX FIFO
- usb_otg->GRXFSIZ = sz;
- }
-
- out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) |
- (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) |
- (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) |
- (xfer->max_size << USB_OTG_DOEPCTL_MPSIZ_Pos);
-
- dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));
- }
- else
- {
- // "USB Data FIFOs" section in reference manual
- // Peripheral FIFO architecture
- //
- // --------------- 320 or 1024 ( 1280 or 4096 bytes )
- // | IN FIFO 0 |
- // --------------- (320 or 1024) - 16
- // | IN FIFO 1 |
- // --------------- (320 or 1024) - 16 - x
- // | . . . . |
- // --------------- (320 or 1024) - 16 - x - y - ... - z
- // | IN FIFO MAX |
- // ---------------
- // | FREE |
- // --------------- GRXFSIZ
- // | OUT FIFO |
- // | ( Shared ) |
- // --------------- 0
- //
- // In FIFO is allocated by following rules:
- // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
-
- // Check if free space is available
- TU_ASSERT(_allocated_fifo_words_tx + fifo_size + usb_otg->GRXFSIZ <= EP_FIFO_SIZE/4);
-
- _allocated_fifo_words_tx += fifo_size;
-
- TU_LOG(2, " Allocated %u bytes at offset %u", fifo_size*4, EP_FIFO_SIZE-_allocated_fifo_words_tx*4);
-
- // DIEPTXF starts at FIFO #1.
- // Both TXFD and TXSA are in unit of 32-bit words.
- usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx);
-
- in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) |
- (epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) |
- (desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) |
- (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DIEPCTL_SD0PID_SEVNFRM : 0) |
- (xfer->max_size << USB_OTG_DIEPCTL_MPSIZ_Pos);
-
- dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum));
- }
-
- return true;
-}
-
-// Close all non-control endpoints, cancel all pending transfers if any.
-void dcd_edpt_close_all (uint8_t rhport)
-{
- (void) rhport;
-
-// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
- USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
-
- // Disable non-control interrupt
- dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos);
-
- for(uint8_t n = 1; n < EP_MAX; n++)
- {
- // disable OUT endpoint
- out_ep[n].DOEPCTL = 0;
- xfer_status[n][TUSB_DIR_OUT].max_size = 0;
-
- // disable IN endpoint
- in_ep[n].DIEPCTL = 0;
- xfer_status[n][TUSB_DIR_IN].max_size = 0;
- }
-
- // reset allocated fifo IN
- _allocated_fifo_words_tx = 16;
-}
-
-bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
- xfer->buffer = buffer;
- xfer->ff = NULL;
- xfer->total_len = total_bytes;
-
- // EP0 can only handle one packet
- if(epnum == 0) {
- ep0_pending[dir] = total_bytes;
- // Schedule the first transaction for EP0 transfer
- edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]);
- return true;
- }
-
- uint16_t num_packets = (total_bytes / xfer->max_size);
- uint16_t const short_packet_size = total_bytes % xfer->max_size;
-
- // Zero-size packet is special case.
- if(short_packet_size > 0 || (total_bytes == 0)) {
- num_packets++;
- }
-
- // Schedule packets to be sent within interrupt
- edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes);
-
- return true;
-}
-
-// The number of bytes has to be given explicitly to allow more flexible control of how many
-// bytes should be written and second to keep the return value free to give back a boolean
-// success message. If total_bytes is too big, the FIFO will copy only what is available
-// into the USB buffer!
-bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
-{
- // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
- TU_ASSERT(ff->item_size == 1);
-
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
- xfer->buffer = NULL;
- xfer->ff = ff;
- xfer->total_len = total_bytes;
-
- uint16_t num_packets = (total_bytes / xfer->max_size);
- uint16_t const short_packet_size = total_bytes % xfer->max_size;
-
- // Zero-size packet is special case.
- if(short_packet_size > 0 || (total_bytes == 0)) num_packets++;
-
- // Schedule packets to be sent within interrupt
- edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes);
-
- return true;
-}
-
-static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall)
-{
- (void) rhport;
-
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
- USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
-
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- if(dir == TUSB_DIR_IN) {
- // Only disable currently enabled non-control endpoint
- if ( (epnum == 0) || !(in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPENA) ){
- in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SNAK | (stall ? USB_OTG_DIEPCTL_STALL : 0);
- } else {
- // Stop transmitting packets and NAK IN xfers.
- in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
- while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_INEPNE) == 0);
-
- // Disable the endpoint.
- in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_EPDIS | (stall ? USB_OTG_DIEPCTL_STALL : 0);
- while((in_ep[epnum].DIEPINT & USB_OTG_DIEPINT_EPDISD_Msk) == 0);
- in_ep[epnum].DIEPINT = USB_OTG_DIEPINT_EPDISD;
- }
-
- // Flush the FIFO, and wait until we have confirmed it cleared.
- usb_otg->GRSTCTL |= (epnum << USB_OTG_GRSTCTL_TXFNUM_Pos);
- usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_TXFFLSH;
- while((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH_Msk) != 0);
- } else {
- // Only disable currently enabled non-control endpoint
- if ( (epnum == 0) || !(out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPENA) ){
- out_ep[epnum].DOEPCTL |= stall ? USB_OTG_DOEPCTL_STALL : 0;
- } else {
- // Asserting GONAK is required to STALL an OUT endpoint.
- // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt
- // anyway, and it can't be cleared by user code. If this while loop never
- // finishes, we have bigger problems than just the stack.
- dev->DCTL |= USB_OTG_DCTL_SGONAK;
- while((usb_otg->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF_Msk) == 0);
-
- // Ditto here- disable the endpoint.
- out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_EPDIS | (stall ? USB_OTG_DOEPCTL_STALL : 0);
- while((out_ep[epnum].DOEPINT & USB_OTG_DOEPINT_EPDISD_Msk) == 0);
- out_ep[epnum].DOEPINT = USB_OTG_DOEPINT_EPDISD;
-
- // Allow other OUT endpoints to keep receiving.
- dev->DCTL |= USB_OTG_DCTL_CGONAK;
- }
- }
-}
-
-/**
- * Close an endpoint.
- */
-void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
-{
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
-
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- dcd_edpt_disable(rhport, ep_addr, false);
-
- // Update max_size
- xfer_status[epnum][dir].max_size = 0; // max_size = 0 marks a disabled EP - required for changing FIFO allocation
-
- if (dir == TUSB_DIR_IN)
- {
- uint16_t const fifo_size = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXFD_Msk) >> USB_OTG_DIEPTXF_INEPTXFD_Pos;
- uint16_t const fifo_start = (usb_otg->DIEPTXF[epnum - 1] & USB_OTG_DIEPTXF_INEPTXSA_Msk) >> USB_OTG_DIEPTXF_INEPTXSA_Pos;
- // For now only the last opened endpoint can be closed without fuss.
- TU_ASSERT(fifo_start == EP_FIFO_SIZE/4 - _allocated_fifo_words_tx,);
- _allocated_fifo_words_tx -= fifo_size;
- }
- else
- {
- _out_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty
- }
-}
-
-void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
-{
- dcd_edpt_disable(rhport, ep_addr, true);
-}
-
-void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
-{
- (void) rhport;
-
- USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
- USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
-
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- // Clear stall and reset data toggle
- if(dir == TUSB_DIR_IN) {
- in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
- in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
- } else {
- out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
- out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
- }
-}
-
-/*------------------------------------------------------------------*/
-
-// Read a single data packet from receive FIFO
-static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len)
-{
- (void) rhport;
-
- usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0);
-
- // Reading full available 32 bit words from fifo
- uint16_t full_words = len >> 2;
- for(uint16_t i = 0; i < full_words; i++) {
- uint32_t tmp = *rx_fifo;
- dst[0] = tmp & 0x000000FF;
- dst[1] = (tmp & 0x0000FF00) >> 8;
- dst[2] = (tmp & 0x00FF0000) >> 16;
- dst[3] = (tmp & 0xFF000000) >> 24;
- dst += 4;
- }
-
- // Read the remaining 1-3 bytes from fifo
- uint8_t bytes_rem = len & 0x03;
- if(bytes_rem != 0) {
- uint32_t tmp = *rx_fifo;
- dst[0] = tmp & 0x000000FF;
- if(bytes_rem > 1) {
- dst[1] = (tmp & 0x0000FF00) >> 8;
- }
- if(bytes_rem > 2) {
- dst[2] = (tmp & 0x00FF0000) >> 16;
- }
- }
-}
-
-// Write a single data packet to EPIN FIFO
-static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t * src, uint16_t len)
-{
- (void) rhport;
-
- usb_fifo_t tx_fifo = FIFO_BASE(rhport, fifo_num);
-
- // Pushing full available 32 bit words to fifo
- uint16_t full_words = len >> 2;
- for(uint16_t i = 0; i < full_words; i++){
- *tx_fifo = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
- src += 4;
- }
-
- // Write the remaining 1-3 bytes into fifo
- uint8_t bytes_rem = len & 0x03;
- if(bytes_rem){
- uint32_t tmp_word = 0;
- tmp_word |= src[0];
- if(bytes_rem > 1){
- tmp_word |= src[1] << 8;
- }
- if(bytes_rem > 2){
- tmp_word |= src[2] << 16;
- }
- *tx_fifo = tmp_word;
- }
-}
-
-static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ep) {
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
- usb_fifo_t rx_fifo = FIFO_BASE(rhport, 0);
-
- // Pop control word off FIFO
- uint32_t ctl_word = usb_otg->GRXSTSP;
- uint8_t pktsts = (ctl_word & USB_OTG_GRXSTSP_PKTSTS_Msk) >> USB_OTG_GRXSTSP_PKTSTS_Pos;
- uint8_t epnum = (ctl_word & USB_OTG_GRXSTSP_EPNUM_Msk) >> USB_OTG_GRXSTSP_EPNUM_Pos;
- uint16_t bcnt = (ctl_word & USB_OTG_GRXSTSP_BCNT_Msk) >> USB_OTG_GRXSTSP_BCNT_Pos;
-
- switch(pktsts) {
- case 0x01: // Global OUT NAK (Interrupt)
- break;
-
- case 0x02: // Out packet recvd
- {
- xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
-
- // Read packet off RxFIFO
- if (xfer->ff)
- {
- // Ring buffer
- tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *)(uintptr_t) rx_fifo, bcnt);
- }
- else
- {
- // Linear buffer
- read_fifo_packet(rhport, xfer->buffer, bcnt);
-
- // Increment pointer to xfer data
- xfer->buffer += bcnt;
- }
-
- // Truncate transfer length in case of short packet
- if(bcnt < xfer->max_size) {
- xfer->total_len -= (out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DOEPTSIZ_XFRSIZ_Pos;
- if(epnum == 0) {
- xfer->total_len -= ep0_pending[TUSB_DIR_OUT];
- ep0_pending[TUSB_DIR_OUT] = 0;
- }
- }
- }
- break;
-
- case 0x03: // Out packet done (Interrupt)
- break;
-
- case 0x04: // Setup packet done (Interrupt)
- out_ep[epnum].DOEPTSIZ |= (3 << USB_OTG_DOEPTSIZ_STUPCNT_Pos);
- break;
-
- case 0x06: // Setup packet recvd
- // We can receive up to three setup packets in succession, but
- // only the last one is valid.
- _setup_packet[0] = (* rx_fifo);
- _setup_packet[1] = (* rx_fifo);
- break;
-
- default: // Invalid
- TU_BREAKPOINT();
- break;
- }
-}
-
-static void handle_epout_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OTG_OUTEndpointTypeDef * out_ep) {
- // DAINT for a given EP clears when DOEPINTx is cleared.
- // OEPINT will be cleared when DAINT's out bits are cleared.
- for(uint8_t n = 0; n < EP_MAX; n++) {
- xfer_ctl_t * xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT);
-
- if(dev->DAINT & (1 << (USB_OTG_DAINT_OEPINT_Pos + n))) {
- // SETUP packet Setup Phase done.
- if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_STUP) {
- out_ep[n].DOEPINT = USB_OTG_DOEPINT_STUP;
- dcd_event_setup_received(rhport, (uint8_t*) &_setup_packet[0], true);
- }
-
- // OUT XFER complete
- if(out_ep[n].DOEPINT & USB_OTG_DOEPINT_XFRC) {
- out_ep[n].DOEPINT = USB_OTG_DOEPINT_XFRC;
-
- // EP0 can only handle one packet
- if((n == 0) && ep0_pending[TUSB_DIR_OUT]) {
- // Schedule another packet to be received.
- edpt_schedule_packets(rhport, n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]);
- } else {
- dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true);
- }
- }
- }
- }
-}
-
-static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OTG_INEndpointTypeDef * in_ep) {
- // DAINT for a given EP clears when DIEPINTx is cleared.
- // IEPINT will be cleared when DAINT's out bits are cleared.
- for ( uint8_t n = 0; n < EP_MAX; n++ )
- {
- xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_IN);
-
- if ( dev->DAINT & (1 << (USB_OTG_DAINT_IEPINT_Pos + n)) )
- {
- // IN XFER complete (entire xfer).
- if ( in_ep[n].DIEPINT & USB_OTG_DIEPINT_XFRC )
- {
- in_ep[n].DIEPINT = USB_OTG_DIEPINT_XFRC;
-
- // EP0 can only handle one packet
- if((n == 0) && ep0_pending[TUSB_DIR_IN]) {
- // Schedule another packet to be transmitted.
- edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]);
- } else {
- dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
- }
- }
-
- // XFER FIFO empty
- if ( (in_ep[n].DIEPINT & USB_OTG_DIEPINT_TXFE) && (dev->DIEPEMPMSK & (1 << n)) )
- {
- // DIEPINT's TXFE bit is read-only, software cannot clear it.
- // It will only be cleared by hardware when written bytes is more than
- // - 64 bytes or
- // - Half of TX FIFO size (configured by DIEPTXF)
-
- uint16_t remaining_packets = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_PKTCNT_Msk) >> USB_OTG_DIEPTSIZ_PKTCNT_Pos;
-
- // Process every single packet (only whole packets can be written to fifo)
- for(uint16_t i = 0; i < remaining_packets; i++)
- {
- uint16_t const remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos;
-
- // Packet can not be larger than ep max size
- uint16_t const packet_size = tu_min16(remaining_bytes, xfer->max_size);
-
- // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current
- // EP has to be checked if the buffer can take another WHOLE packet
- if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)) break;
-
- // Push packet to Tx-FIFO
- if (xfer->ff)
- {
- usb_fifo_t tx_fifo = FIFO_BASE(rhport, n);
- tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *)(uintptr_t) tx_fifo, packet_size);
- }
- else
- {
- write_fifo_packet(rhport, n, xfer->buffer, packet_size);
-
- // Increment pointer to xfer data
- xfer->buffer += packet_size;
- }
- }
-
- // Turn off TXFE if all bytes are written.
- if (((in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos) == 0)
- {
- dev->DIEPEMPMSK &= ~(1 << n);
- }
- }
- }
- }
-}
-
-void dcd_int_handler(uint8_t rhport)
-{
- USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
- USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
- USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
-
- uint32_t const int_status = usb_otg->GINTSTS & usb_otg->GINTMSK;
-
- if(int_status & USB_OTG_GINTSTS_USBRST)
- {
- // USBRST is start of reset.
- usb_otg->GINTSTS = USB_OTG_GINTSTS_USBRST;
- bus_reset(rhport);
- }
-
- if(int_status & USB_OTG_GINTSTS_ENUMDNE)
- {
- // ENUMDNE is the end of reset where speed of the link is detected
-
- usb_otg->GINTSTS = USB_OTG_GINTSTS_ENUMDNE;
-
- tusb_speed_t const speed = get_speed(rhport);
-
- set_turnaround(usb_otg, speed);
- dcd_event_bus_reset(rhport, speed, true);
- }
-
- if(int_status & USB_OTG_GINTSTS_USBSUSP)
- {
- usb_otg->GINTSTS = USB_OTG_GINTSTS_USBSUSP;
- dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
- }
-
- if(int_status & USB_OTG_GINTSTS_WKUINT)
- {
- usb_otg->GINTSTS = USB_OTG_GINTSTS_WKUINT;
- dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
- }
-
- // TODO check USB_OTG_GINTSTS_DISCINT for disconnect detection
- // if(int_status & USB_OTG_GINTSTS_DISCINT)
-
- if(int_status & USB_OTG_GINTSTS_OTGINT)
- {
- // OTG INT bit is read-only
- uint32_t const otg_int = usb_otg->GOTGINT;
-
- if (otg_int & USB_OTG_GOTGINT_SEDET)
- {
- dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
- }
-
- usb_otg->GOTGINT = otg_int;
- }
-
- if(int_status & USB_OTG_GINTSTS_SOF)
- {
- usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF;
-
- // Disable SOF interrupt since currently only used for remote wakeup detection
- usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_SOFM;
-
- dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
- }
-
- // RxFIFO non-empty interrupt handling.
- if(int_status & USB_OTG_GINTSTS_RXFLVL)
- {
- // RXFLVL bit is read-only
-
- // Mask out RXFLVL while reading data from FIFO
- usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM;
-
- // Loop until all available packets were handled
- do
- {
- handle_rxflvl_ints(rhport, out_ep);
- } while(usb_otg->GINTSTS & USB_OTG_GINTSTS_RXFLVL);
-
- // Manage RX FIFO size
- if (_out_ep_closed)
- {
- update_grxfsiz(rhport);
-
- // Disable flag
- _out_ep_closed = false;
- }
-
- usb_otg->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
- }
-
- // OUT endpoint interrupt handling.
- if(int_status & USB_OTG_GINTSTS_OEPINT)
- {
- // OEPINT is read-only
- handle_epout_ints(rhport, dev, out_ep);
- }
-
- // IN endpoint interrupt handling.
- if(int_status & USB_OTG_GINTSTS_IEPINT)
- {
- // IEPINT bit read-only
- handle_epin_ints(rhport, dev, in_ep);
- }
-
- // // Check for Incomplete isochronous IN transfer
- // if(int_status & USB_OTG_GINTSTS_IISOIXFR) {
- // printf(" IISOIXFR!\r\n");
- //// TU_LOG2(" IISOIXFR!\r\n");
- // }
-}
-
-#endif
diff --git a/src/portable/st/synopsys/synopsys_common.h b/src/portable/st/synopsys/synopsys_common.h
deleted file mode 100644
index ce3195b23..000000000
--- a/src/portable/st/synopsys/synopsys_common.h
+++ /dev/null
@@ -1,1465 +0,0 @@
-/**
- ******************************************************************************
- * @file synopsys_common.h
- * @author MCD Application Team
- * @brief CMSIS Cortex-M3 Device USB OTG peripheral Header File.
- * This file contains the USB OTG peripheral register's definitions, bits
- * definitions and memory mapping for STM32F1xx devices.
- *
- * This file contains:
- * - Data structures and the address mapping for the USB OTG peripheral
- * - The Peripheral's registers declarations and bits definition
- * - Macros to access the peripheral's registers hardware
- *
- ******************************************************************************
- * @attention
- *
- * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under BSD 3-Clause license,
- * the "License"; You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- ******************************************************************************
- */
-
-#include "stdint.h"
-
-#pragma once
-
-#ifdef __cplusplus
- #define __I volatile
-#else
- #define __I volatile const
-#endif
-#define __O volatile
-#define __IO volatile
-#define __IM volatile const
-#define __OM volatile
-#define __IOM volatile
-
-/**
- * @brief __USB_OTG_Core_register
- */
-
-typedef struct
-{
- __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register Address offset: 000h */
- __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register Address offset: 004h */
- __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register Address offset: 008h */
- __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register Address offset: 00Ch */
- __IO uint32_t GRSTCTL; /*!< Core Reset Register Address offset: 010h */
- __IO uint32_t GINTSTS; /*!< Core Interrupt Register Address offset: 014h */
- __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register Address offset: 018h */
- __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register Address offset: 01Ch */
- __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register Address offset: 020h */
- __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register Address offset: 024h */
- __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register Address offset: 028h */
- __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg Address offset: 02Ch */
- uint32_t Reserved30[2]; /*!< Reserved 030h*/
- __IO uint32_t GCCFG; /*!< General Purpose IO Register Address offset: 038h */
- __IO uint32_t CID; /*!< User ID Register Address offset: 03Ch */
- uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */
- __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg Address offset: 100h */
- __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO Address offset: 0x104 */
-} USB_OTG_GlobalTypeDef;
-
-/**
- * @brief __device_Registers
- */
-
-typedef struct
-{
- __IO uint32_t DCFG; /*!< dev Configuration Register Address offset: 800h*/
- __IO uint32_t DCTL; /*!< dev Control Register Address offset: 804h*/
- __IO uint32_t DSTS; /*!< dev Status Register (RO) Address offset: 808h*/
- uint32_t Reserved0C; /*!< Reserved 80Ch*/
- __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask Address offset: 810h*/
- __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask Address offset: 814h*/
- __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg Address offset: 818h*/
- __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask Address offset: 81Ch*/
- uint32_t Reserved20; /*!< Reserved 820h*/
- uint32_t Reserved9; /*!< Reserved 824h*/
- __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register Address offset: 828h*/
- __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register Address offset: 82Ch*/
- __IO uint32_t DTHRCTL; /*!< dev thr Address offset: 830h*/
- __IO uint32_t DIEPEMPMSK; /*!< dev empty msk Address offset: 834h*/
- __IO uint32_t DEACHINT; /*!< dedicated EP interrupt Address offset: 838h*/
- __IO uint32_t DEACHMSK; /*!< dedicated EP msk Address offset: 83Ch*/
- uint32_t Reserved40; /*!< dedicated EP mask Address offset: 840h*/
- __IO uint32_t DINEP1MSK; /*!< dedicated EP mask Address offset: 844h*/
- uint32_t Reserved44[15]; /*!< Reserved 844-87Ch*/
- __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk Address offset: 884h*/
-} USB_OTG_DeviceTypeDef;
-
-/**
- * @brief __IN_Endpoint-Specific_Register
- */
-
-typedef struct
-{
- __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/
- uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h*/
- __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/
- uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch*/
- __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/
- __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/
- __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/
- uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/
-} USB_OTG_INEndpointTypeDef;
-
-/**
- * @brief __OUT_Endpoint-Specific_Registers
- */
-
-typedef struct
-{
- __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/
- uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h*/
- __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/
- uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch*/
- __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/
- __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/
- uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/
-} USB_OTG_OUTEndpointTypeDef;
-
-/**
- * @brief __Host_Mode_Register_Structures
- */
-
-typedef struct
-{
- __IO uint32_t HCFG; /*!< Host Configuration Register 400h*/
- __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h*/
- __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h*/
- uint32_t Reserved40C; /*!< Reserved 40Ch*/
- __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h*/
- __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h*/
- __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h*/
-} USB_OTG_HostTypeDef;
-
-/**
- * @brief __Host_Channel_Specific_Registers
- */
-
-typedef struct
-{
- __IO uint32_t HCCHAR;
- __IO uint32_t HCSPLT;
- __IO uint32_t HCINT;
- __IO uint32_t HCINTMSK;
- __IO uint32_t HCTSIZ;
- __IO uint32_t HCDMA;
- uint32_t Reserved[2];
-} USB_OTG_HostChannelTypeDef;
-
-/*!< USB registers base address */
-#define USB_OTG_FS_PERIPH_BASE 0x50000000UL
-
-#define USB_OTG_GLOBAL_BASE 0x00000000UL
-#define USB_OTG_DEVICE_BASE 0x00000800UL
-#define USB_OTG_IN_ENDPOINT_BASE 0x00000900UL
-#define USB_OTG_OUT_ENDPOINT_BASE 0x00000B00UL
-#define USB_OTG_EP_REG_SIZE 0x00000020UL
-#define USB_OTG_HOST_BASE 0x00000400UL
-#define USB_OTG_HOST_PORT_BASE 0x00000440UL
-#define USB_OTG_HOST_CHANNEL_BASE 0x00000500UL
-#define USB_OTG_HOST_CHANNEL_SIZE 0x00000020UL
-#define USB_OTG_PCGCCTL_BASE 0x00000E00UL
-#define USB_OTG_FIFO_BASE 0x00001000UL
-#define USB_OTG_FIFO_SIZE 0x00001000UL
-
-/******************************************************************************/
-/* */
-/* USB_OTG */
-/* */
-/******************************************************************************/
-/******************** Bit definition for USB_OTG_GOTGCTL register ***********/
-#define USB_OTG_GOTGCTL_SRQSCS_Pos (0U)
-#define USB_OTG_GOTGCTL_SRQSCS_Msk (0x1UL << USB_OTG_GOTGCTL_SRQSCS_Pos) /*!< 0x00000001 */
-#define USB_OTG_GOTGCTL_SRQSCS USB_OTG_GOTGCTL_SRQSCS_Msk /*!< Session request success */
-#define USB_OTG_GOTGCTL_SRQ_Pos (1U)
-#define USB_OTG_GOTGCTL_SRQ_Msk (0x1UL << USB_OTG_GOTGCTL_SRQ_Pos) /*!< 0x00000002 */
-#define USB_OTG_GOTGCTL_SRQ USB_OTG_GOTGCTL_SRQ_Msk /*!< Session request */
-#define USB_OTG_GOTGCTL_HNGSCS_Pos (8U)
-#define USB_OTG_GOTGCTL_HNGSCS_Msk (0x1UL << USB_OTG_GOTGCTL_HNGSCS_Pos) /*!< 0x00000100 */
-#define USB_OTG_GOTGCTL_HNGSCS USB_OTG_GOTGCTL_HNGSCS_Msk /*!< Host set HNP enable */
-#define USB_OTG_GOTGCTL_HNPRQ_Pos (9U)
-#define USB_OTG_GOTGCTL_HNPRQ_Msk (0x1UL << USB_OTG_GOTGCTL_HNPRQ_Pos) /*!< 0x00000200 */
-#define USB_OTG_GOTGCTL_HNPRQ USB_OTG_GOTGCTL_HNPRQ_Msk /*!< HNP request */
-#define USB_OTG_GOTGCTL_HSHNPEN_Pos (10U)
-#define USB_OTG_GOTGCTL_HSHNPEN_Msk (0x1UL << USB_OTG_GOTGCTL_HSHNPEN_Pos) /*!< 0x00000400 */
-#define USB_OTG_GOTGCTL_HSHNPEN USB_OTG_GOTGCTL_HSHNPEN_Msk /*!< Host set HNP enable */
-#define USB_OTG_GOTGCTL_DHNPEN_Pos (11U)
-#define USB_OTG_GOTGCTL_DHNPEN_Msk (0x1UL << USB_OTG_GOTGCTL_DHNPEN_Pos) /*!< 0x00000800 */
-#define USB_OTG_GOTGCTL_DHNPEN USB_OTG_GOTGCTL_DHNPEN_Msk /*!< Device HNP enabled */
-#define USB_OTG_GOTGCTL_CIDSTS_Pos (16U)
-#define USB_OTG_GOTGCTL_CIDSTS_Msk (0x1UL << USB_OTG_GOTGCTL_CIDSTS_Pos) /*!< 0x00010000 */
-#define USB_OTG_GOTGCTL_CIDSTS USB_OTG_GOTGCTL_CIDSTS_Msk /*!< Connector ID status */
-#define USB_OTG_GOTGCTL_DBCT_Pos (17U)
-#define USB_OTG_GOTGCTL_DBCT_Msk (0x1UL << USB_OTG_GOTGCTL_DBCT_Pos) /*!< 0x00020000 */
-#define USB_OTG_GOTGCTL_DBCT USB_OTG_GOTGCTL_DBCT_Msk /*!< Long/short debounce time */
-#define USB_OTG_GOTGCTL_ASVLD_Pos (18U)
-#define USB_OTG_GOTGCTL_ASVLD_Msk (0x1UL << USB_OTG_GOTGCTL_ASVLD_Pos) /*!< 0x00040000 */
-#define USB_OTG_GOTGCTL_ASVLD USB_OTG_GOTGCTL_ASVLD_Msk /*!< A-session valid */
-#define USB_OTG_GOTGCTL_BSVLD_Pos (19U)
-#define USB_OTG_GOTGCTL_BSVLD_Msk (0x1UL << USB_OTG_GOTGCTL_BSVLD_Pos) /*!< 0x00080000 */
-#define USB_OTG_GOTGCTL_BSVLD USB_OTG_GOTGCTL_BSVLD_Msk /*!< B-session valid */
-
-/******************** Bit definition for USB_OTG_HCFG register ********************/
-
-#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_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 */
-
-/******************** Bit definition for USB_OTG_DCFG register ********************/
-
-#define USB_OTG_DCFG_DSPD_Pos (0U)
-#define USB_OTG_DCFG_DSPD_Msk (0x3UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000003 */
-#define USB_OTG_DCFG_DSPD USB_OTG_DCFG_DSPD_Msk /*!< Device speed */
-#define USB_OTG_DCFG_DSPD_0 (0x1UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000001 */
-#define USB_OTG_DCFG_DSPD_1 (0x2UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000002 */
-#define USB_OTG_DCFG_NZLSOHSK_Pos (2U)
-#define USB_OTG_DCFG_NZLSOHSK_Msk (0x1UL << USB_OTG_DCFG_NZLSOHSK_Pos) /*!< 0x00000004 */
-#define USB_OTG_DCFG_NZLSOHSK USB_OTG_DCFG_NZLSOHSK_Msk /*!< Nonzero-length status OUT handshake */
-
-#define USB_OTG_DCFG_DAD_Pos (4U)
-#define USB_OTG_DCFG_DAD_Msk (0x7FUL << USB_OTG_DCFG_DAD_Pos) /*!< 0x000007F0 */
-#define USB_OTG_DCFG_DAD USB_OTG_DCFG_DAD_Msk /*!< Device address */
-#define USB_OTG_DCFG_DAD_0 (0x01UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000010 */
-#define USB_OTG_DCFG_DAD_1 (0x02UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000020 */
-#define USB_OTG_DCFG_DAD_2 (0x04UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000040 */
-#define USB_OTG_DCFG_DAD_3 (0x08UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000080 */
-#define USB_OTG_DCFG_DAD_4 (0x10UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000100 */
-#define USB_OTG_DCFG_DAD_5 (0x20UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000200 */
-#define USB_OTG_DCFG_DAD_6 (0x40UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000400 */
-
-#define USB_OTG_DCFG_PFIVL_Pos (11U)
-#define USB_OTG_DCFG_PFIVL_Msk (0x3UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00001800 */
-#define USB_OTG_DCFG_PFIVL USB_OTG_DCFG_PFIVL_Msk /*!< Periodic (micro)frame interval */
-#define USB_OTG_DCFG_PFIVL_0 (0x1UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00000800 */
-#define USB_OTG_DCFG_PFIVL_1 (0x2UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00001000 */
-
-#define USB_OTG_DCFG_PERSCHIVL_Pos (24U)
-#define USB_OTG_DCFG_PERSCHIVL_Msk (0x3UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x03000000 */
-#define USB_OTG_DCFG_PERSCHIVL USB_OTG_DCFG_PERSCHIVL_Msk /*!< Periodic scheduling interval */
-#define USB_OTG_DCFG_PERSCHIVL_0 (0x1UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x01000000 */
-#define USB_OTG_DCFG_PERSCHIVL_1 (0x2UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x02000000 */
-
-/******************** Bit definition for USB_OTG_PCGCR register ********************/
-#define USB_OTG_PCGCR_STPPCLK_Pos (0U)
-#define USB_OTG_PCGCR_STPPCLK_Msk (0x1UL << USB_OTG_PCGCR_STPPCLK_Pos) /*!< 0x00000001 */
-#define USB_OTG_PCGCR_STPPCLK USB_OTG_PCGCR_STPPCLK_Msk /*!< Stop PHY clock */
-#define USB_OTG_PCGCR_GATEHCLK_Pos (1U)
-#define USB_OTG_PCGCR_GATEHCLK_Msk (0x1UL << USB_OTG_PCGCR_GATEHCLK_Pos) /*!< 0x00000002 */
-#define USB_OTG_PCGCR_GATEHCLK USB_OTG_PCGCR_GATEHCLK_Msk /*!< Gate HCLK */
-#define USB_OTG_PCGCR_PHYSUSP_Pos (4U)
-#define USB_OTG_PCGCR_PHYSUSP_Msk (0x1UL << USB_OTG_PCGCR_PHYSUSP_Pos) /*!< 0x00000010 */
-#define USB_OTG_PCGCR_PHYSUSP USB_OTG_PCGCR_PHYSUSP_Msk /*!< PHY suspended */
-
-/******************** Bit definition for USB_OTG_GOTGINT register ********************/
-#define USB_OTG_GOTGINT_SEDET_Pos (2U)
-#define USB_OTG_GOTGINT_SEDET_Msk (0x1UL << USB_OTG_GOTGINT_SEDET_Pos) /*!< 0x00000004 */
-#define USB_OTG_GOTGINT_SEDET USB_OTG_GOTGINT_SEDET_Msk /*!< Session end detected */
-#define USB_OTG_GOTGINT_SRSSCHG_Pos (8U)
-#define USB_OTG_GOTGINT_SRSSCHG_Msk (0x1UL << USB_OTG_GOTGINT_SRSSCHG_Pos) /*!< 0x00000100 */
-#define USB_OTG_GOTGINT_SRSSCHG USB_OTG_GOTGINT_SRSSCHG_Msk /*!< Session request success status change */
-#define USB_OTG_GOTGINT_HNSSCHG_Pos (9U)
-#define USB_OTG_GOTGINT_HNSSCHG_Msk (0x1UL << USB_OTG_GOTGINT_HNSSCHG_Pos) /*!< 0x00000200 */
-#define USB_OTG_GOTGINT_HNSSCHG USB_OTG_GOTGINT_HNSSCHG_Msk /*!< Host negotiation success status change */
-#define USB_OTG_GOTGINT_HNGDET_Pos (17U)
-#define USB_OTG_GOTGINT_HNGDET_Msk (0x1UL << USB_OTG_GOTGINT_HNGDET_Pos) /*!< 0x00020000 */
-#define USB_OTG_GOTGINT_HNGDET USB_OTG_GOTGINT_HNGDET_Msk /*!< Host negotiation detected */
-#define USB_OTG_GOTGINT_ADTOCHG_Pos (18U)
-#define USB_OTG_GOTGINT_ADTOCHG_Msk (0x1UL << USB_OTG_GOTGINT_ADTOCHG_Pos) /*!< 0x00040000 */
-#define USB_OTG_GOTGINT_ADTOCHG USB_OTG_GOTGINT_ADTOCHG_Msk /*!< A-device timeout change */
-#define USB_OTG_GOTGINT_DBCDNE_Pos (19U)
-#define USB_OTG_GOTGINT_DBCDNE_Msk (0x1UL << USB_OTG_GOTGINT_DBCDNE_Pos) /*!< 0x00080000 */
-#define USB_OTG_GOTGINT_DBCDNE USB_OTG_GOTGINT_DBCDNE_Msk /*!< Debounce done */
-
-/******************** Bit definition for USB_OTG_DCTL register ********************/
-#define USB_OTG_DCTL_RWUSIG_Pos (0U)
-#define USB_OTG_DCTL_RWUSIG_Msk (0x1UL << USB_OTG_DCTL_RWUSIG_Pos) /*!< 0x00000001 */
-#define USB_OTG_DCTL_RWUSIG USB_OTG_DCTL_RWUSIG_Msk /*!< Remote wakeup signaling */
-#define USB_OTG_DCTL_SDIS_Pos (1U)
-#define USB_OTG_DCTL_SDIS_Msk (0x1UL << USB_OTG_DCTL_SDIS_Pos) /*!< 0x00000002 */
-#define USB_OTG_DCTL_SDIS USB_OTG_DCTL_SDIS_Msk /*!< Soft disconnect */
-#define USB_OTG_DCTL_GINSTS_Pos (2U)
-#define USB_OTG_DCTL_GINSTS_Msk (0x1UL << USB_OTG_DCTL_GINSTS_Pos) /*!< 0x00000004 */
-#define USB_OTG_DCTL_GINSTS USB_OTG_DCTL_GINSTS_Msk /*!< Global IN NAK status */
-#define USB_OTG_DCTL_GONSTS_Pos (3U)
-#define USB_OTG_DCTL_GONSTS_Msk (0x1UL << USB_OTG_DCTL_GONSTS_Pos) /*!< 0x00000008 */
-#define USB_OTG_DCTL_GONSTS USB_OTG_DCTL_GONSTS_Msk /*!< Global OUT NAK status */
-
-#define USB_OTG_DCTL_TCTL_Pos (4U)
-#define USB_OTG_DCTL_TCTL_Msk (0x7UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000070 */
-#define USB_OTG_DCTL_TCTL USB_OTG_DCTL_TCTL_Msk /*!< Test control */
-#define USB_OTG_DCTL_TCTL_0 (0x1UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000010 */
-#define USB_OTG_DCTL_TCTL_1 (0x2UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000020 */
-#define USB_OTG_DCTL_TCTL_2 (0x4UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000040 */
-#define USB_OTG_DCTL_SGINAK_Pos (7U)
-#define USB_OTG_DCTL_SGINAK_Msk (0x1UL << USB_OTG_DCTL_SGINAK_Pos) /*!< 0x00000080 */
-#define USB_OTG_DCTL_SGINAK USB_OTG_DCTL_SGINAK_Msk /*!< Set global IN NAK */
-#define USB_OTG_DCTL_CGINAK_Pos (8U)
-#define USB_OTG_DCTL_CGINAK_Msk (0x1UL << USB_OTG_DCTL_CGINAK_Pos) /*!< 0x00000100 */
-#define USB_OTG_DCTL_CGINAK USB_OTG_DCTL_CGINAK_Msk /*!< Clear global IN NAK */
-#define USB_OTG_DCTL_SGONAK_Pos (9U)
-#define USB_OTG_DCTL_SGONAK_Msk (0x1UL << USB_OTG_DCTL_SGONAK_Pos) /*!< 0x00000200 */
-#define USB_OTG_DCTL_SGONAK USB_OTG_DCTL_SGONAK_Msk /*!< Set global OUT NAK */
-#define USB_OTG_DCTL_CGONAK_Pos (10U)
-#define USB_OTG_DCTL_CGONAK_Msk (0x1UL << USB_OTG_DCTL_CGONAK_Pos) /*!< 0x00000400 */
-#define USB_OTG_DCTL_CGONAK USB_OTG_DCTL_CGONAK_Msk /*!< Clear global OUT NAK */
-#define USB_OTG_DCTL_POPRGDNE_Pos (11U)
-#define USB_OTG_DCTL_POPRGDNE_Msk (0x1UL << USB_OTG_DCTL_POPRGDNE_Pos) /*!< 0x00000800 */
-#define USB_OTG_DCTL_POPRGDNE USB_OTG_DCTL_POPRGDNE_Msk /*!< Power-on programming done */
-
-/******************** Bit definition for USB_OTG_HFIR register ********************/
-#define USB_OTG_HFIR_FRIVL_Pos (0U)
-#define USB_OTG_HFIR_FRIVL_Msk (0xFFFFUL << USB_OTG_HFIR_FRIVL_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_HFIR_FRIVL USB_OTG_HFIR_FRIVL_Msk /*!< Frame interval */
-
-/******************** Bit definition for USB_OTG_HFNUM register ********************/
-#define USB_OTG_HFNUM_FRNUM_Pos (0U)
-#define USB_OTG_HFNUM_FRNUM_Msk (0xFFFFUL << USB_OTG_HFNUM_FRNUM_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_HFNUM_FRNUM USB_OTG_HFNUM_FRNUM_Msk /*!< Frame number */
-#define USB_OTG_HFNUM_FTREM_Pos (16U)
-#define USB_OTG_HFNUM_FTREM_Msk (0xFFFFUL << USB_OTG_HFNUM_FTREM_Pos) /*!< 0xFFFF0000 */
-#define USB_OTG_HFNUM_FTREM USB_OTG_HFNUM_FTREM_Msk /*!< Frame time remaining */
-
-/******************** Bit definition for USB_OTG_DSTS register ********************/
-#define USB_OTG_DSTS_SUSPSTS_Pos (0U)
-#define USB_OTG_DSTS_SUSPSTS_Msk (0x1UL << USB_OTG_DSTS_SUSPSTS_Pos) /*!< 0x00000001 */
-#define USB_OTG_DSTS_SUSPSTS USB_OTG_DSTS_SUSPSTS_Msk /*!< Suspend status */
-
-#define USB_OTG_DSTS_ENUMSPD_Pos (1U)
-#define USB_OTG_DSTS_ENUMSPD_Msk (0x3UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000006 */
-#define USB_OTG_DSTS_ENUMSPD USB_OTG_DSTS_ENUMSPD_Msk /*!< Enumerated speed */
-#define USB_OTG_DSTS_ENUMSPD_0 (0x1UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000002 */
-#define USB_OTG_DSTS_ENUMSPD_1 (0x2UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000004 */
-#define USB_OTG_DSTS_EERR_Pos (3U)
-#define USB_OTG_DSTS_EERR_Msk (0x1UL << USB_OTG_DSTS_EERR_Pos) /*!< 0x00000008 */
-#define USB_OTG_DSTS_EERR USB_OTG_DSTS_EERR_Msk /*!< Erratic error */
-#define USB_OTG_DSTS_FNSOF_Pos (8U)
-#define USB_OTG_DSTS_FNSOF_Msk (0x3FFFUL << USB_OTG_DSTS_FNSOF_Pos) /*!< 0x003FFF00 */
-#define USB_OTG_DSTS_FNSOF USB_OTG_DSTS_FNSOF_Msk /*!< Frame number of the received SOF */
-
-/******************** Bit definition for USB_OTG_GAHBCFG register ********************/
-#define USB_OTG_GAHBCFG_GINT_Pos (0U)
-#define USB_OTG_GAHBCFG_GINT_Msk (0x1UL << USB_OTG_GAHBCFG_GINT_Pos) /*!< 0x00000001 */
-#define USB_OTG_GAHBCFG_GINT USB_OTG_GAHBCFG_GINT_Msk /*!< Global interrupt mask */
-#define USB_OTG_GAHBCFG_HBSTLEN_Pos (1U)
-#define USB_OTG_GAHBCFG_HBSTLEN_Msk (0xFUL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< 0x0000001E */
-#define USB_OTG_GAHBCFG_HBSTLEN USB_OTG_GAHBCFG_HBSTLEN_Msk /*!< Burst length/type */
-#define USB_OTG_GAHBCFG_HBSTLEN_0 (0x0UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< Single */
-#define USB_OTG_GAHBCFG_HBSTLEN_1 (0x1UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR */
-#define USB_OTG_GAHBCFG_HBSTLEN_2 (0x3UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR4 */
-#define USB_OTG_GAHBCFG_HBSTLEN_3 (0x5UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR8 */
-#define USB_OTG_GAHBCFG_HBSTLEN_4 (0x7UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR16 */
-#define USB_OTG_GAHBCFG_DMAEN_Pos (5U)
-#define USB_OTG_GAHBCFG_DMAEN_Msk (0x1UL << USB_OTG_GAHBCFG_DMAEN_Pos) /*!< 0x00000020 */
-#define USB_OTG_GAHBCFG_DMAEN USB_OTG_GAHBCFG_DMAEN_Msk /*!< DMA enable */
-#define USB_OTG_GAHBCFG_TXFELVL_Pos (7U)
-#define USB_OTG_GAHBCFG_TXFELVL_Msk (0x1UL << USB_OTG_GAHBCFG_TXFELVL_Pos) /*!< 0x00000080 */
-#define USB_OTG_GAHBCFG_TXFELVL USB_OTG_GAHBCFG_TXFELVL_Msk /*!< TxFIFO empty level */
-#define USB_OTG_GAHBCFG_PTXFELVL_Pos (8U)
-#define USB_OTG_GAHBCFG_PTXFELVL_Msk (0x1UL << USB_OTG_GAHBCFG_PTXFELVL_Pos) /*!< 0x00000100 */
-#define USB_OTG_GAHBCFG_PTXFELVL USB_OTG_GAHBCFG_PTXFELVL_Msk /*!< Periodic TxFIFO empty level */
-
-/******************** Bit definition for USB_OTG_GUSBCFG register ********************/
-
-#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_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_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 */
-#define USB_OTG_GUSBCFG_HNPCAP_Pos (9U)
-#define USB_OTG_GUSBCFG_HNPCAP_Msk (0x1UL << USB_OTG_GUSBCFG_HNPCAP_Pos) /*!< 0x00000200 */
-#define USB_OTG_GUSBCFG_HNPCAP USB_OTG_GUSBCFG_HNPCAP_Msk /*!< HNP-capable */
-#define USB_OTG_GUSBCFG_TRDT_Pos (10U)
-#define USB_OTG_GUSBCFG_TRDT_Msk (0xFUL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00003C00 */
-#define USB_OTG_GUSBCFG_TRDT USB_OTG_GUSBCFG_TRDT_Msk /*!< USB turnaround time */
-#define USB_OTG_GUSBCFG_TRDT_0 (0x1UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00000400 */
-#define USB_OTG_GUSBCFG_TRDT_1 (0x2UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00000800 */
-#define USB_OTG_GUSBCFG_TRDT_2 (0x4UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00001000 */
-#define USB_OTG_GUSBCFG_TRDT_3 (0x8UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00002000 */
-#define USB_OTG_GUSBCFG_PHYLPCS_Pos (15U)
-#define USB_OTG_GUSBCFG_PHYLPCS_Msk (0x1UL << USB_OTG_GUSBCFG_PHYLPCS_Pos) /*!< 0x00008000 */
-#define USB_OTG_GUSBCFG_PHYLPCS USB_OTG_GUSBCFG_PHYLPCS_Msk /*!< PHY Low-power clock select */
-#define USB_OTG_GUSBCFG_ULPIFSLS_Pos (17U)
-#define USB_OTG_GUSBCFG_ULPIFSLS_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIFSLS_Pos) /*!< 0x00020000 */
-#define USB_OTG_GUSBCFG_ULPIFSLS USB_OTG_GUSBCFG_ULPIFSLS_Msk /*!< ULPI FS/LS select */
-#define USB_OTG_GUSBCFG_ULPIAR_Pos (18U)
-#define USB_OTG_GUSBCFG_ULPIAR_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIAR_Pos) /*!< 0x00040000 */
-#define USB_OTG_GUSBCFG_ULPIAR USB_OTG_GUSBCFG_ULPIAR_Msk /*!< ULPI Auto-resume */
-#define USB_OTG_GUSBCFG_ULPICSM_Pos (19U)
-#define USB_OTG_GUSBCFG_ULPICSM_Msk (0x1UL << USB_OTG_GUSBCFG_ULPICSM_Pos) /*!< 0x00080000 */
-#define USB_OTG_GUSBCFG_ULPICSM USB_OTG_GUSBCFG_ULPICSM_Msk /*!< ULPI Clock SuspendM */
-#define USB_OTG_GUSBCFG_ULPIEVBUSD_Pos (20U)
-#define USB_OTG_GUSBCFG_ULPIEVBUSD_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIEVBUSD_Pos) /*!< 0x00100000 */
-#define USB_OTG_GUSBCFG_ULPIEVBUSD USB_OTG_GUSBCFG_ULPIEVBUSD_Msk /*!< ULPI External VBUS Drive */
-#define USB_OTG_GUSBCFG_ULPIEVBUSI_Pos (21U)
-#define USB_OTG_GUSBCFG_ULPIEVBUSI_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIEVBUSI_Pos) /*!< 0x00200000 */
-#define USB_OTG_GUSBCFG_ULPIEVBUSI USB_OTG_GUSBCFG_ULPIEVBUSI_Msk /*!< ULPI external VBUS indicator */
-#define USB_OTG_GUSBCFG_TSDPS_Pos (22U)
-#define USB_OTG_GUSBCFG_TSDPS_Msk (0x1UL << USB_OTG_GUSBCFG_TSDPS_Pos) /*!< 0x00400000 */
-#define USB_OTG_GUSBCFG_TSDPS USB_OTG_GUSBCFG_TSDPS_Msk /*!< TermSel DLine pulsing selection */
-#define USB_OTG_GUSBCFG_PCCI_Pos (23U)
-#define USB_OTG_GUSBCFG_PCCI_Msk (0x1UL << USB_OTG_GUSBCFG_PCCI_Pos) /*!< 0x00800000 */
-#define USB_OTG_GUSBCFG_PCCI USB_OTG_GUSBCFG_PCCI_Msk /*!< Indicator complement */
-#define USB_OTG_GUSBCFG_PTCI_Pos (24U)
-#define USB_OTG_GUSBCFG_PTCI_Msk (0x1UL << USB_OTG_GUSBCFG_PTCI_Pos) /*!< 0x01000000 */
-#define USB_OTG_GUSBCFG_PTCI USB_OTG_GUSBCFG_PTCI_Msk /*!< Indicator pass through */
-#define USB_OTG_GUSBCFG_ULPIIPD_Pos (25U)
-#define USB_OTG_GUSBCFG_ULPIIPD_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIIPD_Pos) /*!< 0x02000000 */
-#define USB_OTG_GUSBCFG_ULPIIPD USB_OTG_GUSBCFG_ULPIIPD_Msk /*!< ULPI interface protect disable */
-#define USB_OTG_GUSBCFG_FHMOD_Pos (29U)
-#define USB_OTG_GUSBCFG_FHMOD_Msk (0x1UL << USB_OTG_GUSBCFG_FHMOD_Pos) /*!< 0x20000000 */
-#define USB_OTG_GUSBCFG_FHMOD USB_OTG_GUSBCFG_FHMOD_Msk /*!< Forced host mode */
-#define USB_OTG_GUSBCFG_FDMOD_Pos (30U)
-#define USB_OTG_GUSBCFG_FDMOD_Msk (0x1UL << USB_OTG_GUSBCFG_FDMOD_Pos) /*!< 0x40000000 */
-#define USB_OTG_GUSBCFG_FDMOD USB_OTG_GUSBCFG_FDMOD_Msk /*!< Forced peripheral mode */
-#define USB_OTG_GUSBCFG_CTXPKT_Pos (31U)
-#define USB_OTG_GUSBCFG_CTXPKT_Msk (0x1UL << USB_OTG_GUSBCFG_CTXPKT_Pos) /*!< 0x80000000 */
-#define USB_OTG_GUSBCFG_CTXPKT USB_OTG_GUSBCFG_CTXPKT_Msk /*!< Corrupt Tx packet */
-
-/******************** Bit definition for USB_OTG_GRSTCTL register ********************/
-#define USB_OTG_GRSTCTL_CSRST_Pos (0U)
-#define USB_OTG_GRSTCTL_CSRST_Msk (0x1UL << USB_OTG_GRSTCTL_CSRST_Pos) /*!< 0x00000001 */
-#define USB_OTG_GRSTCTL_CSRST USB_OTG_GRSTCTL_CSRST_Msk /*!< Core soft reset */
-#define USB_OTG_GRSTCTL_HSRST_Pos (1U)
-#define USB_OTG_GRSTCTL_HSRST_Msk (0x1UL << USB_OTG_GRSTCTL_HSRST_Pos) /*!< 0x00000002 */
-#define USB_OTG_GRSTCTL_HSRST USB_OTG_GRSTCTL_HSRST_Msk /*!< HCLK soft reset */
-#define USB_OTG_GRSTCTL_FCRST_Pos (2U)
-#define USB_OTG_GRSTCTL_FCRST_Msk (0x1UL << USB_OTG_GRSTCTL_FCRST_Pos) /*!< 0x00000004 */
-#define USB_OTG_GRSTCTL_FCRST USB_OTG_GRSTCTL_FCRST_Msk /*!< Host frame counter reset */
-#define USB_OTG_GRSTCTL_RXFFLSH_Pos (4U)
-#define USB_OTG_GRSTCTL_RXFFLSH_Msk (0x1UL << USB_OTG_GRSTCTL_RXFFLSH_Pos) /*!< 0x00000010 */
-#define USB_OTG_GRSTCTL_RXFFLSH USB_OTG_GRSTCTL_RXFFLSH_Msk /*!< RxFIFO flush */
-#define USB_OTG_GRSTCTL_TXFFLSH_Pos (5U)
-#define USB_OTG_GRSTCTL_TXFFLSH_Msk (0x1UL << USB_OTG_GRSTCTL_TXFFLSH_Pos) /*!< 0x00000020 */
-#define USB_OTG_GRSTCTL_TXFFLSH USB_OTG_GRSTCTL_TXFFLSH_Msk /*!< TxFIFO flush */
-
-
-#define USB_OTG_GRSTCTL_TXFNUM_Pos (6U)
-#define USB_OTG_GRSTCTL_TXFNUM_Msk (0x1FUL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x000007C0 */
-#define USB_OTG_GRSTCTL_TXFNUM USB_OTG_GRSTCTL_TXFNUM_Msk /*!< TxFIFO number */
-#define USB_OTG_GRSTCTL_TXFNUM_0 (0x01UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000040 */
-#define USB_OTG_GRSTCTL_TXFNUM_1 (0x02UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000080 */
-#define USB_OTG_GRSTCTL_TXFNUM_2 (0x04UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000100 */
-#define USB_OTG_GRSTCTL_TXFNUM_3 (0x08UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000200 */
-#define USB_OTG_GRSTCTL_TXFNUM_4 (0x10UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000400 */
-#define USB_OTG_GRSTCTL_DMAREQ_Pos (30U)
-#define USB_OTG_GRSTCTL_DMAREQ_Msk (0x1UL << USB_OTG_GRSTCTL_DMAREQ_Pos) /*!< 0x40000000 */
-#define USB_OTG_GRSTCTL_DMAREQ USB_OTG_GRSTCTL_DMAREQ_Msk /*!< DMA request signal */
-#define USB_OTG_GRSTCTL_AHBIDL_Pos (31U)
-#define USB_OTG_GRSTCTL_AHBIDL_Msk (0x1UL << USB_OTG_GRSTCTL_AHBIDL_Pos) /*!< 0x80000000 */
-#define USB_OTG_GRSTCTL_AHBIDL USB_OTG_GRSTCTL_AHBIDL_Msk /*!< AHB master idle */
-
-/******************** Bit definition for USB_OTG_DIEPMSK register ********************/
-#define USB_OTG_DIEPMSK_XFRCM_Pos (0U)
-#define USB_OTG_DIEPMSK_XFRCM_Msk (0x1UL << USB_OTG_DIEPMSK_XFRCM_Pos) /*!< 0x00000001 */
-#define USB_OTG_DIEPMSK_XFRCM USB_OTG_DIEPMSK_XFRCM_Msk /*!< Transfer completed interrupt mask */
-#define USB_OTG_DIEPMSK_EPDM_Pos (1U)
-#define USB_OTG_DIEPMSK_EPDM_Msk (0x1UL << USB_OTG_DIEPMSK_EPDM_Pos) /*!< 0x00000002 */
-#define USB_OTG_DIEPMSK_EPDM USB_OTG_DIEPMSK_EPDM_Msk /*!< Endpoint disabled interrupt mask */
-#define USB_OTG_DIEPMSK_TOM_Pos (3U)
-#define USB_OTG_DIEPMSK_TOM_Msk (0x1UL << USB_OTG_DIEPMSK_TOM_Pos) /*!< 0x00000008 */
-#define USB_OTG_DIEPMSK_TOM USB_OTG_DIEPMSK_TOM_Msk /*!< Timeout condition mask (nonisochronous endpoints) */
-#define USB_OTG_DIEPMSK_ITTXFEMSK_Pos (4U)
-#define USB_OTG_DIEPMSK_ITTXFEMSK_Msk (0x1UL << USB_OTG_DIEPMSK_ITTXFEMSK_Pos) /*!< 0x00000010 */
-#define USB_OTG_DIEPMSK_ITTXFEMSK USB_OTG_DIEPMSK_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */
-#define USB_OTG_DIEPMSK_INEPNMM_Pos (5U)
-#define USB_OTG_DIEPMSK_INEPNMM_Msk (0x1UL << USB_OTG_DIEPMSK_INEPNMM_Pos) /*!< 0x00000020 */
-#define USB_OTG_DIEPMSK_INEPNMM USB_OTG_DIEPMSK_INEPNMM_Msk /*!< IN token received with EP mismatch mask */
-#define USB_OTG_DIEPMSK_INEPNEM_Pos (6U)
-#define USB_OTG_DIEPMSK_INEPNEM_Msk (0x1UL << USB_OTG_DIEPMSK_INEPNEM_Pos) /*!< 0x00000040 */
-#define USB_OTG_DIEPMSK_INEPNEM USB_OTG_DIEPMSK_INEPNEM_Msk /*!< IN endpoint NAK effective mask */
-#define USB_OTG_DIEPMSK_TXFURM_Pos (8U)
-#define USB_OTG_DIEPMSK_TXFURM_Msk (0x1UL << USB_OTG_DIEPMSK_TXFURM_Pos) /*!< 0x00000100 */
-#define USB_OTG_DIEPMSK_TXFURM USB_OTG_DIEPMSK_TXFURM_Msk /*!< FIFO underrun mask */
-#define USB_OTG_DIEPMSK_BIM_Pos (9U)
-#define USB_OTG_DIEPMSK_BIM_Msk (0x1UL << USB_OTG_DIEPMSK_BIM_Pos) /*!< 0x00000200 */
-#define USB_OTG_DIEPMSK_BIM USB_OTG_DIEPMSK_BIM_Msk /*!< BNA interrupt mask */
-
-/******************** Bit definition for USB_OTG_HPTXSTS register ********************/
-#define USB_OTG_HPTXSTS_PTXFSAVL_Pos (0U)
-#define USB_OTG_HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << USB_OTG_HPTXSTS_PTXFSAVL_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_HPTXSTS_PTXFSAVL USB_OTG_HPTXSTS_PTXFSAVL_Msk /*!< Periodic transmit data FIFO space available */
-#define USB_OTG_HPTXSTS_PTXQSAV_Pos (16U)
-#define USB_OTG_HPTXSTS_PTXQSAV_Msk (0xFFUL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00FF0000 */
-#define USB_OTG_HPTXSTS_PTXQSAV USB_OTG_HPTXSTS_PTXQSAV_Msk /*!< Periodic transmit request queue space available */
-#define USB_OTG_HPTXSTS_PTXQSAV_0 (0x01UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00010000 */
-#define USB_OTG_HPTXSTS_PTXQSAV_1 (0x02UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00020000 */
-#define USB_OTG_HPTXSTS_PTXQSAV_2 (0x04UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00040000 */
-#define USB_OTG_HPTXSTS_PTXQSAV_3 (0x08UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00080000 */
-#define USB_OTG_HPTXSTS_PTXQSAV_4 (0x10UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00100000 */
-#define USB_OTG_HPTXSTS_PTXQSAV_5 (0x20UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00200000 */
-#define USB_OTG_HPTXSTS_PTXQSAV_6 (0x40UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00400000 */
-#define USB_OTG_HPTXSTS_PTXQSAV_7 (0x80UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00800000 */
-
-#define USB_OTG_HPTXSTS_PTXQTOP_Pos (24U)
-#define USB_OTG_HPTXSTS_PTXQTOP_Msk (0xFFUL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0xFF000000 */
-#define USB_OTG_HPTXSTS_PTXQTOP USB_OTG_HPTXSTS_PTXQTOP_Msk /*!< Top of the periodic transmit request queue */
-#define USB_OTG_HPTXSTS_PTXQTOP_0 (0x01UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x01000000 */
-#define USB_OTG_HPTXSTS_PTXQTOP_1 (0x02UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x02000000 */
-#define USB_OTG_HPTXSTS_PTXQTOP_2 (0x04UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x04000000 */
-#define USB_OTG_HPTXSTS_PTXQTOP_3 (0x08UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x08000000 */
-#define USB_OTG_HPTXSTS_PTXQTOP_4 (0x10UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x10000000 */
-#define USB_OTG_HPTXSTS_PTXQTOP_5 (0x20UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x20000000 */
-#define USB_OTG_HPTXSTS_PTXQTOP_6 (0x40UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x40000000 */
-#define USB_OTG_HPTXSTS_PTXQTOP_7 (0x80UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x80000000 */
-
-/******************** Bit definition for USB_OTG_HAINT register ********************/
-#define USB_OTG_HAINT_HAINT_Pos (0U)
-#define USB_OTG_HAINT_HAINT_Msk (0xFFFFUL << USB_OTG_HAINT_HAINT_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_HAINT_HAINT USB_OTG_HAINT_HAINT_Msk /*!< Channel interrupts */
-
-/******************** Bit definition for USB_OTG_DOEPMSK register ********************/
-#define USB_OTG_DOEPMSK_XFRCM_Pos (0U)
-#define USB_OTG_DOEPMSK_XFRCM_Msk (0x1UL << USB_OTG_DOEPMSK_XFRCM_Pos) /*!< 0x00000001 */
-#define USB_OTG_DOEPMSK_XFRCM USB_OTG_DOEPMSK_XFRCM_Msk /*!< Transfer completed interrupt mask */
-#define USB_OTG_DOEPMSK_EPDM_Pos (1U)
-#define USB_OTG_DOEPMSK_EPDM_Msk (0x1UL << USB_OTG_DOEPMSK_EPDM_Pos) /*!< 0x00000002 */
-#define USB_OTG_DOEPMSK_EPDM USB_OTG_DOEPMSK_EPDM_Msk /*!< Endpoint disabled interrupt mask */
-#define USB_OTG_DOEPMSK_AHBERRM_Pos (2U)
-#define USB_OTG_DOEPMSK_AHBERRM_Msk (0x1UL << USB_OTG_DOEPMSK_AHBERRM_Pos) /*!< 0x00000004 */
-#define USB_OTG_DOEPMSK_AHBERRM USB_OTG_DOEPMSK_AHBERRM_Msk /*!< OUT transaction AHB Error interrupt mask */
-#define USB_OTG_DOEPMSK_STUPM_Pos (3U)
-#define USB_OTG_DOEPMSK_STUPM_Msk (0x1UL << USB_OTG_DOEPMSK_STUPM_Pos) /*!< 0x00000008 */
-#define USB_OTG_DOEPMSK_STUPM USB_OTG_DOEPMSK_STUPM_Msk /*!< SETUP phase done mask */
-#define USB_OTG_DOEPMSK_OTEPDM_Pos (4U)
-#define USB_OTG_DOEPMSK_OTEPDM_Msk (0x1UL << USB_OTG_DOEPMSK_OTEPDM_Pos) /*!< 0x00000010 */
-#define USB_OTG_DOEPMSK_OTEPDM USB_OTG_DOEPMSK_OTEPDM_Msk /*!< OUT token received when endpoint disabled mask */
-#define USB_OTG_DOEPMSK_OTEPSPRM_Pos (5U)
-#define USB_OTG_DOEPMSK_OTEPSPRM_Msk (0x1UL << USB_OTG_DOEPMSK_OTEPSPRM_Pos) /*!< 0x00000020 */
-#define USB_OTG_DOEPMSK_OTEPSPRM USB_OTG_DOEPMSK_OTEPSPRM_Msk /*!< Status Phase Received mask */
-#define USB_OTG_DOEPMSK_B2BSTUP_Pos (6U)
-#define USB_OTG_DOEPMSK_B2BSTUP_Msk (0x1UL << USB_OTG_DOEPMSK_B2BSTUP_Pos) /*!< 0x00000040 */
-#define USB_OTG_DOEPMSK_B2BSTUP USB_OTG_DOEPMSK_B2BSTUP_Msk /*!< Back-to-back SETUP packets received mask */
-#define USB_OTG_DOEPMSK_OPEM_Pos (8U)
-#define USB_OTG_DOEPMSK_OPEM_Msk (0x1UL << USB_OTG_DOEPMSK_OPEM_Pos) /*!< 0x00000100 */
-#define USB_OTG_DOEPMSK_OPEM USB_OTG_DOEPMSK_OPEM_Msk /*!< OUT packet error mask */
-#define USB_OTG_DOEPMSK_BOIM_Pos (9U)
-#define USB_OTG_DOEPMSK_BOIM_Msk (0x1UL << USB_OTG_DOEPMSK_BOIM_Pos) /*!< 0x00000200 */
-#define USB_OTG_DOEPMSK_BOIM USB_OTG_DOEPMSK_BOIM_Msk /*!< BNA interrupt mask */
-#define USB_OTG_DOEPMSK_BERRM_Pos (12U)
-#define USB_OTG_DOEPMSK_BERRM_Msk (0x1UL << USB_OTG_DOEPMSK_BERRM_Pos) /*!< 0x00001000 */
-#define USB_OTG_DOEPMSK_BERRM USB_OTG_DOEPMSK_BERRM_Msk /*!< Babble error interrupt mask */
-#define USB_OTG_DOEPMSK_NAKM_Pos (13U)
-#define USB_OTG_DOEPMSK_NAKM_Msk (0x1UL << USB_OTG_DOEPMSK_NAKM_Pos) /*!< 0x00002000 */
-#define USB_OTG_DOEPMSK_NAKM USB_OTG_DOEPMSK_NAKM_Msk /*!< OUT Packet NAK interrupt mask */
-#define USB_OTG_DOEPMSK_NYETM_Pos (14U)
-#define USB_OTG_DOEPMSK_NYETM_Msk (0x1UL << USB_OTG_DOEPMSK_NYETM_Pos) /*!< 0x00004000 */
-#define USB_OTG_DOEPMSK_NYETM USB_OTG_DOEPMSK_NYETM_Msk /*!< NYET interrupt mask */
-/******************** Bit definition for USB_OTG_GINTSTS register ********************/
-#define USB_OTG_GINTSTS_CMOD_Pos (0U)
-#define USB_OTG_GINTSTS_CMOD_Msk (0x1UL << USB_OTG_GINTSTS_CMOD_Pos) /*!< 0x00000001 */
-#define USB_OTG_GINTSTS_CMOD USB_OTG_GINTSTS_CMOD_Msk /*!< Current mode of operation */
-#define USB_OTG_GINTSTS_MMIS_Pos (1U)
-#define USB_OTG_GINTSTS_MMIS_Msk (0x1UL << USB_OTG_GINTSTS_MMIS_Pos) /*!< 0x00000002 */
-#define USB_OTG_GINTSTS_MMIS USB_OTG_GINTSTS_MMIS_Msk /*!< Mode mismatch interrupt */
-#define USB_OTG_GINTSTS_OTGINT_Pos (2U)
-#define USB_OTG_GINTSTS_OTGINT_Msk (0x1UL << USB_OTG_GINTSTS_OTGINT_Pos) /*!< 0x00000004 */
-#define USB_OTG_GINTSTS_OTGINT USB_OTG_GINTSTS_OTGINT_Msk /*!< OTG interrupt */
-#define USB_OTG_GINTSTS_SOF_Pos (3U)
-#define USB_OTG_GINTSTS_SOF_Msk (0x1UL << USB_OTG_GINTSTS_SOF_Pos) /*!< 0x00000008 */
-#define USB_OTG_GINTSTS_SOF USB_OTG_GINTSTS_SOF_Msk /*!< Start of frame */
-#define USB_OTG_GINTSTS_RXFLVL_Pos (4U)
-#define USB_OTG_GINTSTS_RXFLVL_Msk (0x1UL << USB_OTG_GINTSTS_RXFLVL_Pos) /*!< 0x00000010 */
-#define USB_OTG_GINTSTS_RXFLVL USB_OTG_GINTSTS_RXFLVL_Msk /*!< RxFIFO nonempty */
-#define USB_OTG_GINTSTS_NPTXFE_Pos (5U)
-#define USB_OTG_GINTSTS_NPTXFE_Msk (0x1UL << USB_OTG_GINTSTS_NPTXFE_Pos) /*!< 0x00000020 */
-#define USB_OTG_GINTSTS_NPTXFE USB_OTG_GINTSTS_NPTXFE_Msk /*!< Nonperiodic TxFIFO empty */
-#define USB_OTG_GINTSTS_GINAKEFF_Pos (6U)
-#define USB_OTG_GINTSTS_GINAKEFF_Msk (0x1UL << USB_OTG_GINTSTS_GINAKEFF_Pos) /*!< 0x00000040 */
-#define USB_OTG_GINTSTS_GINAKEFF USB_OTG_GINTSTS_GINAKEFF_Msk /*!< Global IN nonperiodic NAK effective */
-#define USB_OTG_GINTSTS_BOUTNAKEFF_Pos (7U)
-#define USB_OTG_GINTSTS_BOUTNAKEFF_Msk (0x1UL << USB_OTG_GINTSTS_BOUTNAKEFF_Pos) /*!< 0x00000080 */
-#define USB_OTG_GINTSTS_BOUTNAKEFF USB_OTG_GINTSTS_BOUTNAKEFF_Msk /*!< Global OUT NAK effective */
-#define USB_OTG_GINTSTS_ESUSP_Pos (10U)
-#define USB_OTG_GINTSTS_ESUSP_Msk (0x1UL << USB_OTG_GINTSTS_ESUSP_Pos) /*!< 0x00000400 */
-#define USB_OTG_GINTSTS_ESUSP USB_OTG_GINTSTS_ESUSP_Msk /*!< Early suspend */
-#define USB_OTG_GINTSTS_USBSUSP_Pos (11U)
-#define USB_OTG_GINTSTS_USBSUSP_Msk (0x1UL << USB_OTG_GINTSTS_USBSUSP_Pos) /*!< 0x00000800 */
-#define USB_OTG_GINTSTS_USBSUSP USB_OTG_GINTSTS_USBSUSP_Msk /*!< USB suspend */
-#define USB_OTG_GINTSTS_USBRST_Pos (12U)
-#define USB_OTG_GINTSTS_USBRST_Msk (0x1UL << USB_OTG_GINTSTS_USBRST_Pos) /*!< 0x00001000 */
-#define USB_OTG_GINTSTS_USBRST USB_OTG_GINTSTS_USBRST_Msk /*!< USB reset */
-#define USB_OTG_GINTSTS_ENUMDNE_Pos (13U)
-#define USB_OTG_GINTSTS_ENUMDNE_Msk (0x1UL << USB_OTG_GINTSTS_ENUMDNE_Pos) /*!< 0x00002000 */
-#define USB_OTG_GINTSTS_ENUMDNE USB_OTG_GINTSTS_ENUMDNE_Msk /*!< Enumeration done */
-#define USB_OTG_GINTSTS_ISOODRP_Pos (14U)
-#define USB_OTG_GINTSTS_ISOODRP_Msk (0x1UL << USB_OTG_GINTSTS_ISOODRP_Pos) /*!< 0x00004000 */
-#define USB_OTG_GINTSTS_ISOODRP USB_OTG_GINTSTS_ISOODRP_Msk /*!< Isochronous OUT packet dropped interrupt */
-#define USB_OTG_GINTSTS_EOPF_Pos (15U)
-#define USB_OTG_GINTSTS_EOPF_Msk (0x1UL << USB_OTG_GINTSTS_EOPF_Pos) /*!< 0x00008000 */
-#define USB_OTG_GINTSTS_EOPF USB_OTG_GINTSTS_EOPF_Msk /*!< End of periodic frame interrupt */
-#define USB_OTG_GINTSTS_IEPINT_Pos (18U)
-#define USB_OTG_GINTSTS_IEPINT_Msk (0x1UL << USB_OTG_GINTSTS_IEPINT_Pos) /*!< 0x00040000 */
-#define USB_OTG_GINTSTS_IEPINT USB_OTG_GINTSTS_IEPINT_Msk /*!< IN endpoint interrupt */
-#define USB_OTG_GINTSTS_OEPINT_Pos (19U)
-#define USB_OTG_GINTSTS_OEPINT_Msk (0x1UL << USB_OTG_GINTSTS_OEPINT_Pos) /*!< 0x00080000 */
-#define USB_OTG_GINTSTS_OEPINT USB_OTG_GINTSTS_OEPINT_Msk /*!< OUT endpoint interrupt */
-#define USB_OTG_GINTSTS_IISOIXFR_Pos (20U)
-#define USB_OTG_GINTSTS_IISOIXFR_Msk (0x1UL << USB_OTG_GINTSTS_IISOIXFR_Pos) /*!< 0x00100000 */
-#define USB_OTG_GINTSTS_IISOIXFR USB_OTG_GINTSTS_IISOIXFR_Msk /*!< Incomplete isochronous IN transfer */
-#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Pos (21U)
-#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Pos) /*!< 0x00200000 */
-#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Msk /*!< Incomplete periodic transfer */
-#define USB_OTG_GINTSTS_DATAFSUSP_Pos (22U)
-#define USB_OTG_GINTSTS_DATAFSUSP_Msk (0x1UL << USB_OTG_GINTSTS_DATAFSUSP_Pos) /*!< 0x00400000 */
-#define USB_OTG_GINTSTS_DATAFSUSP USB_OTG_GINTSTS_DATAFSUSP_Msk /*!< Data fetch suspended */
-#define USB_OTG_GINTSTS_HPRTINT_Pos (24U)
-#define USB_OTG_GINTSTS_HPRTINT_Msk (0x1UL << USB_OTG_GINTSTS_HPRTINT_Pos) /*!< 0x01000000 */
-#define USB_OTG_GINTSTS_HPRTINT USB_OTG_GINTSTS_HPRTINT_Msk /*!< Host port interrupt */
-#define USB_OTG_GINTSTS_HCINT_Pos (25U)
-#define USB_OTG_GINTSTS_HCINT_Msk (0x1UL << USB_OTG_GINTSTS_HCINT_Pos) /*!< 0x02000000 */
-#define USB_OTG_GINTSTS_HCINT USB_OTG_GINTSTS_HCINT_Msk /*!< Host channels interrupt */
-#define USB_OTG_GINTSTS_PTXFE_Pos (26U)
-#define USB_OTG_GINTSTS_PTXFE_Msk (0x1UL << USB_OTG_GINTSTS_PTXFE_Pos) /*!< 0x04000000 */
-#define USB_OTG_GINTSTS_PTXFE USB_OTG_GINTSTS_PTXFE_Msk /*!< Periodic TxFIFO empty */
-#define USB_OTG_GINTSTS_CIDSCHG_Pos (28U)
-#define USB_OTG_GINTSTS_CIDSCHG_Msk (0x1UL << USB_OTG_GINTSTS_CIDSCHG_Pos) /*!< 0x10000000 */
-#define USB_OTG_GINTSTS_CIDSCHG USB_OTG_GINTSTS_CIDSCHG_Msk /*!< Connector ID status change */
-#define USB_OTG_GINTSTS_DISCINT_Pos (29U)
-#define USB_OTG_GINTSTS_DISCINT_Msk (0x1UL << USB_OTG_GINTSTS_DISCINT_Pos) /*!< 0x20000000 */
-#define USB_OTG_GINTSTS_DISCINT USB_OTG_GINTSTS_DISCINT_Msk /*!< Disconnect detected interrupt */
-#define USB_OTG_GINTSTS_SRQINT_Pos (30U)
-#define USB_OTG_GINTSTS_SRQINT_Msk (0x1UL << USB_OTG_GINTSTS_SRQINT_Pos) /*!< 0x40000000 */
-#define USB_OTG_GINTSTS_SRQINT USB_OTG_GINTSTS_SRQINT_Msk /*!< Session request/new session detected interrupt */
-#define USB_OTG_GINTSTS_WKUINT_Pos (31U)
-#define USB_OTG_GINTSTS_WKUINT_Msk (0x1UL << USB_OTG_GINTSTS_WKUINT_Pos) /*!< 0x80000000 */
-#define USB_OTG_GINTSTS_WKUINT USB_OTG_GINTSTS_WKUINT_Msk /*!< Resume/remote wakeup detected interrupt */
-
-/******************** Bit definition for USB_OTG_GINTMSK register ********************/
-#define USB_OTG_GINTMSK_MMISM_Pos (1U)
-#define USB_OTG_GINTMSK_MMISM_Msk (0x1UL << USB_OTG_GINTMSK_MMISM_Pos) /*!< 0x00000002 */
-#define USB_OTG_GINTMSK_MMISM USB_OTG_GINTMSK_MMISM_Msk /*!< Mode mismatch interrupt mask */
-#define USB_OTG_GINTMSK_OTGINT_Pos (2U)
-#define USB_OTG_GINTMSK_OTGINT_Msk (0x1UL << USB_OTG_GINTMSK_OTGINT_Pos) /*!< 0x00000004 */
-#define USB_OTG_GINTMSK_OTGINT USB_OTG_GINTMSK_OTGINT_Msk /*!< OTG interrupt mask */
-#define USB_OTG_GINTMSK_SOFM_Pos (3U)
-#define USB_OTG_GINTMSK_SOFM_Msk (0x1UL << USB_OTG_GINTMSK_SOFM_Pos) /*!< 0x00000008 */
-#define USB_OTG_GINTMSK_SOFM USB_OTG_GINTMSK_SOFM_Msk /*!< Start of frame mask */
-#define USB_OTG_GINTMSK_RXFLVLM_Pos (4U)
-#define USB_OTG_GINTMSK_RXFLVLM_Msk (0x1UL << USB_OTG_GINTMSK_RXFLVLM_Pos) /*!< 0x00000010 */
-#define USB_OTG_GINTMSK_RXFLVLM USB_OTG_GINTMSK_RXFLVLM_Msk /*!< Receive FIFO nonempty mask */
-#define USB_OTG_GINTMSK_NPTXFEM_Pos (5U)
-#define USB_OTG_GINTMSK_NPTXFEM_Msk (0x1UL << USB_OTG_GINTMSK_NPTXFEM_Pos) /*!< 0x00000020 */
-#define USB_OTG_GINTMSK_NPTXFEM USB_OTG_GINTMSK_NPTXFEM_Msk /*!< Nonperiodic TxFIFO empty mask */
-#define USB_OTG_GINTMSK_GINAKEFFM_Pos (6U)
-#define USB_OTG_GINTMSK_GINAKEFFM_Msk (0x1UL << USB_OTG_GINTMSK_GINAKEFFM_Pos) /*!< 0x00000040 */
-#define USB_OTG_GINTMSK_GINAKEFFM USB_OTG_GINTMSK_GINAKEFFM_Msk /*!< Global nonperiodic IN NAK effective mask */
-#define USB_OTG_GINTMSK_GONAKEFFM_Pos (7U)
-#define USB_OTG_GINTMSK_GONAKEFFM_Msk (0x1UL << USB_OTG_GINTMSK_GONAKEFFM_Pos) /*!< 0x00000080 */
-#define USB_OTG_GINTMSK_GONAKEFFM USB_OTG_GINTMSK_GONAKEFFM_Msk /*!< Global OUT NAK effective mask */
-#define USB_OTG_GINTMSK_ESUSPM_Pos (10U)
-#define USB_OTG_GINTMSK_ESUSPM_Msk (0x1UL << USB_OTG_GINTMSK_ESUSPM_Pos) /*!< 0x00000400 */
-#define USB_OTG_GINTMSK_ESUSPM USB_OTG_GINTMSK_ESUSPM_Msk /*!< Early suspend mask */
-#define USB_OTG_GINTMSK_USBSUSPM_Pos (11U)
-#define USB_OTG_GINTMSK_USBSUSPM_Msk (0x1UL << USB_OTG_GINTMSK_USBSUSPM_Pos) /*!< 0x00000800 */
-#define USB_OTG_GINTMSK_USBSUSPM USB_OTG_GINTMSK_USBSUSPM_Msk /*!< USB suspend mask */
-#define USB_OTG_GINTMSK_USBRST_Pos (12U)
-#define USB_OTG_GINTMSK_USBRST_Msk (0x1UL << USB_OTG_GINTMSK_USBRST_Pos) /*!< 0x00001000 */
-#define USB_OTG_GINTMSK_USBRST USB_OTG_GINTMSK_USBRST_Msk /*!< USB reset mask */
-#define USB_OTG_GINTMSK_ENUMDNEM_Pos (13U)
-#define USB_OTG_GINTMSK_ENUMDNEM_Msk (0x1UL << USB_OTG_GINTMSK_ENUMDNEM_Pos) /*!< 0x00002000 */
-#define USB_OTG_GINTMSK_ENUMDNEM USB_OTG_GINTMSK_ENUMDNEM_Msk /*!< Enumeration done mask */
-#define USB_OTG_GINTMSK_ISOODRPM_Pos (14U)
-#define USB_OTG_GINTMSK_ISOODRPM_Msk (0x1UL << USB_OTG_GINTMSK_ISOODRPM_Pos) /*!< 0x00004000 */
-#define USB_OTG_GINTMSK_ISOODRPM USB_OTG_GINTMSK_ISOODRPM_Msk /*!< Isochronous OUT packet dropped interrupt mask */
-#define USB_OTG_GINTMSK_EOPFM_Pos (15U)
-#define USB_OTG_GINTMSK_EOPFM_Msk (0x1UL << USB_OTG_GINTMSK_EOPFM_Pos) /*!< 0x00008000 */
-#define USB_OTG_GINTMSK_EOPFM USB_OTG_GINTMSK_EOPFM_Msk /*!< End of periodic frame interrupt mask */
-#define USB_OTG_GINTMSK_EPMISM_Pos (17U)
-#define USB_OTG_GINTMSK_EPMISM_Msk (0x1UL << USB_OTG_GINTMSK_EPMISM_Pos) /*!< 0x00020000 */
-#define USB_OTG_GINTMSK_EPMISM USB_OTG_GINTMSK_EPMISM_Msk /*!< Endpoint mismatch interrupt mask */
-#define USB_OTG_GINTMSK_IEPINT_Pos (18U)
-#define USB_OTG_GINTMSK_IEPINT_Msk (0x1UL << USB_OTG_GINTMSK_IEPINT_Pos) /*!< 0x00040000 */
-#define USB_OTG_GINTMSK_IEPINT USB_OTG_GINTMSK_IEPINT_Msk /*!< IN endpoints interrupt mask */
-#define USB_OTG_GINTMSK_OEPINT_Pos (19U)
-#define USB_OTG_GINTMSK_OEPINT_Msk (0x1UL << USB_OTG_GINTMSK_OEPINT_Pos) /*!< 0x00080000 */
-#define USB_OTG_GINTMSK_OEPINT USB_OTG_GINTMSK_OEPINT_Msk /*!< OUT endpoints interrupt mask */
-#define USB_OTG_GINTMSK_IISOIXFRM_Pos (20U)
-#define USB_OTG_GINTMSK_IISOIXFRM_Msk (0x1UL << USB_OTG_GINTMSK_IISOIXFRM_Pos) /*!< 0x00100000 */
-#define USB_OTG_GINTMSK_IISOIXFRM USB_OTG_GINTMSK_IISOIXFRM_Msk /*!< Incomplete isochronous IN transfer mask */
-#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Pos (21U)
-#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Pos) /*!< 0x00200000 */
-#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Msk /*!< Incomplete periodic transfer mask */
-#define USB_OTG_GINTMSK_FSUSPM_Pos (22U)
-#define USB_OTG_GINTMSK_FSUSPM_Msk (0x1UL << USB_OTG_GINTMSK_FSUSPM_Pos) /*!< 0x00400000 */
-#define USB_OTG_GINTMSK_FSUSPM USB_OTG_GINTMSK_FSUSPM_Msk /*!< Data fetch suspended mask */
-#define USB_OTG_GINTMSK_PRTIM_Pos (24U)
-#define USB_OTG_GINTMSK_PRTIM_Msk (0x1UL << USB_OTG_GINTMSK_PRTIM_Pos) /*!< 0x01000000 */
-#define USB_OTG_GINTMSK_PRTIM USB_OTG_GINTMSK_PRTIM_Msk /*!< Host port interrupt mask */
-#define USB_OTG_GINTMSK_HCIM_Pos (25U)
-#define USB_OTG_GINTMSK_HCIM_Msk (0x1UL << USB_OTG_GINTMSK_HCIM_Pos) /*!< 0x02000000 */
-#define USB_OTG_GINTMSK_HCIM USB_OTG_GINTMSK_HCIM_Msk /*!< Host channels interrupt mask */
-#define USB_OTG_GINTMSK_PTXFEM_Pos (26U)
-#define USB_OTG_GINTMSK_PTXFEM_Msk (0x1UL << USB_OTG_GINTMSK_PTXFEM_Pos) /*!< 0x04000000 */
-#define USB_OTG_GINTMSK_PTXFEM USB_OTG_GINTMSK_PTXFEM_Msk /*!< Periodic TxFIFO empty mask */
-#define USB_OTG_GINTMSK_CIDSCHGM_Pos (28U)
-#define USB_OTG_GINTMSK_CIDSCHGM_Msk (0x1UL << USB_OTG_GINTMSK_CIDSCHGM_Pos) /*!< 0x10000000 */
-#define USB_OTG_GINTMSK_CIDSCHGM USB_OTG_GINTMSK_CIDSCHGM_Msk /*!< Connector ID status change mask */
-#define USB_OTG_GINTMSK_DISCINT_Pos (29U)
-#define USB_OTG_GINTMSK_DISCINT_Msk (0x1UL << USB_OTG_GINTMSK_DISCINT_Pos) /*!< 0x20000000 */
-#define USB_OTG_GINTMSK_DISCINT USB_OTG_GINTMSK_DISCINT_Msk /*!< Disconnect detected interrupt mask */
-#define USB_OTG_GINTMSK_SRQIM_Pos (30U)
-#define USB_OTG_GINTMSK_SRQIM_Msk (0x1UL << USB_OTG_GINTMSK_SRQIM_Pos) /*!< 0x40000000 */
-#define USB_OTG_GINTMSK_SRQIM USB_OTG_GINTMSK_SRQIM_Msk /*!< Session request/new session detected interrupt mask */
-#define USB_OTG_GINTMSK_WUIM_Pos (31U)
-#define USB_OTG_GINTMSK_WUIM_Msk (0x1UL << USB_OTG_GINTMSK_WUIM_Pos) /*!< 0x80000000 */
-#define USB_OTG_GINTMSK_WUIM USB_OTG_GINTMSK_WUIM_Msk /*!< Resume/remote wakeup detected interrupt mask */
-
-/******************** Bit definition for USB_OTG_DAINT register ********************/
-#define USB_OTG_DAINT_IEPINT_Pos (0U)
-#define USB_OTG_DAINT_IEPINT_Msk (0xFFFFUL << USB_OTG_DAINT_IEPINT_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_DAINT_IEPINT USB_OTG_DAINT_IEPINT_Msk /*!< IN endpoint interrupt bits */
-#define USB_OTG_DAINT_OEPINT_Pos (16U)
-#define USB_OTG_DAINT_OEPINT_Msk (0xFFFFUL << USB_OTG_DAINT_OEPINT_Pos) /*!< 0xFFFF0000 */
-#define USB_OTG_DAINT_OEPINT USB_OTG_DAINT_OEPINT_Msk /*!< OUT endpoint interrupt bits */
-
-/******************** Bit definition for USB_OTG_HAINTMSK register ********************/
-#define USB_OTG_HAINTMSK_HAINTM_Pos (0U)
-#define USB_OTG_HAINTMSK_HAINTM_Msk (0xFFFFUL << USB_OTG_HAINTMSK_HAINTM_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_HAINTMSK_HAINTM USB_OTG_HAINTMSK_HAINTM_Msk /*!< Channel interrupt mask */
-
-/******************** Bit definition for USB_OTG_GRXSTSP register ********************/
-#define USB_OTG_GRXSTSP_EPNUM_Pos (0U)
-#define USB_OTG_GRXSTSP_EPNUM_Msk (0xFUL << USB_OTG_GRXSTSP_EPNUM_Pos) /*!< 0x0000000F */
-#define USB_OTG_GRXSTSP_EPNUM USB_OTG_GRXSTSP_EPNUM_Msk /*!< IN EP interrupt mask bits */
-#define USB_OTG_GRXSTSP_BCNT_Pos (4U)
-#define USB_OTG_GRXSTSP_BCNT_Msk (0x7FFUL << USB_OTG_GRXSTSP_BCNT_Pos) /*!< 0x00007FF0 */
-#define USB_OTG_GRXSTSP_BCNT USB_OTG_GRXSTSP_BCNT_Msk /*!< OUT EP interrupt mask bits */
-#define USB_OTG_GRXSTSP_DPID_Pos (15U)
-#define USB_OTG_GRXSTSP_DPID_Msk (0x3UL << USB_OTG_GRXSTSP_DPID_Pos) /*!< 0x00018000 */
-#define USB_OTG_GRXSTSP_DPID USB_OTG_GRXSTSP_DPID_Msk /*!< OUT EP interrupt mask bits */
-#define USB_OTG_GRXSTSP_PKTSTS_Pos (17U)
-#define USB_OTG_GRXSTSP_PKTSTS_Msk (0xFUL << USB_OTG_GRXSTSP_PKTSTS_Pos) /*!< 0x001E0000 */
-#define USB_OTG_GRXSTSP_PKTSTS USB_OTG_GRXSTSP_PKTSTS_Msk /*!< OUT EP interrupt mask bits */
-
-/******************** Bit definition for USB_OTG_DAINTMSK register ********************/
-#define USB_OTG_DAINTMSK_IEPM_Pos (0U)
-#define USB_OTG_DAINTMSK_IEPM_Msk (0xFFFFUL << USB_OTG_DAINTMSK_IEPM_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_DAINTMSK_IEPM USB_OTG_DAINTMSK_IEPM_Msk /*!< IN EP interrupt mask bits */
-#define USB_OTG_DAINTMSK_OEPM_Pos (16U)
-#define USB_OTG_DAINTMSK_OEPM_Msk (0xFFFFUL << USB_OTG_DAINTMSK_OEPM_Pos) /*!< 0xFFFF0000 */
-#define USB_OTG_DAINTMSK_OEPM USB_OTG_DAINTMSK_OEPM_Msk /*!< OUT EP interrupt mask bits */
-
-/******************** Bit definition for USB_OTG_GRXFSIZ register ********************/
-#define USB_OTG_GRXFSIZ_RXFD_Pos (0U)
-#define USB_OTG_GRXFSIZ_RXFD_Msk (0xFFFFUL << USB_OTG_GRXFSIZ_RXFD_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_GRXFSIZ_RXFD USB_OTG_GRXFSIZ_RXFD_Msk /*!< RxFIFO depth */
-
-/******************** Bit definition for USB_OTG_DVBUSDIS register ********************/
-#define USB_OTG_DVBUSDIS_VBUSDT_Pos (0U)
-#define USB_OTG_DVBUSDIS_VBUSDT_Msk (0xFFFFUL << USB_OTG_DVBUSDIS_VBUSDT_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_DVBUSDIS_VBUSDT USB_OTG_DVBUSDIS_VBUSDT_Msk /*!< Device VBUS discharge time */
-
-/******************** Bit definition for OTG register ********************/
-#define USB_OTG_NPTXFSA_Pos (0U)
-#define USB_OTG_NPTXFSA_Msk (0xFFFFUL << USB_OTG_NPTXFSA_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_NPTXFSA USB_OTG_NPTXFSA_Msk /*!< Nonperiodic transmit RAM start address */
-#define USB_OTG_NPTXFD_Pos (16U)
-#define USB_OTG_NPTXFD_Msk (0xFFFFUL << USB_OTG_NPTXFD_Pos) /*!< 0xFFFF0000 */
-#define USB_OTG_NPTXFD USB_OTG_NPTXFD_Msk /*!< Nonperiodic TxFIFO depth */
-#define USB_OTG_TX0FSA_Pos (0U)
-#define USB_OTG_TX0FSA_Msk (0xFFFFUL << USB_OTG_TX0FSA_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_TX0FSA USB_OTG_TX0FSA_Msk /*!< Endpoint 0 transmit RAM start address */
-#define USB_OTG_TX0FD_Pos (16U)
-#define USB_OTG_TX0FD_Msk (0xFFFFUL << USB_OTG_TX0FD_Pos) /*!< 0xFFFF0000 */
-#define USB_OTG_TX0FD USB_OTG_TX0FD_Msk /*!< Endpoint 0 TxFIFO depth */
-
-/******************** Bit definition for USB_OTG_DVBUSPULSE register ********************/
-#define USB_OTG_DVBUSPULSE_DVBUSP_Pos (0U)
-#define USB_OTG_DVBUSPULSE_DVBUSP_Msk (0xFFFUL << USB_OTG_DVBUSPULSE_DVBUSP_Pos) /*!< 0x00000FFF */
-#define USB_OTG_DVBUSPULSE_DVBUSP USB_OTG_DVBUSPULSE_DVBUSP_Msk /*!< Device VBUS pulsing time */
-
-/******************** Bit definition for USB_OTG_GNPTXSTS register ********************/
-#define USB_OTG_GNPTXSTS_NPTXFSAV_Pos (0U)
-#define USB_OTG_GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << USB_OTG_GNPTXSTS_NPTXFSAV_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_GNPTXSTS_NPTXFSAV USB_OTG_GNPTXSTS_NPTXFSAV_Msk /*!< Nonperiodic TxFIFO space available */
-
-#define USB_OTG_GNPTXSTS_NPTQXSAV_Pos (16U)
-#define USB_OTG_GNPTXSTS_NPTQXSAV_Msk (0xFFUL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00FF0000 */
-#define USB_OTG_GNPTXSTS_NPTQXSAV USB_OTG_GNPTXSTS_NPTQXSAV_Msk /*!< Nonperiodic transmit request queue space available */
-#define USB_OTG_GNPTXSTS_NPTQXSAV_0 (0x01UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00010000 */
-#define USB_OTG_GNPTXSTS_NPTQXSAV_1 (0x02UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00020000 */
-#define USB_OTG_GNPTXSTS_NPTQXSAV_2 (0x04UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00040000 */
-#define USB_OTG_GNPTXSTS_NPTQXSAV_3 (0x08UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00080000 */
-#define USB_OTG_GNPTXSTS_NPTQXSAV_4 (0x10UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00100000 */
-#define USB_OTG_GNPTXSTS_NPTQXSAV_5 (0x20UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00200000 */
-#define USB_OTG_GNPTXSTS_NPTQXSAV_6 (0x40UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00400000 */
-#define USB_OTG_GNPTXSTS_NPTQXSAV_7 (0x80UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00800000 */
-
-#define USB_OTG_GNPTXSTS_NPTXQTOP_Pos (24U)
-#define USB_OTG_GNPTXSTS_NPTXQTOP_Msk (0x7FUL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x7F000000 */
-#define USB_OTG_GNPTXSTS_NPTXQTOP USB_OTG_GNPTXSTS_NPTXQTOP_Msk /*!< Top of the nonperiodic transmit request queue */
-#define USB_OTG_GNPTXSTS_NPTXQTOP_0 (0x01UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x01000000 */
-#define USB_OTG_GNPTXSTS_NPTXQTOP_1 (0x02UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x02000000 */
-#define USB_OTG_GNPTXSTS_NPTXQTOP_2 (0x04UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x04000000 */
-#define USB_OTG_GNPTXSTS_NPTXQTOP_3 (0x08UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x08000000 */
-#define USB_OTG_GNPTXSTS_NPTXQTOP_4 (0x10UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x10000000 */
-#define USB_OTG_GNPTXSTS_NPTXQTOP_5 (0x20UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x20000000 */
-#define USB_OTG_GNPTXSTS_NPTXQTOP_6 (0x40UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x40000000 */
-
-/******************** Bit definition for USB_OTG_DTHRCTL register ********************/
-#define USB_OTG_DTHRCTL_NONISOTHREN_Pos (0U)
-#define USB_OTG_DTHRCTL_NONISOTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_NONISOTHREN_Pos) /*!< 0x00000001 */
-#define USB_OTG_DTHRCTL_NONISOTHREN USB_OTG_DTHRCTL_NONISOTHREN_Msk /*!< Nonisochronous IN endpoints threshold enable */
-#define USB_OTG_DTHRCTL_ISOTHREN_Pos (1U)
-#define USB_OTG_DTHRCTL_ISOTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_ISOTHREN_Pos) /*!< 0x00000002 */
-#define USB_OTG_DTHRCTL_ISOTHREN USB_OTG_DTHRCTL_ISOTHREN_Msk /*!< ISO IN endpoint threshold enable */
-
-#define USB_OTG_DTHRCTL_TXTHRLEN_Pos (2U)
-#define USB_OTG_DTHRCTL_TXTHRLEN_Msk (0x1FFUL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x000007FC */
-#define USB_OTG_DTHRCTL_TXTHRLEN USB_OTG_DTHRCTL_TXTHRLEN_Msk /*!< Transmit threshold length */
-#define USB_OTG_DTHRCTL_TXTHRLEN_0 (0x001UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000004 */
-#define USB_OTG_DTHRCTL_TXTHRLEN_1 (0x002UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000008 */
-#define USB_OTG_DTHRCTL_TXTHRLEN_2 (0x004UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000010 */
-#define USB_OTG_DTHRCTL_TXTHRLEN_3 (0x008UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000020 */
-#define USB_OTG_DTHRCTL_TXTHRLEN_4 (0x010UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000040 */
-#define USB_OTG_DTHRCTL_TXTHRLEN_5 (0x020UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000080 */
-#define USB_OTG_DTHRCTL_TXTHRLEN_6 (0x040UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000100 */
-#define USB_OTG_DTHRCTL_TXTHRLEN_7 (0x080UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000200 */
-#define USB_OTG_DTHRCTL_TXTHRLEN_8 (0x100UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000400 */
-#define USB_OTG_DTHRCTL_RXTHREN_Pos (16U)
-#define USB_OTG_DTHRCTL_RXTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_RXTHREN_Pos) /*!< 0x00010000 */
-#define USB_OTG_DTHRCTL_RXTHREN USB_OTG_DTHRCTL_RXTHREN_Msk /*!< Receive threshold enable */
-
-#define USB_OTG_DTHRCTL_RXTHRLEN_Pos (17U)
-#define USB_OTG_DTHRCTL_RXTHRLEN_Msk (0x1FFUL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x03FE0000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN USB_OTG_DTHRCTL_RXTHRLEN_Msk /*!< Receive threshold length */
-#define USB_OTG_DTHRCTL_RXTHRLEN_0 (0x001UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00020000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN_1 (0x002UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00040000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN_2 (0x004UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00080000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN_3 (0x008UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00100000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN_4 (0x010UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00200000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN_5 (0x020UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00400000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN_6 (0x040UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00800000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN_7 (0x080UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x01000000 */
-#define USB_OTG_DTHRCTL_RXTHRLEN_8 (0x100UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x02000000 */
-#define USB_OTG_DTHRCTL_ARPEN_Pos (27U)
-#define USB_OTG_DTHRCTL_ARPEN_Msk (0x1UL << USB_OTG_DTHRCTL_ARPEN_Pos) /*!< 0x08000000 */
-#define USB_OTG_DTHRCTL_ARPEN USB_OTG_DTHRCTL_ARPEN_Msk /*!< Arbiter parking enable */
-
-/******************** Bit definition for USB_OTG_DIEPEMPMSK register ********************/
-#define USB_OTG_DIEPEMPMSK_INEPTXFEM_Pos (0U)
-#define USB_OTG_DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << USB_OTG_DIEPEMPMSK_INEPTXFEM_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_DIEPEMPMSK_INEPTXFEM USB_OTG_DIEPEMPMSK_INEPTXFEM_Msk /*!< IN EP Tx FIFO empty interrupt mask bits */
-
-/******************** Bit definition for USB_OTG_DEACHINT register ********************/
-#define USB_OTG_DEACHINT_IEP1INT_Pos (1U)
-#define USB_OTG_DEACHINT_IEP1INT_Msk (0x1UL << USB_OTG_DEACHINT_IEP1INT_Pos) /*!< 0x00000002 */
-#define USB_OTG_DEACHINT_IEP1INT USB_OTG_DEACHINT_IEP1INT_Msk /*!< IN endpoint 1interrupt bit */
-#define USB_OTG_DEACHINT_OEP1INT_Pos (17U)
-#define USB_OTG_DEACHINT_OEP1INT_Msk (0x1UL << USB_OTG_DEACHINT_OEP1INT_Pos) /*!< 0x00020000 */
-#define USB_OTG_DEACHINT_OEP1INT USB_OTG_DEACHINT_OEP1INT_Msk /*!< OUT endpoint 1 interrupt bit */
-
-/******************** Bit definition for USB_OTG_GCCFG register ********************/
-#define USB_OTG_GCCFG_PWRDWN_Pos (16U)
-#define USB_OTG_GCCFG_PWRDWN_Msk (0x1UL << USB_OTG_GCCFG_PWRDWN_Pos) /*!< 0x00010000 */
-#define USB_OTG_GCCFG_PWRDWN USB_OTG_GCCFG_PWRDWN_Msk /*!< Power down */
-#define USB_OTG_GCCFG_VBUSASEN_Pos (18U)
-#define USB_OTG_GCCFG_VBUSASEN_Msk (0x1UL << USB_OTG_GCCFG_VBUSASEN_Pos) /*!< 0x00040000 */
-#define USB_OTG_GCCFG_VBUSASEN USB_OTG_GCCFG_VBUSASEN_Msk /*!< Enable the VBUS sensing device */
-#define USB_OTG_GCCFG_VBUSBSEN_Pos (19U)
-#define USB_OTG_GCCFG_VBUSBSEN_Msk (0x1UL << USB_OTG_GCCFG_VBUSBSEN_Pos) /*!< 0x00080000 */
-#define USB_OTG_GCCFG_VBUSBSEN USB_OTG_GCCFG_VBUSBSEN_Msk /*!< Enable the VBUS sensing device */
-#define USB_OTG_GCCFG_SOFOUTEN_Pos (20U)
-#define USB_OTG_GCCFG_SOFOUTEN_Msk (0x1UL << USB_OTG_GCCFG_SOFOUTEN_Pos) /*!< 0x00100000 */
-#define USB_OTG_GCCFG_SOFOUTEN USB_OTG_GCCFG_SOFOUTEN_Msk /*!< SOF output enable */
-
-/******************** Bit definition for USB_OTG_DEACHINTMSK register ********************/
-#define USB_OTG_DEACHINTMSK_IEP1INTM_Pos (1U)
-#define USB_OTG_DEACHINTMSK_IEP1INTM_Msk (0x1UL << USB_OTG_DEACHINTMSK_IEP1INTM_Pos) /*!< 0x00000002 */
-#define USB_OTG_DEACHINTMSK_IEP1INTM USB_OTG_DEACHINTMSK_IEP1INTM_Msk /*!< IN Endpoint 1 interrupt mask bit */
-#define USB_OTG_DEACHINTMSK_OEP1INTM_Pos (17U)
-#define USB_OTG_DEACHINTMSK_OEP1INTM_Msk (0x1UL << USB_OTG_DEACHINTMSK_OEP1INTM_Pos) /*!< 0x00020000 */
-#define USB_OTG_DEACHINTMSK_OEP1INTM USB_OTG_DEACHINTMSK_OEP1INTM_Msk /*!< OUT Endpoint 1 interrupt mask bit */
-
-/******************** Bit definition for USB_OTG_CID register ********************/
-#define USB_OTG_CID_PRODUCT_ID_Pos (0U)
-#define USB_OTG_CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << USB_OTG_CID_PRODUCT_ID_Pos) /*!< 0xFFFFFFFF */
-#define USB_OTG_CID_PRODUCT_ID USB_OTG_CID_PRODUCT_ID_Msk /*!< Product ID field */
-
-/******************** Bit definition for USB_OTG_DIEPEACHMSK1 register ********************/
-#define USB_OTG_DIEPEACHMSK1_XFRCM_Pos (0U)
-#define USB_OTG_DIEPEACHMSK1_XFRCM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_XFRCM_Pos) /*!< 0x00000001 */
-#define USB_OTG_DIEPEACHMSK1_XFRCM USB_OTG_DIEPEACHMSK1_XFRCM_Msk /*!< Transfer completed interrupt mask */
-#define USB_OTG_DIEPEACHMSK1_EPDM_Pos (1U)
-#define USB_OTG_DIEPEACHMSK1_EPDM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_EPDM_Pos) /*!< 0x00000002 */
-#define USB_OTG_DIEPEACHMSK1_EPDM USB_OTG_DIEPEACHMSK1_EPDM_Msk /*!< Endpoint disabled interrupt mask */
-#define USB_OTG_DIEPEACHMSK1_TOM_Pos (3U)
-#define USB_OTG_DIEPEACHMSK1_TOM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_TOM_Pos) /*!< 0x00000008 */
-#define USB_OTG_DIEPEACHMSK1_TOM USB_OTG_DIEPEACHMSK1_TOM_Msk /*!< Timeout condition mask (nonisochronous endpoints) */
-#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Pos (4U)
-#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Pos) /*!< 0x00000010 */
-#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */
-#define USB_OTG_DIEPEACHMSK1_INEPNMM_Pos (5U)
-#define USB_OTG_DIEPEACHMSK1_INEPNMM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_INEPNMM_Pos) /*!< 0x00000020 */
-#define USB_OTG_DIEPEACHMSK1_INEPNMM USB_OTG_DIEPEACHMSK1_INEPNMM_Msk /*!< IN token received with EP mismatch mask */
-#define USB_OTG_DIEPEACHMSK1_INEPNEM_Pos (6U)
-#define USB_OTG_DIEPEACHMSK1_INEPNEM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_INEPNEM_Pos) /*!< 0x00000040 */
-#define USB_OTG_DIEPEACHMSK1_INEPNEM USB_OTG_DIEPEACHMSK1_INEPNEM_Msk /*!< IN endpoint NAK effective mask */
-#define USB_OTG_DIEPEACHMSK1_TXFURM_Pos (8U)
-#define USB_OTG_DIEPEACHMSK1_TXFURM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_TXFURM_Pos) /*!< 0x00000100 */
-#define USB_OTG_DIEPEACHMSK1_TXFURM USB_OTG_DIEPEACHMSK1_TXFURM_Msk /*!< FIFO underrun mask */
-#define USB_OTG_DIEPEACHMSK1_BIM_Pos (9U)
-#define USB_OTG_DIEPEACHMSK1_BIM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_BIM_Pos) /*!< 0x00000200 */
-#define USB_OTG_DIEPEACHMSK1_BIM USB_OTG_DIEPEACHMSK1_BIM_Msk /*!< BNA interrupt mask */
-#define USB_OTG_DIEPEACHMSK1_NAKM_Pos (13U)
-#define USB_OTG_DIEPEACHMSK1_NAKM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_NAKM_Pos) /*!< 0x00002000 */
-#define USB_OTG_DIEPEACHMSK1_NAKM USB_OTG_DIEPEACHMSK1_NAKM_Msk /*!< NAK interrupt mask */
-
-/******************** Bit definition for USB_OTG_HPRT register ********************/
-#define USB_OTG_HPRT_PCSTS_Pos (0U)
-#define USB_OTG_HPRT_PCSTS_Msk (0x1UL << USB_OTG_HPRT_PCSTS_Pos) /*!< 0x00000001 */
-#define USB_OTG_HPRT_PCSTS USB_OTG_HPRT_PCSTS_Msk /*!< Port connect status */
-#define USB_OTG_HPRT_PCDET_Pos (1U)
-#define USB_OTG_HPRT_PCDET_Msk (0x1UL << USB_OTG_HPRT_PCDET_Pos) /*!< 0x00000002 */
-#define USB_OTG_HPRT_PCDET USB_OTG_HPRT_PCDET_Msk /*!< Port connect detected */
-#define USB_OTG_HPRT_PENA_Pos (2U)
-#define USB_OTG_HPRT_PENA_Msk (0x1UL << USB_OTG_HPRT_PENA_Pos) /*!< 0x00000004 */
-#define USB_OTG_HPRT_PENA USB_OTG_HPRT_PENA_Msk /*!< Port enable */
-#define USB_OTG_HPRT_PENCHNG_Pos (3U)
-#define USB_OTG_HPRT_PENCHNG_Msk (0x1UL << USB_OTG_HPRT_PENCHNG_Pos) /*!< 0x00000008 */
-#define USB_OTG_HPRT_PENCHNG USB_OTG_HPRT_PENCHNG_Msk /*!< Port enable/disable change */
-#define USB_OTG_HPRT_POCA_Pos (4U)
-#define USB_OTG_HPRT_POCA_Msk (0x1UL << USB_OTG_HPRT_POCA_Pos) /*!< 0x00000010 */
-#define USB_OTG_HPRT_POCA USB_OTG_HPRT_POCA_Msk /*!< Port overcurrent active */
-#define USB_OTG_HPRT_POCCHNG_Pos (5U)
-#define USB_OTG_HPRT_POCCHNG_Msk (0x1UL << USB_OTG_HPRT_POCCHNG_Pos) /*!< 0x00000020 */
-#define USB_OTG_HPRT_POCCHNG USB_OTG_HPRT_POCCHNG_Msk /*!< Port overcurrent change */
-#define USB_OTG_HPRT_PRES_Pos (6U)
-#define USB_OTG_HPRT_PRES_Msk (0x1UL << USB_OTG_HPRT_PRES_Pos) /*!< 0x00000040 */
-#define USB_OTG_HPRT_PRES USB_OTG_HPRT_PRES_Msk /*!< Port resume */
-#define USB_OTG_HPRT_PSUSP_Pos (7U)
-#define USB_OTG_HPRT_PSUSP_Msk (0x1UL << USB_OTG_HPRT_PSUSP_Pos) /*!< 0x00000080 */
-#define USB_OTG_HPRT_PSUSP USB_OTG_HPRT_PSUSP_Msk /*!< Port suspend */
-#define USB_OTG_HPRT_PRST_Pos (8U)
-#define USB_OTG_HPRT_PRST_Msk (0x1UL << USB_OTG_HPRT_PRST_Pos) /*!< 0x00000100 */
-#define USB_OTG_HPRT_PRST USB_OTG_HPRT_PRST_Msk /*!< Port reset */
-
-#define USB_OTG_HPRT_PLSTS_Pos (10U)
-#define USB_OTG_HPRT_PLSTS_Msk (0x3UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000C00 */
-#define USB_OTG_HPRT_PLSTS USB_OTG_HPRT_PLSTS_Msk /*!< Port line status */
-#define USB_OTG_HPRT_PLSTS_0 (0x1UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000400 */
-#define USB_OTG_HPRT_PLSTS_1 (0x2UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000800 */
-#define USB_OTG_HPRT_PPWR_Pos (12U)
-#define USB_OTG_HPRT_PPWR_Msk (0x1UL << USB_OTG_HPRT_PPWR_Pos) /*!< 0x00001000 */
-#define USB_OTG_HPRT_PPWR USB_OTG_HPRT_PPWR_Msk /*!< Port power */
-
-#define USB_OTG_HPRT_PTCTL_Pos (13U)
-#define USB_OTG_HPRT_PTCTL_Msk (0xFUL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x0001E000 */
-#define USB_OTG_HPRT_PTCTL USB_OTG_HPRT_PTCTL_Msk /*!< Port test control */
-#define USB_OTG_HPRT_PTCTL_0 (0x1UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00002000 */
-#define USB_OTG_HPRT_PTCTL_1 (0x2UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00004000 */
-#define USB_OTG_HPRT_PTCTL_2 (0x4UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00008000 */
-#define USB_OTG_HPRT_PTCTL_3 (0x8UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00010000 */
-
-#define USB_OTG_HPRT_PSPD_Pos (17U)
-#define USB_OTG_HPRT_PSPD_Msk (0x3UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00060000 */
-#define USB_OTG_HPRT_PSPD USB_OTG_HPRT_PSPD_Msk /*!< Port speed */
-#define USB_OTG_HPRT_PSPD_0 (0x1UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00020000 */
-#define USB_OTG_HPRT_PSPD_1 (0x2UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00040000 */
-
-/******************** Bit definition for USB_OTG_DOEPEACHMSK1 register ********************/
-#define USB_OTG_DOEPEACHMSK1_XFRCM_Pos (0U)
-#define USB_OTG_DOEPEACHMSK1_XFRCM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_XFRCM_Pos) /*!< 0x00000001 */
-#define USB_OTG_DOEPEACHMSK1_XFRCM USB_OTG_DOEPEACHMSK1_XFRCM_Msk /*!< Transfer completed interrupt mask */
-#define USB_OTG_DOEPEACHMSK1_EPDM_Pos (1U)
-#define USB_OTG_DOEPEACHMSK1_EPDM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_EPDM_Pos) /*!< 0x00000002 */
-#define USB_OTG_DOEPEACHMSK1_EPDM USB_OTG_DOEPEACHMSK1_EPDM_Msk /*!< Endpoint disabled interrupt mask */
-#define USB_OTG_DOEPEACHMSK1_TOM_Pos (3U)
-#define USB_OTG_DOEPEACHMSK1_TOM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_TOM_Pos) /*!< 0x00000008 */
-#define USB_OTG_DOEPEACHMSK1_TOM USB_OTG_DOEPEACHMSK1_TOM_Msk /*!< Timeout condition mask */
-#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Pos (4U)
-#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Pos) /*!< 0x00000010 */
-#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */
-#define USB_OTG_DOEPEACHMSK1_INEPNMM_Pos (5U)
-#define USB_OTG_DOEPEACHMSK1_INEPNMM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_INEPNMM_Pos) /*!< 0x00000020 */
-#define USB_OTG_DOEPEACHMSK1_INEPNMM USB_OTG_DOEPEACHMSK1_INEPNMM_Msk /*!< IN token received with EP mismatch mask */
-#define USB_OTG_DOEPEACHMSK1_INEPNEM_Pos (6U)
-#define USB_OTG_DOEPEACHMSK1_INEPNEM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_INEPNEM_Pos) /*!< 0x00000040 */
-#define USB_OTG_DOEPEACHMSK1_INEPNEM USB_OTG_DOEPEACHMSK1_INEPNEM_Msk /*!< IN endpoint NAK effective mask */
-#define USB_OTG_DOEPEACHMSK1_TXFURM_Pos (8U)
-#define USB_OTG_DOEPEACHMSK1_TXFURM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_TXFURM_Pos) /*!< 0x00000100 */
-#define USB_OTG_DOEPEACHMSK1_TXFURM USB_OTG_DOEPEACHMSK1_TXFURM_Msk /*!< OUT packet error mask */
-#define USB_OTG_DOEPEACHMSK1_BIM_Pos (9U)
-#define USB_OTG_DOEPEACHMSK1_BIM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_BIM_Pos) /*!< 0x00000200 */
-#define USB_OTG_DOEPEACHMSK1_BIM USB_OTG_DOEPEACHMSK1_BIM_Msk /*!< BNA interrupt mask */
-#define USB_OTG_DOEPEACHMSK1_BERRM_Pos (12U)
-#define USB_OTG_DOEPEACHMSK1_BERRM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_BERRM_Pos) /*!< 0x00001000 */
-#define USB_OTG_DOEPEACHMSK1_BERRM USB_OTG_DOEPEACHMSK1_BERRM_Msk /*!< Bubble error interrupt mask */
-#define USB_OTG_DOEPEACHMSK1_NAKM_Pos (13U)
-#define USB_OTG_DOEPEACHMSK1_NAKM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_NAKM_Pos) /*!< 0x00002000 */
-#define USB_OTG_DOEPEACHMSK1_NAKM USB_OTG_DOEPEACHMSK1_NAKM_Msk /*!< NAK interrupt mask */
-#define USB_OTG_DOEPEACHMSK1_NYETM_Pos (14U)
-#define USB_OTG_DOEPEACHMSK1_NYETM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_NYETM_Pos) /*!< 0x00004000 */
-#define USB_OTG_DOEPEACHMSK1_NYETM USB_OTG_DOEPEACHMSK1_NYETM_Msk /*!< NYET interrupt mask */
-
-/******************** Bit definition for USB_OTG_HPTXFSIZ register ********************/
-#define USB_OTG_HPTXFSIZ_PTXSA_Pos (0U)
-#define USB_OTG_HPTXFSIZ_PTXSA_Msk (0xFFFFUL << USB_OTG_HPTXFSIZ_PTXSA_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_HPTXFSIZ_PTXSA USB_OTG_HPTXFSIZ_PTXSA_Msk /*!< Host periodic TxFIFO start address */
-#define USB_OTG_HPTXFSIZ_PTXFD_Pos (16U)
-#define USB_OTG_HPTXFSIZ_PTXFD_Msk (0xFFFFUL << USB_OTG_HPTXFSIZ_PTXFD_Pos) /*!< 0xFFFF0000 */
-#define USB_OTG_HPTXFSIZ_PTXFD USB_OTG_HPTXFSIZ_PTXFD_Msk /*!< Host periodic TxFIFO depth */
-
-/******************** Bit definition for USB_OTG_DIEPCTL register ********************/
-#define USB_OTG_DIEPCTL_MPSIZ_Pos (0U)
-#define USB_OTG_DIEPCTL_MPSIZ_Msk (0x7FFUL << USB_OTG_DIEPCTL_MPSIZ_Pos) /*!< 0x000007FF */
-#define USB_OTG_DIEPCTL_MPSIZ USB_OTG_DIEPCTL_MPSIZ_Msk /*!< Maximum packet size */
-#define USB_OTG_DIEPCTL_USBAEP_Pos (15U)
-#define USB_OTG_DIEPCTL_USBAEP_Msk (0x1UL << USB_OTG_DIEPCTL_USBAEP_Pos) /*!< 0x00008000 */
-#define USB_OTG_DIEPCTL_USBAEP USB_OTG_DIEPCTL_USBAEP_Msk /*!< USB active endpoint */
-#define USB_OTG_DIEPCTL_EONUM_DPID_Pos (16U)
-#define USB_OTG_DIEPCTL_EONUM_DPID_Msk (0x1UL << USB_OTG_DIEPCTL_EONUM_DPID_Pos) /*!< 0x00010000 */
-#define USB_OTG_DIEPCTL_EONUM_DPID USB_OTG_DIEPCTL_EONUM_DPID_Msk /*!< Even/odd frame */
-#define USB_OTG_DIEPCTL_NAKSTS_Pos (17U)
-#define USB_OTG_DIEPCTL_NAKSTS_Msk (0x1UL << USB_OTG_DIEPCTL_NAKSTS_Pos) /*!< 0x00020000 */
-#define USB_OTG_DIEPCTL_NAKSTS USB_OTG_DIEPCTL_NAKSTS_Msk /*!< NAK status */
-
-#define USB_OTG_DIEPCTL_EPTYP_Pos (18U)
-#define USB_OTG_DIEPCTL_EPTYP_Msk (0x3UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x000C0000 */
-#define USB_OTG_DIEPCTL_EPTYP USB_OTG_DIEPCTL_EPTYP_Msk /*!< Endpoint type */
-#define USB_OTG_DIEPCTL_EPTYP_0 (0x1UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x00040000 */
-#define USB_OTG_DIEPCTL_EPTYP_1 (0x2UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x00080000 */
-#define USB_OTG_DIEPCTL_STALL_Pos (21U)
-#define USB_OTG_DIEPCTL_STALL_Msk (0x1UL << USB_OTG_DIEPCTL_STALL_Pos) /*!< 0x00200000 */
-#define USB_OTG_DIEPCTL_STALL USB_OTG_DIEPCTL_STALL_Msk /*!< STALL handshake */
-
-#define USB_OTG_DIEPCTL_TXFNUM_Pos (22U)
-#define USB_OTG_DIEPCTL_TXFNUM_Msk (0xFUL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x03C00000 */
-#define USB_OTG_DIEPCTL_TXFNUM USB_OTG_DIEPCTL_TXFNUM_Msk /*!< TxFIFO number */
-#define USB_OTG_DIEPCTL_TXFNUM_0 (0x1UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x00400000 */
-#define USB_OTG_DIEPCTL_TXFNUM_1 (0x2UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x00800000 */
-#define USB_OTG_DIEPCTL_TXFNUM_2 (0x4UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x01000000 */
-#define USB_OTG_DIEPCTL_TXFNUM_3 (0x8UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x02000000 */
-#define USB_OTG_DIEPCTL_CNAK_Pos (26U)
-#define USB_OTG_DIEPCTL_CNAK_Msk (0x1UL << USB_OTG_DIEPCTL_CNAK_Pos) /*!< 0x04000000 */
-#define USB_OTG_DIEPCTL_CNAK USB_OTG_DIEPCTL_CNAK_Msk /*!< Clear NAK */
-#define USB_OTG_DIEPCTL_SNAK_Pos (27U)
-#define USB_OTG_DIEPCTL_SNAK_Msk (0x1UL << USB_OTG_DIEPCTL_SNAK_Pos) /*!< 0x08000000 */
-#define USB_OTG_DIEPCTL_SNAK USB_OTG_DIEPCTL_SNAK_Msk /*!< Set NAK */
-#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Pos (28U)
-#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Pos) /*!< 0x10000000 */
-#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk /*!< Set DATA0 PID */
-#define USB_OTG_DIEPCTL_SODDFRM_Pos (29U)
-#define USB_OTG_DIEPCTL_SODDFRM_Msk (0x1UL << USB_OTG_DIEPCTL_SODDFRM_Pos) /*!< 0x20000000 */
-#define USB_OTG_DIEPCTL_SODDFRM USB_OTG_DIEPCTL_SODDFRM_Msk /*!< Set odd frame */
-#define USB_OTG_DIEPCTL_EPDIS_Pos (30U)
-#define USB_OTG_DIEPCTL_EPDIS_Msk (0x1UL << USB_OTG_DIEPCTL_EPDIS_Pos) /*!< 0x40000000 */
-#define USB_OTG_DIEPCTL_EPDIS USB_OTG_DIEPCTL_EPDIS_Msk /*!< Endpoint disable */
-#define USB_OTG_DIEPCTL_EPENA_Pos (31U)
-#define USB_OTG_DIEPCTL_EPENA_Msk (0x1UL << USB_OTG_DIEPCTL_EPENA_Pos) /*!< 0x80000000 */
-#define USB_OTG_DIEPCTL_EPENA USB_OTG_DIEPCTL_EPENA_Msk /*!< Endpoint enable */
-
-/******************** Bit definition for USB_OTG_HCCHAR register ********************/
-#define USB_OTG_HCCHAR_MPSIZ_Pos (0U)
-#define USB_OTG_HCCHAR_MPSIZ_Msk (0x7FFUL << USB_OTG_HCCHAR_MPSIZ_Pos) /*!< 0x000007FF */
-#define USB_OTG_HCCHAR_MPSIZ USB_OTG_HCCHAR_MPSIZ_Msk /*!< Maximum packet size */
-
-#define USB_OTG_HCCHAR_EPNUM_Pos (11U)
-#define USB_OTG_HCCHAR_EPNUM_Msk (0xFUL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00007800 */
-#define USB_OTG_HCCHAR_EPNUM USB_OTG_HCCHAR_EPNUM_Msk /*!< Endpoint number */
-#define USB_OTG_HCCHAR_EPNUM_0 (0x1UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00000800 */
-#define USB_OTG_HCCHAR_EPNUM_1 (0x2UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00001000 */
-#define USB_OTG_HCCHAR_EPNUM_2 (0x4UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00002000 */
-#define USB_OTG_HCCHAR_EPNUM_3 (0x8UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00004000 */
-#define USB_OTG_HCCHAR_EPDIR_Pos (15U)
-#define USB_OTG_HCCHAR_EPDIR_Msk (0x1UL << USB_OTG_HCCHAR_EPDIR_Pos) /*!< 0x00008000 */
-#define USB_OTG_HCCHAR_EPDIR USB_OTG_HCCHAR_EPDIR_Msk /*!< Endpoint direction */
-#define USB_OTG_HCCHAR_LSDEV_Pos (17U)
-#define USB_OTG_HCCHAR_LSDEV_Msk (0x1UL << USB_OTG_HCCHAR_LSDEV_Pos) /*!< 0x00020000 */
-#define USB_OTG_HCCHAR_LSDEV USB_OTG_HCCHAR_LSDEV_Msk /*!< Low-speed device */
-
-#define USB_OTG_HCCHAR_EPTYP_Pos (18U)
-#define USB_OTG_HCCHAR_EPTYP_Msk (0x3UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x000C0000 */
-#define USB_OTG_HCCHAR_EPTYP USB_OTG_HCCHAR_EPTYP_Msk /*!< Endpoint type */
-#define USB_OTG_HCCHAR_EPTYP_0 (0x1UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x00040000 */
-#define USB_OTG_HCCHAR_EPTYP_1 (0x2UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x00080000 */
-
-#define USB_OTG_HCCHAR_MC_Pos (20U)
-#define USB_OTG_HCCHAR_MC_Msk (0x3UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00300000 */
-#define USB_OTG_HCCHAR_MC USB_OTG_HCCHAR_MC_Msk /*!< Multi Count (MC) / Error Count (EC) */
-#define USB_OTG_HCCHAR_MC_0 (0x1UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00100000 */
-#define USB_OTG_HCCHAR_MC_1 (0x2UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00200000 */
-
-#define USB_OTG_HCCHAR_DAD_Pos (22U)
-#define USB_OTG_HCCHAR_DAD_Msk (0x7FUL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x1FC00000 */
-#define USB_OTG_HCCHAR_DAD USB_OTG_HCCHAR_DAD_Msk /*!< Device address */
-#define USB_OTG_HCCHAR_DAD_0 (0x01UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x00400000 */
-#define USB_OTG_HCCHAR_DAD_1 (0x02UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x00800000 */
-#define USB_OTG_HCCHAR_DAD_2 (0x04UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x01000000 */
-#define USB_OTG_HCCHAR_DAD_3 (0x08UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x02000000 */
-#define USB_OTG_HCCHAR_DAD_4 (0x10UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x04000000 */
-#define USB_OTG_HCCHAR_DAD_5 (0x20UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x08000000 */
-#define USB_OTG_HCCHAR_DAD_6 (0x40UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x10000000 */
-#define USB_OTG_HCCHAR_ODDFRM_Pos (29U)
-#define USB_OTG_HCCHAR_ODDFRM_Msk (0x1UL << USB_OTG_HCCHAR_ODDFRM_Pos) /*!< 0x20000000 */
-#define USB_OTG_HCCHAR_ODDFRM USB_OTG_HCCHAR_ODDFRM_Msk /*!< Odd frame */
-#define USB_OTG_HCCHAR_CHDIS_Pos (30U)
-#define USB_OTG_HCCHAR_CHDIS_Msk (0x1UL << USB_OTG_HCCHAR_CHDIS_Pos) /*!< 0x40000000 */
-#define USB_OTG_HCCHAR_CHDIS USB_OTG_HCCHAR_CHDIS_Msk /*!< Channel disable */
-#define USB_OTG_HCCHAR_CHENA_Pos (31U)
-#define USB_OTG_HCCHAR_CHENA_Msk (0x1UL << USB_OTG_HCCHAR_CHENA_Pos) /*!< 0x80000000 */
-#define USB_OTG_HCCHAR_CHENA USB_OTG_HCCHAR_CHENA_Msk /*!< Channel enable */
-
-/******************** Bit definition for USB_OTG_HCSPLT register ********************/
-
-#define USB_OTG_HCSPLT_PRTADDR_Pos (0U)
-#define USB_OTG_HCSPLT_PRTADDR_Msk (0x7FUL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x0000007F */
-#define USB_OTG_HCSPLT_PRTADDR USB_OTG_HCSPLT_PRTADDR_Msk /*!< Port address */
-#define USB_OTG_HCSPLT_PRTADDR_0 (0x01UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000001 */
-#define USB_OTG_HCSPLT_PRTADDR_1 (0x02UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000002 */
-#define USB_OTG_HCSPLT_PRTADDR_2 (0x04UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000004 */
-#define USB_OTG_HCSPLT_PRTADDR_3 (0x08UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000008 */
-#define USB_OTG_HCSPLT_PRTADDR_4 (0x10UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000010 */
-#define USB_OTG_HCSPLT_PRTADDR_5 (0x20UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000020 */
-#define USB_OTG_HCSPLT_PRTADDR_6 (0x40UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000040 */
-
-#define USB_OTG_HCSPLT_HUBADDR_Pos (7U)
-#define USB_OTG_HCSPLT_HUBADDR_Msk (0x7FUL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00003F80 */
-#define USB_OTG_HCSPLT_HUBADDR USB_OTG_HCSPLT_HUBADDR_Msk /*!< Hub address */
-#define USB_OTG_HCSPLT_HUBADDR_0 (0x01UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000080 */
-#define USB_OTG_HCSPLT_HUBADDR_1 (0x02UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000100 */
-#define USB_OTG_HCSPLT_HUBADDR_2 (0x04UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000200 */
-#define USB_OTG_HCSPLT_HUBADDR_3 (0x08UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000400 */
-#define USB_OTG_HCSPLT_HUBADDR_4 (0x10UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000800 */
-#define USB_OTG_HCSPLT_HUBADDR_5 (0x20UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00001000 */
-#define USB_OTG_HCSPLT_HUBADDR_6 (0x40UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00002000 */
-
-#define USB_OTG_HCSPLT_XACTPOS_Pos (14U)
-#define USB_OTG_HCSPLT_XACTPOS_Msk (0x3UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x0000C000 */
-#define USB_OTG_HCSPLT_XACTPOS USB_OTG_HCSPLT_XACTPOS_Msk /*!< XACTPOS */
-#define USB_OTG_HCSPLT_XACTPOS_0 (0x1UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x00004000 */
-#define USB_OTG_HCSPLT_XACTPOS_1 (0x2UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x00008000 */
-#define USB_OTG_HCSPLT_COMPLSPLT_Pos (16U)
-#define USB_OTG_HCSPLT_COMPLSPLT_Msk (0x1UL << USB_OTG_HCSPLT_COMPLSPLT_Pos) /*!< 0x00010000 */
-#define USB_OTG_HCSPLT_COMPLSPLT USB_OTG_HCSPLT_COMPLSPLT_Msk /*!< Do complete split */
-#define USB_OTG_HCSPLT_SPLITEN_Pos (31U)
-#define USB_OTG_HCSPLT_SPLITEN_Msk (0x1UL << USB_OTG_HCSPLT_SPLITEN_Pos) /*!< 0x80000000 */
-#define USB_OTG_HCSPLT_SPLITEN USB_OTG_HCSPLT_SPLITEN_Msk /*!< Split enable */
-
-/******************** Bit definition for USB_OTG_HCINT register ********************/
-#define USB_OTG_HCINT_XFRC_Pos (0U)
-#define USB_OTG_HCINT_XFRC_Msk (0x1UL << USB_OTG_HCINT_XFRC_Pos) /*!< 0x00000001 */
-#define USB_OTG_HCINT_XFRC USB_OTG_HCINT_XFRC_Msk /*!< Transfer completed */
-#define USB_OTG_HCINT_CHH_Pos (1U)
-#define USB_OTG_HCINT_CHH_Msk (0x1UL << USB_OTG_HCINT_CHH_Pos) /*!< 0x00000002 */
-#define USB_OTG_HCINT_CHH USB_OTG_HCINT_CHH_Msk /*!< Channel halted */
-#define USB_OTG_HCINT_AHBERR_Pos (2U)
-#define USB_OTG_HCINT_AHBERR_Msk (0x1UL << USB_OTG_HCINT_AHBERR_Pos) /*!< 0x00000004 */
-#define USB_OTG_HCINT_AHBERR USB_OTG_HCINT_AHBERR_Msk /*!< AHB error */
-#define USB_OTG_HCINT_STALL_Pos (3U)
-#define USB_OTG_HCINT_STALL_Msk (0x1UL << USB_OTG_HCINT_STALL_Pos) /*!< 0x00000008 */
-#define USB_OTG_HCINT_STALL USB_OTG_HCINT_STALL_Msk /*!< STALL response received interrupt */
-#define USB_OTG_HCINT_NAK_Pos (4U)
-#define USB_OTG_HCINT_NAK_Msk (0x1UL << USB_OTG_HCINT_NAK_Pos) /*!< 0x00000010 */
-#define USB_OTG_HCINT_NAK USB_OTG_HCINT_NAK_Msk /*!< NAK response received interrupt */
-#define USB_OTG_HCINT_ACK_Pos (5U)
-#define USB_OTG_HCINT_ACK_Msk (0x1UL << USB_OTG_HCINT_ACK_Pos) /*!< 0x00000020 */
-#define USB_OTG_HCINT_ACK USB_OTG_HCINT_ACK_Msk /*!< ACK response received/transmitted interrupt */
-#define USB_OTG_HCINT_NYET_Pos (6U)
-#define USB_OTG_HCINT_NYET_Msk (0x1UL << USB_OTG_HCINT_NYET_Pos) /*!< 0x00000040 */
-#define USB_OTG_HCINT_NYET USB_OTG_HCINT_NYET_Msk /*!< Response received interrupt */
-#define USB_OTG_HCINT_TXERR_Pos (7U)
-#define USB_OTG_HCINT_TXERR_Msk (0x1UL << USB_OTG_HCINT_TXERR_Pos) /*!< 0x00000080 */
-#define USB_OTG_HCINT_TXERR USB_OTG_HCINT_TXERR_Msk /*!< Transaction error */
-#define USB_OTG_HCINT_BBERR_Pos (8U)
-#define USB_OTG_HCINT_BBERR_Msk (0x1UL << USB_OTG_HCINT_BBERR_Pos) /*!< 0x00000100 */
-#define USB_OTG_HCINT_BBERR USB_OTG_HCINT_BBERR_Msk /*!< Babble error */
-#define USB_OTG_HCINT_FRMOR_Pos (9U)
-#define USB_OTG_HCINT_FRMOR_Msk (0x1UL << USB_OTG_HCINT_FRMOR_Pos) /*!< 0x00000200 */
-#define USB_OTG_HCINT_FRMOR USB_OTG_HCINT_FRMOR_Msk /*!< Frame overrun */
-#define USB_OTG_HCINT_DTERR_Pos (10U)
-#define USB_OTG_HCINT_DTERR_Msk (0x1UL << USB_OTG_HCINT_DTERR_Pos) /*!< 0x00000400 */
-#define USB_OTG_HCINT_DTERR USB_OTG_HCINT_DTERR_Msk /*!< Data toggle error */
-
-/******************** Bit definition for USB_OTG_DIEPINT register ********************/
-#define USB_OTG_DIEPINT_XFRC_Pos (0U)
-#define USB_OTG_DIEPINT_XFRC_Msk (0x1UL << USB_OTG_DIEPINT_XFRC_Pos) /*!< 0x00000001 */
-#define USB_OTG_DIEPINT_XFRC USB_OTG_DIEPINT_XFRC_Msk /*!< Transfer completed interrupt */
-#define USB_OTG_DIEPINT_EPDISD_Pos (1U)
-#define USB_OTG_DIEPINT_EPDISD_Msk (0x1UL << USB_OTG_DIEPINT_EPDISD_Pos) /*!< 0x00000002 */
-#define USB_OTG_DIEPINT_EPDISD USB_OTG_DIEPINT_EPDISD_Msk /*!< Endpoint disabled interrupt */
-#define USB_OTG_DIEPINT_AHBERR_Pos (2U)
-#define USB_OTG_DIEPINT_AHBERR_Msk (0x1UL << USB_OTG_DIEPINT_AHBERR_Pos) /*!< 0x00000004 */
-#define USB_OTG_DIEPINT_AHBERR USB_OTG_DIEPINT_AHBERR_Msk /*!< AHB Error (AHBErr) during an IN transaction */
-#define USB_OTG_DIEPINT_TOC_Pos (3U)
-#define USB_OTG_DIEPINT_TOC_Msk (0x1UL << USB_OTG_DIEPINT_TOC_Pos) /*!< 0x00000008 */
-#define USB_OTG_DIEPINT_TOC USB_OTG_DIEPINT_TOC_Msk /*!< Timeout condition */
-#define USB_OTG_DIEPINT_ITTXFE_Pos (4U)
-#define USB_OTG_DIEPINT_ITTXFE_Msk (0x1UL << USB_OTG_DIEPINT_ITTXFE_Pos) /*!< 0x00000010 */
-#define USB_OTG_DIEPINT_ITTXFE USB_OTG_DIEPINT_ITTXFE_Msk /*!< IN token received when TxFIFO is empty */
-#define USB_OTG_DIEPINT_INEPNM_Pos (5U)
-#define USB_OTG_DIEPINT_INEPNM_Msk (0x1UL << USB_OTG_DIEPINT_INEPNM_Pos) /*!< 0x00000004 */
-#define USB_OTG_DIEPINT_INEPNM USB_OTG_DIEPINT_INEPNM_Msk /*!< IN token received with EP mismatch */
-#define USB_OTG_DIEPINT_INEPNE_Pos (6U)
-#define USB_OTG_DIEPINT_INEPNE_Msk (0x1UL << USB_OTG_DIEPINT_INEPNE_Pos) /*!< 0x00000040 */
-#define USB_OTG_DIEPINT_INEPNE USB_OTG_DIEPINT_INEPNE_Msk /*!< IN endpoint NAK effective */
-#define USB_OTG_DIEPINT_TXFE_Pos (7U)
-#define USB_OTG_DIEPINT_TXFE_Msk (0x1UL << USB_OTG_DIEPINT_TXFE_Pos) /*!< 0x00000080 */
-#define USB_OTG_DIEPINT_TXFE USB_OTG_DIEPINT_TXFE_Msk /*!< Transmit FIFO empty */
-#define USB_OTG_DIEPINT_TXFIFOUDRN_Pos (8U)
-#define USB_OTG_DIEPINT_TXFIFOUDRN_Msk (0x1UL << USB_OTG_DIEPINT_TXFIFOUDRN_Pos) /*!< 0x00000100 */
-#define USB_OTG_DIEPINT_TXFIFOUDRN USB_OTG_DIEPINT_TXFIFOUDRN_Msk /*!< Transmit Fifo Underrun */
-#define USB_OTG_DIEPINT_BNA_Pos (9U)
-#define USB_OTG_DIEPINT_BNA_Msk (0x1UL << USB_OTG_DIEPINT_BNA_Pos) /*!< 0x00000200 */
-#define USB_OTG_DIEPINT_BNA USB_OTG_DIEPINT_BNA_Msk /*!< Buffer not available interrupt */
-#define USB_OTG_DIEPINT_PKTDRPSTS_Pos (11U)
-#define USB_OTG_DIEPINT_PKTDRPSTS_Msk (0x1UL << USB_OTG_DIEPINT_PKTDRPSTS_Pos) /*!< 0x00000800 */
-#define USB_OTG_DIEPINT_PKTDRPSTS USB_OTG_DIEPINT_PKTDRPSTS_Msk /*!< Packet dropped status */
-#define USB_OTG_DIEPINT_BERR_Pos (12U)
-#define USB_OTG_DIEPINT_BERR_Msk (0x1UL << USB_OTG_DIEPINT_BERR_Pos) /*!< 0x00001000 */
-#define USB_OTG_DIEPINT_BERR USB_OTG_DIEPINT_BERR_Msk /*!< Babble error interrupt */
-#define USB_OTG_DIEPINT_NAK_Pos (13U)
-#define USB_OTG_DIEPINT_NAK_Msk (0x1UL << USB_OTG_DIEPINT_NAK_Pos) /*!< 0x00002000 */
-#define USB_OTG_DIEPINT_NAK USB_OTG_DIEPINT_NAK_Msk /*!< NAK interrupt */
-
-/******************** Bit definition for USB_OTG_HCINTMSK register ********************/
-#define USB_OTG_HCINTMSK_XFRCM_Pos (0U)
-#define USB_OTG_HCINTMSK_XFRCM_Msk (0x1UL << USB_OTG_HCINTMSK_XFRCM_Pos) /*!< 0x00000001 */
-#define USB_OTG_HCINTMSK_XFRCM USB_OTG_HCINTMSK_XFRCM_Msk /*!< Transfer completed mask */
-#define USB_OTG_HCINTMSK_CHHM_Pos (1U)
-#define USB_OTG_HCINTMSK_CHHM_Msk (0x1UL << USB_OTG_HCINTMSK_CHHM_Pos) /*!< 0x00000002 */
-#define USB_OTG_HCINTMSK_CHHM USB_OTG_HCINTMSK_CHHM_Msk /*!< Channel halted mask */
-#define USB_OTG_HCINTMSK_AHBERR_Pos (2U)
-#define USB_OTG_HCINTMSK_AHBERR_Msk (0x1UL << USB_OTG_HCINTMSK_AHBERR_Pos) /*!< 0x00000004 */
-#define USB_OTG_HCINTMSK_AHBERR USB_OTG_HCINTMSK_AHBERR_Msk /*!< AHB error */
-#define USB_OTG_HCINTMSK_STALLM_Pos (3U)
-#define USB_OTG_HCINTMSK_STALLM_Msk (0x1UL << USB_OTG_HCINTMSK_STALLM_Pos) /*!< 0x00000008 */
-#define USB_OTG_HCINTMSK_STALLM USB_OTG_HCINTMSK_STALLM_Msk /*!< STALL response received interrupt mask */
-#define USB_OTG_HCINTMSK_NAKM_Pos (4U)
-#define USB_OTG_HCINTMSK_NAKM_Msk (0x1UL << USB_OTG_HCINTMSK_NAKM_Pos) /*!< 0x00000010 */
-#define USB_OTG_HCINTMSK_NAKM USB_OTG_HCINTMSK_NAKM_Msk /*!< NAK response received interrupt mask */
-#define USB_OTG_HCINTMSK_ACKM_Pos (5U)
-#define USB_OTG_HCINTMSK_ACKM_Msk (0x1UL << USB_OTG_HCINTMSK_ACKM_Pos) /*!< 0x00000020 */
-#define USB_OTG_HCINTMSK_ACKM USB_OTG_HCINTMSK_ACKM_Msk /*!< ACK response received/transmitted interrupt mask */
-#define USB_OTG_HCINTMSK_NYET_Pos (6U)
-#define USB_OTG_HCINTMSK_NYET_Msk (0x1UL << USB_OTG_HCINTMSK_NYET_Pos) /*!< 0x00000040 */
-#define USB_OTG_HCINTMSK_NYET USB_OTG_HCINTMSK_NYET_Msk /*!< response received interrupt mask */
-#define USB_OTG_HCINTMSK_TXERRM_Pos (7U)
-#define USB_OTG_HCINTMSK_TXERRM_Msk (0x1UL << USB_OTG_HCINTMSK_TXERRM_Pos) /*!< 0x00000080 */
-#define USB_OTG_HCINTMSK_TXERRM USB_OTG_HCINTMSK_TXERRM_Msk /*!< Transaction error mask */
-#define USB_OTG_HCINTMSK_BBERRM_Pos (8U)
-#define USB_OTG_HCINTMSK_BBERRM_Msk (0x1UL << USB_OTG_HCINTMSK_BBERRM_Pos) /*!< 0x00000100 */
-#define USB_OTG_HCINTMSK_BBERRM USB_OTG_HCINTMSK_BBERRM_Msk /*!< Babble error mask */
-#define USB_OTG_HCINTMSK_FRMORM_Pos (9U)
-#define USB_OTG_HCINTMSK_FRMORM_Msk (0x1UL << USB_OTG_HCINTMSK_FRMORM_Pos) /*!< 0x00000200 */
-#define USB_OTG_HCINTMSK_FRMORM USB_OTG_HCINTMSK_FRMORM_Msk /*!< Frame overrun mask */
-#define USB_OTG_HCINTMSK_DTERRM_Pos (10U)
-#define USB_OTG_HCINTMSK_DTERRM_Msk (0x1UL << USB_OTG_HCINTMSK_DTERRM_Pos) /*!< 0x00000400 */
-#define USB_OTG_HCINTMSK_DTERRM USB_OTG_HCINTMSK_DTERRM_Msk /*!< Data toggle error mask */
-
-/******************** Bit definition for USB_OTG_DIEPTSIZ register ********************/
-
-#define USB_OTG_DIEPTSIZ_XFRSIZ_Pos (0U)
-#define USB_OTG_DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */
-#define USB_OTG_DIEPTSIZ_XFRSIZ USB_OTG_DIEPTSIZ_XFRSIZ_Msk /*!< Transfer size */
-#define USB_OTG_DIEPTSIZ_PKTCNT_Pos (19U)
-#define USB_OTG_DIEPTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_DIEPTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */
-#define USB_OTG_DIEPTSIZ_PKTCNT USB_OTG_DIEPTSIZ_PKTCNT_Msk /*!< Packet count */
-#define USB_OTG_DIEPTSIZ_MULCNT_Pos (29U)
-#define USB_OTG_DIEPTSIZ_MULCNT_Msk (0x3UL << USB_OTG_DIEPTSIZ_MULCNT_Pos) /*!< 0x60000000 */
-#define USB_OTG_DIEPTSIZ_MULCNT USB_OTG_DIEPTSIZ_MULCNT_Msk /*!< Packet count */
-/******************** Bit definition for USB_OTG_HCTSIZ register ********************/
-#define USB_OTG_HCTSIZ_XFRSIZ_Pos (0U)
-#define USB_OTG_HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_HCTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */
-#define USB_OTG_HCTSIZ_XFRSIZ USB_OTG_HCTSIZ_XFRSIZ_Msk /*!< Transfer size */
-#define USB_OTG_HCTSIZ_PKTCNT_Pos (19U)
-#define USB_OTG_HCTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_HCTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */
-#define USB_OTG_HCTSIZ_PKTCNT USB_OTG_HCTSIZ_PKTCNT_Msk /*!< Packet count */
-#define USB_OTG_HCTSIZ_DOPING_Pos (31U)
-#define USB_OTG_HCTSIZ_DOPING_Msk (0x1UL << USB_OTG_HCTSIZ_DOPING_Pos) /*!< 0x80000000 */
-#define USB_OTG_HCTSIZ_DOPING USB_OTG_HCTSIZ_DOPING_Msk /*!< Do PING */
-#define USB_OTG_HCTSIZ_DPID_Pos (29U)
-#define USB_OTG_HCTSIZ_DPID_Msk (0x3UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x60000000 */
-#define USB_OTG_HCTSIZ_DPID USB_OTG_HCTSIZ_DPID_Msk /*!< Data PID */
-#define USB_OTG_HCTSIZ_DPID_0 (0x1UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x20000000 */
-#define USB_OTG_HCTSIZ_DPID_1 (0x2UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x40000000 */
-
-/******************** Bit definition for USB_OTG_DIEPDMA register ********************/
-#define USB_OTG_DIEPDMA_DMAADDR_Pos (0U)
-#define USB_OTG_DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << USB_OTG_DIEPDMA_DMAADDR_Pos) /*!< 0xFFFFFFFF */
-#define USB_OTG_DIEPDMA_DMAADDR USB_OTG_DIEPDMA_DMAADDR_Msk /*!< DMA address */
-
-/******************** Bit definition for USB_OTG_HCDMA register ********************/
-#define USB_OTG_HCDMA_DMAADDR_Pos (0U)
-#define USB_OTG_HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << USB_OTG_HCDMA_DMAADDR_Pos) /*!< 0xFFFFFFFF */
-#define USB_OTG_HCDMA_DMAADDR USB_OTG_HCDMA_DMAADDR_Msk /*!< DMA address */
-
-/******************** Bit definition for USB_OTG_DTXFSTS register ********************/
-#define USB_OTG_DTXFSTS_INEPTFSAV_Pos (0U)
-#define USB_OTG_DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << USB_OTG_DTXFSTS_INEPTFSAV_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_DTXFSTS_INEPTFSAV USB_OTG_DTXFSTS_INEPTFSAV_Msk /*!< IN endpoint TxFIFO space available */
-
-/******************** Bit definition for USB_OTG_DIEPTXF register ********************/
-#define USB_OTG_DIEPTXF_INEPTXSA_Pos (0U)
-#define USB_OTG_DIEPTXF_INEPTXSA_Msk (0xFFFFUL << USB_OTG_DIEPTXF_INEPTXSA_Pos) /*!< 0x0000FFFF */
-#define USB_OTG_DIEPTXF_INEPTXSA USB_OTG_DIEPTXF_INEPTXSA_Msk /*!< IN endpoint FIFOx transmit RAM start address */
-#define USB_OTG_DIEPTXF_INEPTXFD_Pos (16U)
-#define USB_OTG_DIEPTXF_INEPTXFD_Msk (0xFFFFUL << USB_OTG_DIEPTXF_INEPTXFD_Pos) /*!< 0xFFFF0000 */
-#define USB_OTG_DIEPTXF_INEPTXFD USB_OTG_DIEPTXF_INEPTXFD_Msk /*!< IN endpoint TxFIFO depth */
-
-/******************** Bit definition for USB_OTG_DOEPCTL register ********************/
-
-#define USB_OTG_DOEPCTL_MPSIZ_Pos (0U)
-#define USB_OTG_DOEPCTL_MPSIZ_Msk (0x7FFUL << USB_OTG_DOEPCTL_MPSIZ_Pos) /*!< 0x000007FF */
-#define USB_OTG_DOEPCTL_MPSIZ USB_OTG_DOEPCTL_MPSIZ_Msk /*!< Maximum packet size */ /*!<Bit 1 */
-#define USB_OTG_DOEPCTL_USBAEP_Pos (15U)
-#define USB_OTG_DOEPCTL_USBAEP_Msk (0x1UL << USB_OTG_DOEPCTL_USBAEP_Pos) /*!< 0x00008000 */
-#define USB_OTG_DOEPCTL_USBAEP USB_OTG_DOEPCTL_USBAEP_Msk /*!< USB active endpoint */
-#define USB_OTG_DOEPCTL_NAKSTS_Pos (17U)
-#define USB_OTG_DOEPCTL_NAKSTS_Msk (0x1UL << USB_OTG_DOEPCTL_NAKSTS_Pos) /*!< 0x00020000 */
-#define USB_OTG_DOEPCTL_NAKSTS USB_OTG_DOEPCTL_NAKSTS_Msk /*!< NAK status */
-#define USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Pos (28U)
-#define USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Pos) /*!< 0x10000000 */
-#define USB_OTG_DOEPCTL_SD0PID_SEVNFRM USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk /*!< Set DATA0 PID */
-#define USB_OTG_DOEPCTL_SODDFRM_Pos (29U)
-#define USB_OTG_DOEPCTL_SODDFRM_Msk (0x1UL << USB_OTG_DOEPCTL_SODDFRM_Pos) /*!< 0x20000000 */
-#define USB_OTG_DOEPCTL_SODDFRM USB_OTG_DOEPCTL_SODDFRM_Msk /*!< Set odd frame */
-#define USB_OTG_DOEPCTL_EPTYP_Pos (18U)
-#define USB_OTG_DOEPCTL_EPTYP_Msk (0x3UL << USB_OTG_DOEPCTL_EPTYP_Pos) /*!< 0x000C0000 */
-#define USB_OTG_DOEPCTL_EPTYP USB_OTG_DOEPCTL_EPTYP_Msk /*!< Endpoint type */
-#define USB_OTG_DOEPCTL_EPTYP_0 (0x1UL << USB_OTG_DOEPCTL_EPTYP_Pos) /*!< 0x00040000 */
-#define USB_OTG_DOEPCTL_EPTYP_1 (0x2UL << USB_OTG_DOEPCTL_EPTYP_Pos) /*!< 0x00080000 */
-#define USB_OTG_DOEPCTL_SNPM_Pos (20U)
-#define USB_OTG_DOEPCTL_SNPM_Msk (0x1UL << USB_OTG_DOEPCTL_SNPM_Pos) /*!< 0x00100000 */
-#define USB_OTG_DOEPCTL_SNPM USB_OTG_DOEPCTL_SNPM_Msk /*!< Snoop mode */
-#define USB_OTG_DOEPCTL_STALL_Pos (21U)
-#define USB_OTG_DOEPCTL_STALL_Msk (0x1UL << USB_OTG_DOEPCTL_STALL_Pos) /*!< 0x00200000 */
-#define USB_OTG_DOEPCTL_STALL USB_OTG_DOEPCTL_STALL_Msk /*!< STALL handshake */
-#define USB_OTG_DOEPCTL_CNAK_Pos (26U)
-#define USB_OTG_DOEPCTL_CNAK_Msk (0x1UL << USB_OTG_DOEPCTL_CNAK_Pos) /*!< 0x04000000 */
-#define USB_OTG_DOEPCTL_CNAK USB_OTG_DOEPCTL_CNAK_Msk /*!< Clear NAK */
-#define USB_OTG_DOEPCTL_SNAK_Pos (27U)
-#define USB_OTG_DOEPCTL_SNAK_Msk (0x1UL << USB_OTG_DOEPCTL_SNAK_Pos) /*!< 0x08000000 */
-#define USB_OTG_DOEPCTL_SNAK USB_OTG_DOEPCTL_SNAK_Msk /*!< Set NAK */
-#define USB_OTG_DOEPCTL_EPDIS_Pos (30U)
-#define USB_OTG_DOEPCTL_EPDIS_Msk (0x1UL << USB_OTG_DOEPCTL_EPDIS_Pos) /*!< 0x40000000 */
-#define USB_OTG_DOEPCTL_EPDIS USB_OTG_DOEPCTL_EPDIS_Msk /*!< Endpoint disable */
-#define USB_OTG_DOEPCTL_EPENA_Pos (31U)
-#define USB_OTG_DOEPCTL_EPENA_Msk (0x1UL << USB_OTG_DOEPCTL_EPENA_Pos) /*!< 0x80000000 */
-#define USB_OTG_DOEPCTL_EPENA USB_OTG_DOEPCTL_EPENA_Msk /*!< Endpoint enable */
-
-/******************** Bit definition for USB_OTG_DOEPINT register ********************/
-#define USB_OTG_DOEPINT_XFRC_Pos (0U)
-#define USB_OTG_DOEPINT_XFRC_Msk (0x1UL << USB_OTG_DOEPINT_XFRC_Pos) /*!< 0x00000001 */
-#define USB_OTG_DOEPINT_XFRC USB_OTG_DOEPINT_XFRC_Msk /*!< Transfer completed interrupt */
-#define USB_OTG_DOEPINT_EPDISD_Pos (1U)
-#define USB_OTG_DOEPINT_EPDISD_Msk (0x1UL << USB_OTG_DOEPINT_EPDISD_Pos) /*!< 0x00000002 */
-#define USB_OTG_DOEPINT_EPDISD USB_OTG_DOEPINT_EPDISD_Msk /*!< Endpoint disabled interrupt */
-#define USB_OTG_DOEPINT_AHBERR_Pos (2U)
-#define USB_OTG_DOEPINT_AHBERR_Msk (0x1UL << USB_OTG_DOEPINT_AHBERR_Pos) /*!< 0x00000004 */
-#define USB_OTG_DOEPINT_AHBERR USB_OTG_DOEPINT_AHBERR_Msk /*!< AHB Error (AHBErr) during an OUT transaction */
-#define USB_OTG_DOEPINT_STUP_Pos (3U)
-#define USB_OTG_DOEPINT_STUP_Msk (0x1UL << USB_OTG_DOEPINT_STUP_Pos) /*!< 0x00000008 */
-#define USB_OTG_DOEPINT_STUP USB_OTG_DOEPINT_STUP_Msk /*!< SETUP phase done */
-#define USB_OTG_DOEPINT_OTEPDIS_Pos (4U)
-#define USB_OTG_DOEPINT_OTEPDIS_Msk (0x1UL << USB_OTG_DOEPINT_OTEPDIS_Pos) /*!< 0x00000010 */
-#define USB_OTG_DOEPINT_OTEPDIS USB_OTG_DOEPINT_OTEPDIS_Msk /*!< OUT token received when endpoint disabled */
-#define USB_OTG_DOEPINT_OTEPSPR_Pos (5U)
-#define USB_OTG_DOEPINT_OTEPSPR_Msk (0x1UL << USB_OTG_DOEPINT_OTEPSPR_Pos) /*!< 0x00000020 */
-#define USB_OTG_DOEPINT_OTEPSPR USB_OTG_DOEPINT_OTEPSPR_Msk /*!< Status Phase Received For Control Write */
-#define USB_OTG_DOEPINT_B2BSTUP_Pos (6U)
-#define USB_OTG_DOEPINT_B2BSTUP_Msk (0x1UL << USB_OTG_DOEPINT_B2BSTUP_Pos) /*!< 0x00000040 */
-#define USB_OTG_DOEPINT_B2BSTUP USB_OTG_DOEPINT_B2BSTUP_Msk /*!< Back-to-back SETUP packets received */
-#define USB_OTG_DOEPINT_OUTPKTERR_Pos (8U)
-#define USB_OTG_DOEPINT_OUTPKTERR_Msk (0x1UL << USB_OTG_DOEPINT_OUTPKTERR_Pos) /*!< 0x00000100 */
-#define USB_OTG_DOEPINT_OUTPKTERR USB_OTG_DOEPINT_OUTPKTERR_Msk /*!< OUT packet error */
-#define USB_OTG_DOEPINT_NAK_Pos (13U)
-#define USB_OTG_DOEPINT_NAK_Msk (0x1UL << USB_OTG_DOEPINT_NAK_Pos) /*!< 0x00002000 */
-#define USB_OTG_DOEPINT_NAK USB_OTG_DOEPINT_NAK_Msk /*!< NAK Packet is transmitted by the device */
-#define USB_OTG_DOEPINT_NYET_Pos (14U)
-#define USB_OTG_DOEPINT_NYET_Msk (0x1UL << USB_OTG_DOEPINT_NYET_Pos) /*!< 0x00004000 */
-#define USB_OTG_DOEPINT_NYET USB_OTG_DOEPINT_NYET_Msk /*!< NYET interrupt */
-#define USB_OTG_DOEPINT_STPKTRX_Pos (15U)
-#define USB_OTG_DOEPINT_STPKTRX_Msk (0x1UL << USB_OTG_DOEPINT_STPKTRX_Pos) /*!< 0x00008000 */
-#define USB_OTG_DOEPINT_STPKTRX USB_OTG_DOEPINT_STPKTRX_Msk /*!< Setup Packet Received */
-/******************** Bit definition for USB_OTG_DOEPTSIZ register ********************/
-
-#define USB_OTG_DOEPTSIZ_XFRSIZ_Pos (0U)
-#define USB_OTG_DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */
-#define USB_OTG_DOEPTSIZ_XFRSIZ USB_OTG_DOEPTSIZ_XFRSIZ_Msk /*!< Transfer size */
-#define USB_OTG_DOEPTSIZ_PKTCNT_Pos (19U)
-#define USB_OTG_DOEPTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_DOEPTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */
-#define USB_OTG_DOEPTSIZ_PKTCNT USB_OTG_DOEPTSIZ_PKTCNT_Msk /*!< Packet count */
-
-#define USB_OTG_DOEPTSIZ_STUPCNT_Pos (29U)
-#define USB_OTG_DOEPTSIZ_STUPCNT_Msk (0x3UL << USB_OTG_DOEPTSIZ_STUPCNT_Pos) /*!< 0x60000000 */
-#define USB_OTG_DOEPTSIZ_STUPCNT USB_OTG_DOEPTSIZ_STUPCNT_Msk /*!< SETUP packet count */
-#define USB_OTG_DOEPTSIZ_STUPCNT_0 (0x1UL << USB_OTG_DOEPTSIZ_STUPCNT_Pos) /*!< 0x20000000 */
-#define USB_OTG_DOEPTSIZ_STUPCNT_1 (0x2UL << USB_OTG_DOEPTSIZ_STUPCNT_Pos) /*!< 0x40000000 */
-
-/******************** Bit definition for PCGCCTL register ********************/
-#define USB_OTG_PCGCCTL_STOPCLK_Pos (0U)
-#define USB_OTG_PCGCCTL_STOPCLK_Msk (0x1UL << USB_OTG_PCGCCTL_STOPCLK_Pos) /*!< 0x00000001 */
-#define USB_OTG_PCGCCTL_STOPCLK USB_OTG_PCGCCTL_STOPCLK_Msk /*!< SETUP packet count */
-#define USB_OTG_PCGCCTL_GATECLK_Pos (1U)
-#define USB_OTG_PCGCCTL_GATECLK_Msk (0x1UL << USB_OTG_PCGCCTL_GATECLK_Pos) /*!< 0x00000002 */
-#define USB_OTG_PCGCCTL_GATECLK USB_OTG_PCGCCTL_GATECLK_Msk /*!<Bit 0 */
-#define USB_OTG_PCGCCTL_PHYSUSP_Pos (4U)
-#define USB_OTG_PCGCCTL_PHYSUSP_Msk (0x1UL << USB_OTG_PCGCCTL_PHYSUSP_Pos) /*!< 0x00000010 */
-#define USB_OTG_PCGCCTL_PHYSUSP USB_OTG_PCGCCTL_PHYSUSP_Msk /*!<Bit 1 */
-
-/* Legacy define */
-/******************** Bit definition for OTG register ********************/
-#define USB_OTG_CHNUM_Pos (0U)
-#define USB_OTG_CHNUM_Msk (0xFUL << USB_OTG_CHNUM_Pos) /*!< 0x0000000F */
-#define USB_OTG_CHNUM USB_OTG_CHNUM_Msk /*!< Channel number */
-#define USB_OTG_CHNUM_0 (0x1UL << USB_OTG_CHNUM_Pos) /*!< 0x00000001 */
-#define USB_OTG_CHNUM_1 (0x2UL << USB_OTG_CHNUM_Pos) /*!< 0x00000002 */
-#define USB_OTG_CHNUM_2 (0x4UL << USB_OTG_CHNUM_Pos) /*!< 0x00000004 */
-#define USB_OTG_CHNUM_3 (0x8UL << USB_OTG_CHNUM_Pos) /*!< 0x00000008 */
-#define USB_OTG_BCNT_Pos (4U)
-#define USB_OTG_BCNT_Msk (0x7FFUL << USB_OTG_BCNT_Pos) /*!< 0x00007FF0 */
-#define USB_OTG_BCNT USB_OTG_BCNT_Msk /*!< Byte count */
-
-#define USB_OTG_DPID_Pos (15U)
-#define USB_OTG_DPID_Msk (0x3UL << USB_OTG_DPID_Pos) /*!< 0x00018000 */
-#define USB_OTG_DPID USB_OTG_DPID_Msk /*!< Data PID */
-#define USB_OTG_DPID_0 (0x1UL << USB_OTG_DPID_Pos) /*!< 0x00008000 */
-#define USB_OTG_DPID_1 (0x2UL << USB_OTG_DPID_Pos) /*!< 0x00010000 */
-
-#define USB_OTG_PKTSTS_Pos (17U)
-#define USB_OTG_PKTSTS_Msk (0xFUL << USB_OTG_PKTSTS_Pos) /*!< 0x001E0000 */
-#define USB_OTG_PKTSTS USB_OTG_PKTSTS_Msk /*!< Packet status */
-#define USB_OTG_PKTSTS_0 (0x1UL << USB_OTG_PKTSTS_Pos) /*!< 0x00020000 */
-#define USB_OTG_PKTSTS_1 (0x2UL << USB_OTG_PKTSTS_Pos) /*!< 0x00040000 */
-#define USB_OTG_PKTSTS_2 (0x4UL << USB_OTG_PKTSTS_Pos) /*!< 0x00080000 */
-#define USB_OTG_PKTSTS_3 (0x8UL << USB_OTG_PKTSTS_Pos) /*!< 0x00100000 */
-
-#define USB_OTG_EPNUM_Pos (0U)
-#define USB_OTG_EPNUM_Msk (0xFUL << USB_OTG_EPNUM_Pos) /*!< 0x0000000F */
-#define USB_OTG_EPNUM USB_OTG_EPNUM_Msk /*!< Endpoint number */
-#define USB_OTG_EPNUM_0 (0x1UL << USB_OTG_EPNUM_Pos) /*!< 0x00000001 */
-#define USB_OTG_EPNUM_1 (0x2UL << USB_OTG_EPNUM_Pos) /*!< 0x00000002 */
-#define USB_OTG_EPNUM_2 (0x4UL << USB_OTG_EPNUM_Pos) /*!< 0x00000004 */
-#define USB_OTG_EPNUM_3 (0x8UL << USB_OTG_EPNUM_Pos) /*!< 0x00000008 */
-
-#define USB_OTG_FRMNUM_Pos (21U)
-#define USB_OTG_FRMNUM_Msk (0xFUL << USB_OTG_FRMNUM_Pos) /*!< 0x01E00000 */
-#define USB_OTG_FRMNUM USB_OTG_FRMNUM_Msk /*!< Frame number */
-#define USB_OTG_FRMNUM_0 (0x1UL << USB_OTG_FRMNUM_Pos) /*!< 0x00200000 */
-#define USB_OTG_FRMNUM_1 (0x2UL << USB_OTG_FRMNUM_Pos) /*!< 0x00400000 */
-#define USB_OTG_FRMNUM_2 (0x4UL << USB_OTG_FRMNUM_Pos) /*!< 0x00800000 */
-#define USB_OTG_FRMNUM_3 (0x8UL << USB_OTG_FRMNUM_Pos) /*!< 0x01000000 */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/portable/st/typec/typec_stm32.c b/src/portable/st/typec/typec_stm32.c
new file mode 100644
index 000000000..8da2e39ba
--- /dev/null
+++ b/src/portable/st/typec/typec_stm32.c
@@ -0,0 +1,372 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "tusb_option.h"
+#include "typec/tcd.h"
+
+#if CFG_TUC_ENABLED && defined(TUP_USBIP_TYPEC_STM32)
+
+#include "common/tusb_common.h"
+
+#if CFG_TUSB_MCU == OPT_MCU_STM32G4
+ #include "stm32g4xx.h"
+ #include "stm32g4xx_ll_dma.h" // for UCPD REQID
+#else
+ #error "Unsupported STM32 family"
+#endif
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+enum {
+ IMR_ATTACHED = UCPD_IMR_TXMSGDISCIE | UCPD_IMR_TXMSGSENTIE | UCPD_IMR_TXMSGABTIE | UCPD_IMR_TXUNDIE |
+ UCPD_IMR_RXHRSTDETIE | UCPD_IMR_RXOVRIE | UCPD_IMR_RXMSGENDIE | UCPD_IMR_RXORDDETIE |
+ UCPD_IMR_HRSTDISCIE | UCPD_IMR_HRSTSENTIE | UCPD_IMR_FRSEVTIE
+};
+
+#define PHY_SYNC1 0x18u
+#define PHY_SYNC2 0x11u
+#define PHY_SYNC3 0x06u
+#define PHY_RST1 0x07u
+#define PHY_RST2 0x19u
+#define PHY_EOP 0x0Du
+
+#define PHY_ORDERED_SET_SOP (PHY_SYNC1 | (PHY_SYNC1<<5u) | (PHY_SYNC1<<10u) | (PHY_SYNC2<<15u)) // SOP Ordered set coding
+#define PHY_ORDERED_SET_SOP_P (PHY_SYNC1 | (PHY_SYNC1<<5u) | (PHY_SYNC3<<10u) | (PHY_SYNC3<<15u)) // SOP' Ordered set coding
+#define PHY_ORDERED_SET_SOP_PP (PHY_SYNC1 | (PHY_SYNC3<<5u) | (PHY_SYNC1<<10u) | (PHY_SYNC3<<15u)) // SOP'' Ordered set coding
+#define PHY_ORDERED_SET_HARD_RESET (PHY_RST1 | (PHY_RST1<<5u) | (PHY_RST1<<10u) | (PHY_RST2<<15u )) // Hard Reset Ordered set coding
+#define PHY_ORDERED_SET_CABLE_RESET (PHY_RST1 | (PHY_SYNC1<<5u) | (PHY_RST1<<10u) | (PHY_SYNC3<<15u)) // Cable Reset Ordered set coding
+#define PHY_ORDERED_SET_SOP_P_DEBUG (PHY_SYNC1 | (PHY_RST2<<5u) | (PHY_RST2<<10u) | (PHY_SYNC3<<15u)) // SOP' Debug Ordered set coding
+#define PHY_ORDERED_SET_SOP_PP_DEBUG (PHY_SYNC1 | (PHY_RST2<<5u) | (PHY_SYNC3<<10u) | (PHY_SYNC2<<15u)) // SOP'' Debug Ordered set coding
+
+
+static uint8_t const* _rx_buf;
+static uint8_t const* _tx_pending_buf;
+static uint16_t _tx_pending_bytes;
+static uint16_t _tx_xferring_bytes;
+
+static pd_header_t _good_crc = {
+ .msg_type = PD_CTRL_GOOD_CRC,
+ .data_role = 0, // UFP
+ .specs_rev = PD_REV_20,
+ .power_role = 0, // Sink
+ .msg_id = 0,
+ .n_data_obj = 0,
+ .extended = 0
+};
+
+// address of DMA channel rx, tx for each port
+#define CFG_TUC_STM32_DMA { { DMA1_Channel1_BASE, DMA1_Channel2_BASE } }
+
+//--------------------------------------------------------------------+
+// DMA
+//--------------------------------------------------------------------+
+
+static const uint32_t _dma_addr_arr[TUP_TYPEC_RHPORTS_NUM][2] = CFG_TUC_STM32_DMA;
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t dma_get_addr(uint8_t rhport, bool is_rx) {
+ return _dma_addr_arr[rhport][is_rx ? 0 : 1];
+}
+
+static void dma_init(uint8_t rhport, bool is_rx) {
+ uint32_t dma_addr = dma_get_addr(rhport, is_rx);
+ DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_addr;
+ uint32_t req_id;
+
+ if (is_rx) {
+ // Peripheral -> Memory, Memory inc, 8-bit, High priority
+ dma_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1;
+ dma_ch->CPAR = (uint32_t) &UCPD1->RXDR;
+
+ req_id = LL_DMAMUX_REQ_UCPD1_RX;
+ } else {
+ // Memory -> Peripheral, Memory inc, 8-bit, High priority
+ dma_ch->CCR = DMA_CCR_MINC | DMA_CCR_PL_1 | DMA_CCR_DIR;
+ dma_ch->CPAR = (uint32_t) &UCPD1->TXDR;
+
+ req_id = LL_DMAMUX_REQ_UCPD1_TX;
+ }
+
+ // find and set up mux channel TODO support mcu with multiple DMAMUXs
+ enum {
+ CH_DIFF = DMA1_Channel2_BASE - DMA1_Channel1_BASE
+ };
+ uint32_t mux_ch_num;
+
+ #ifdef DMA2_BASE
+ if (dma_addr > DMA2_BASE) {
+ mux_ch_num = 8 * ((dma_addr - DMA2_Channel1_BASE) / CH_DIFF);
+ } else
+ #endif
+ {
+ mux_ch_num = (dma_addr - DMA1_Channel1_BASE) / CH_DIFF;
+ }
+
+ DMAMUX_Channel_TypeDef* mux_ch = DMAMUX1_Channel0 + mux_ch_num;
+
+ uint32_t mux_ccr = mux_ch->CCR & ~(DMAMUX_CxCR_DMAREQ_ID);
+ mux_ccr |= req_id;
+ mux_ch->CCR = mux_ccr;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void dma_start(uint8_t rhport, bool is_rx, void const* buf, uint16_t len) {
+ DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_get_addr(rhport, is_rx);
+
+ dma_ch->CMAR = (uint32_t) buf;
+ dma_ch->CNDTR = len;
+ dma_ch->CCR |= DMA_CCR_EN;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void dma_stop(uint8_t rhport, bool is_rx) {
+ DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_get_addr(rhport, is_rx);
+ dma_ch->CCR &= ~DMA_CCR_EN;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool dma_enabled(uint8_t rhport, bool is_rx) {
+ DMA_Channel_TypeDef* dma_ch = (DMA_Channel_TypeDef*) dma_get_addr(rhport, is_rx);
+ return dma_ch->CCR & DMA_CCR_EN;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void dma_tx_start(uint8_t rhport, void const* buf, uint16_t len) {
+ UCPD1->TX_ORDSET = PHY_ORDERED_SET_SOP;
+ UCPD1->TX_PAYSZ = len;
+ dma_start(rhport, false, buf, len);
+ UCPD1->CR |= UCPD_CR_TXSEND;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void dma_tx_stop(uint8_t rhport) {
+ dma_stop(rhport, false);
+}
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+bool tcd_init(uint8_t rhport, uint32_t port_type) {
+ (void) rhport;
+
+ // Init DMA for RX, TX
+ dma_init(rhport, true);
+ dma_init(rhport, false);
+
+ // Initialization phase: CFG1, detect all SOPs
+ UCPD1->CFG1 = (0x0d << UCPD_CFG1_HBITCLKDIV_Pos) | (0x10 << UCPD_CFG1_IFRGAP_Pos) | (0x07 << UCPD_CFG1_TRANSWIN_Pos) |
+ (0x01 << UCPD_CFG1_PSC_UCPDCLK_Pos) | (0x1f << UCPD_CFG1_RXORDSETEN_Pos);
+ UCPD1->CFG1 |= UCPD_CFG1_UCPDEN;
+
+ // General programming sequence (with UCPD configured then enabled)
+ if (port_type == TUSB_TYPEC_PORT_SNK) {
+ // Set analog mode enable both CC Phy
+ UCPD1->CR = (0x01 << UCPD_CR_ANAMODE_Pos) | (UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1);
+
+ // Read Voltage State on CC1 & CC2 fore initial state
+ uint32_t v_cc[2];
+ (void) v_cc;
+ v_cc[0] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos) & 0x03;
+ v_cc[1] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos) & 0x03;
+ TU_LOG1("Initial VState CC1 = %lu, CC2 = %lu\r\n", v_cc[0], v_cc[1]);
+
+ // Enable CC1 & CC2 Interrupt
+ UCPD1->IMR = UCPD_IMR_TYPECEVT1IE | UCPD_IMR_TYPECEVT2IE;
+ }
+
+ // Disable dead battery in PWR's CR3
+ PWR->CR3 |= PWR_CR3_UCPD_DBDIS;
+
+ return true;
+}
+
+// Enable interrupt
+void tcd_int_enable (uint8_t rhport) {
+ (void) rhport;
+ NVIC_EnableIRQ(UCPD1_IRQn);
+}
+
+// Disable interrupt
+void tcd_int_disable(uint8_t rhport) {
+ (void) rhport;
+ NVIC_DisableIRQ(UCPD1_IRQn);
+}
+
+bool tcd_msg_receive(uint8_t rhport, uint8_t* buffer, uint16_t total_bytes) {
+ _rx_buf = buffer;
+ dma_start(rhport, true, buffer, total_bytes);
+ return true;
+}
+
+bool tcd_msg_send(uint8_t rhport, uint8_t const* buffer, uint16_t total_bytes) {
+ (void) rhport;
+
+ if (dma_enabled(rhport, false)) {
+ // DMA is busy, probably sending GoodCRC, save as pending TX
+ _tx_pending_buf = buffer;
+ _tx_pending_bytes = total_bytes;
+ }else {
+ // DMA is free, start sending
+ _tx_pending_buf = NULL;
+ _tx_pending_bytes = 0;
+
+ _tx_xferring_bytes = total_bytes;
+ dma_tx_start(rhport, buffer, total_bytes);
+ }
+
+ return true;
+}
+
+void tcd_int_handler(uint8_t rhport) {
+ (void) rhport;
+
+ uint32_t sr = UCPD1->SR;
+ sr &= UCPD1->IMR;
+
+ if (sr & (UCPD_SR_TYPECEVT1 | UCPD_SR_TYPECEVT2)) {
+ uint32_t v_cc[2];
+ v_cc[0] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC1_Pos) & 0x03;
+ v_cc[1] = (UCPD1->SR >> UCPD_SR_TYPEC_VSTATE_CC2_Pos) & 0x03;
+
+ TU_LOG3("VState CC1 = %lu, CC2 = %lu\r\n", v_cc[0], v_cc[1]);
+
+ uint32_t cr = UCPD1->CR;
+
+ // TODO only support SNK for now, required highest voltage for now
+ // Enable PHY on active CC and disable Rd on other CC
+ // FIXME somehow CC2 is vstate is not correct, always 1 even not attached.
+ // on DPOW1 board, it is connected to PA10 (USBPD_DBCC2), we probably miss something.
+ if ((sr & UCPD_SR_TYPECEVT1) && (v_cc[0] == 3)) {
+ TU_LOG3("Attach CC1\r\n");
+ cr &= ~(UCPD_CR_PHYCCSEL | UCPD_CR_CCENABLE);
+ cr |= UCPD_CR_PHYRXEN | UCPD_CR_CCENABLE_0;
+ } else if ((sr & UCPD_SR_TYPECEVT2) && (v_cc[1] == 3)) {
+ TU_LOG3("Attach CC2\r\n");
+ cr &= ~UCPD_CR_CCENABLE;
+ cr |= (UCPD_CR_PHYCCSEL | UCPD_CR_PHYRXEN | UCPD_CR_CCENABLE_1);
+ } else {
+ TU_LOG3("Detach\r\n");
+ cr &= ~UCPD_CR_PHYRXEN;
+ cr |= UCPD_CR_CCENABLE_0 | UCPD_CR_CCENABLE_1;
+ }
+
+ if (cr & UCPD_CR_PHYRXEN) {
+ // Attached
+ UCPD1->IMR |= IMR_ATTACHED;
+ UCPD1->CFG1 |= UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN;
+ }else {
+ // Detached
+ UCPD1->CFG1 &= ~(UCPD_CFG1_RXDMAEN | UCPD_CFG1_TXDMAEN);
+ UCPD1->IMR &= ~IMR_ATTACHED;
+ }
+
+ // notify stack
+ tcd_event_cc_changed(rhport, v_cc[0], v_cc[1], true);
+
+ UCPD1->CR = cr;
+
+ // ack
+ UCPD1->ICR = UCPD_ICR_TYPECEVT1CF | UCPD_ICR_TYPECEVT2CF;
+ }
+
+ //------------- RX -------------//
+ if (sr & UCPD_SR_RXORDDET) {
+ // SOP: Start of Packet.
+ TU_LOG3("SOP\r\n");
+ // UCPD1->RX_ORDSET & UCPD_RX_ORDSET_RXORDSET_Msk;
+
+ // ack
+ UCPD1->ICR = UCPD_ICR_RXORDDETCF;
+ }
+
+ // Received full message
+ if (sr & UCPD_SR_RXMSGEND) {
+ TU_LOG3("RX MSG END\r\n");
+
+ // stop TX
+ dma_stop(rhport, true);
+
+ uint8_t result;
+
+ if (!(sr & UCPD_SR_RXERR)) {
+ // response with good crc
+ // TODO move this to usbc stack
+ if (_rx_buf) {
+ _good_crc.msg_id = ((pd_header_t const *) _rx_buf)->msg_id;
+ dma_tx_start(rhport, &_good_crc, 2);
+ }
+
+ result = XFER_RESULT_SUCCESS;
+ }else {
+ // CRC failed
+ result = XFER_RESULT_FAILED;
+ }
+
+ // notify stack
+ tcd_event_rx_complete(rhport, UCPD1->RX_PAYSZ, result, true);
+
+ // ack
+ UCPD1->ICR = UCPD_ICR_RXMSGENDCF;
+ }
+
+ if (sr & UCPD_SR_RXOVR) {
+ TU_LOG3("RXOVR\r\n");
+ // ack
+ UCPD1->ICR = UCPD_ICR_RXOVRCF;
+ }
+
+ //------------- TX -------------//
+ // All tx events: complete and error
+ if (sr & (UCPD_SR_TXMSGSENT | (UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND))) {
+ // force TX stop
+ dma_tx_stop(rhport);
+
+ uint16_t const xferred_bytes = _tx_xferring_bytes - UCPD1->TX_PAYSZ;
+ uint8_t result;
+
+ if ( sr & UCPD_SR_TXMSGSENT ) {
+ TU_LOG3("TX MSG SENT\r\n");
+ result = XFER_RESULT_SUCCESS;
+ // ack
+ UCPD1->ICR = UCPD_ICR_TXMSGSENTCF;
+ }else {
+ TU_LOG3("TX Error\r\n");
+ result = XFER_RESULT_FAILED;
+ // ack
+ UCPD1->ICR = UCPD_SR_TXMSGDISC | UCPD_SR_TXMSGABT | UCPD_SR_TXUND;
+ }
+
+ // start pending TX if any
+ if (_tx_pending_buf && _tx_pending_bytes ) {
+ // Start the pending TX
+ dma_tx_start(rhport, _tx_pending_buf, _tx_pending_bytes);
+
+ // clear pending
+ _tx_pending_buf = NULL;
+ _tx_pending_bytes = 0;
+ }
+
+ // notify stack
+ tcd_event_tx_complete(rhport, xferred_bytes, result, true);
+ }
+}
+
+#endif
diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c
index e26be775d..6cc1975a8 100644
--- a/src/portable/sunxi/dcd_sunxi_musb.c
+++ b/src/portable/sunxi/dcd_sunxi_musb.c
@@ -408,9 +408,9 @@ static inline unsigned free_block_size(free_block_t const *blk)
#if 0
static inline void print_block_list(free_block_t const *blk, unsigned num)
{
- TU_LOG1("*************\n");
+ TU_LOG1("*************\r\n");
for (unsigned i = 0; i < num; ++i) {
- TU_LOG1(" Blk%u %u %u\n", i, blk->beg, blk->end);
+ TU_LOG1(" Blk%u %u %u\r\n", i, blk->beg, blk->end);
++blk;
}
}
@@ -590,7 +590,7 @@ static bool handle_xfer_in(uint_fast8_t ep_addr)
const unsigned mps = USBC_Readw(USBC_REG_TXMAXP(USBC0_BASE));
const unsigned len = TU_MIN(mps, rem);
uint8_t *buf = pipe->buf;
- // TU_LOG1(" %p mps %d len %d rem %d\n", buf, mps, len, rem);
+ // TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem);
if (len) {
volatile void* addr = (volatile void*)(USBC_REG_EPFIFO1(USBC0_BASE) + (epnum_minus1 << 2));
if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) {
@@ -602,7 +602,7 @@ static bool handle_xfer_in(uint_fast8_t ep_addr)
pipe->remaining = rem - len;
}
__USBC_Dev_Tx_WriteDataComplete();
- // TU_LOG1(" TXCSRL%d = %x %d\n", epnum_minus1 + 1, regs->TXCSRL, rem - len);
+ // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum_minus1 + 1, regs->TXCSRL, rem - len);
return false;
}
@@ -610,7 +610,7 @@ static bool handle_xfer_out(uint_fast8_t ep_addr)
{
unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1;
pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
- // TU_LOG1(" RXCSRL%d = %x\n", epnum_minus1 + 1, regs->RXCSRL);
+ // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, regs->RXCSRL);
TU_ASSERT(__USBC_Dev_Rx_IsReadDataReady());
@@ -677,14 +677,14 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_
* may have already finished and received the next setup packet
* without calling this function, so we have no choice but to
* invoke the callback function of status packet here. */
- // TU_LOG1(" STATUS OUT CSRL0 = %x\n", CSRL0);
+ // TU_LOG1(" STATUS OUT CSRL0 = %x\r\n", CSRL0);
_dcd.status_out = 0;
if (req == REQUEST_TYPE_INVALID) {
dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false);
} else {
/* The next setup packet has already been received, it aborts
* invoking callback function to avoid confusing TUSB stack. */
- TU_LOG1("Drop CONTROL_STAGE_ACK\n");
+ TU_LOG1("Drop CONTROL_STAGE_ACK\r\n");
}
return true;
}
@@ -709,16 +709,16 @@ static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_
} else {
__USBC_Dev_ep0_WriteDataHalf();
}
- // TU_LOG1(" IN CSRL0 = %x\n", CSRL0);
+ // TU_LOG1(" IN CSRL0 = %x\r\n", CSRL0);
} else {
- // TU_LOG1(" OUT CSRL0 = %x\n", CSRL0);
+ // TU_LOG1(" OUT CSRL0 = %x\r\n", CSRL0);
_dcd.pipe0.buf = buffer;
_dcd.pipe0.length = len;
_dcd.pipe0.remaining = len;
__USBC_Dev_ep0_ReadDataHalf();
}
} else if (dir_in) {
- // TU_LOG1(" STATUS IN CSRL0 = %x\n", CSRL0);
+ // TU_LOG1(" STATUS IN CSRL0 = %x\r\n", CSRL0);
_dcd.pipe0.buf = NULL;
_dcd.pipe0.length = 0;
_dcd.pipe0.remaining = 0;
@@ -733,7 +733,7 @@ static void process_ep0(uint8_t rhport)
USBC_SelectActiveEp(0);
uint_fast8_t csrl = USBC_Readw(USBC_REG_CSR0(USBC0_BASE));
- // TU_LOG1(" EP0 CSRL0 = %x\n", csrl);
+ // TU_LOG1(" EP0 CSRL0 = %x\r\n", csrl);
if (csrl & USB_CSRL0_STALLED) {
/* Returned STALL packet to HOST. */
@@ -743,7 +743,7 @@ static void process_ep0(uint8_t rhport)
unsigned req = _dcd.setup_packet.bmRequestType;
if (csrl & USB_CSRL0_SETEND) {
- // TU_LOG1(" ABORT by the next packets\n");
+ // TU_LOG1(" ABORT by the next packets\r\n");
USBC_Dev_Ctrl_ClearSetupEnd();
if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) {
/* DATA stage was aborted by receiving STATUS or SETUP packet. */
@@ -819,14 +819,14 @@ static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr)
USBC_SelectActiveEp(epn);
if (dir_in) {
- // TU_LOG1(" TXCSRL%d = %x\n", epn_minus1 + 1, regs->TXCSRL);
+ // TU_LOG1(" TXCSRL%d = %x\r\n", epn_minus1 + 1, regs->TXCSRL);
if (__USBC_Dev_Tx_IsEpStall()) {
__USBC_Dev_Tx_ClearStall();
return;
}
completed = handle_xfer_in(ep_addr);
} else {
- // TU_LOG1(" RXCSRL%d = %x\n", epn_minus1 + 1, regs->RXCSRL);
+ // TU_LOG1(" RXCSRL%d = %x\r\n", epn_minus1 + 1, regs->RXCSRL);
if (__USBC_Dev_Rx_IsEpStall()) {
__USBC_Dev_Rx_ClearStall();
return;
@@ -1092,7 +1092,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
{
(void)rhport;
bool ret;
- // TU_LOG1("X %x %d\n", ep_addr, total_bytes);
+ // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
unsigned const epnum = tu_edpt_number(ep_addr);
musb_int_mask();
@@ -1111,7 +1111,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_
{
(void)rhport;
bool ret;
- // TU_LOG1("X %x %d\n", ep_addr, total_bytes);
+ // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
unsigned const epnum = tu_edpt_number(ep_addr);
TU_ASSERT(epnum);
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index c3d3ae085..69d96aff0 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -82,8 +82,8 @@
static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2];
typedef struct {
- uint8_t * buffer;
- tu_fifo_t * ff;
+ uint8_t* buffer;
+ tu_fifo_t* ff;
uint16_t total_len;
uint16_t max_size;
uint8_t interval;
@@ -93,45 +93,170 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2];
#define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir])
// EP0 transfers are limited to 1 packet - larger sizes has to be split
-static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type
+static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type
// TX FIFO RAM allocation so far in words - RX FIFO size is readily available from dwc2->grxfsiz
-static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs)
-static bool _out_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size)
+static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs)
// SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by
static bool _sof_en;
-// Calculate the RX FIFO size according to recommendations from reference manual
-static inline uint16_t calc_grxfsiz(uint16_t max_ep_size, uint8_t ep_count)
-{
- return 15 + 2*(max_ep_size/4) + 2*ep_count;
+// Calculate the RX FIFO size according to minimum recommendations from reference manual
+// RxFIFO = (5 * number of control endpoints + 8) +
+// ((largest USB packet used / 4) + 1 for status information) +
+// (2 * number of OUT endpoints) + 1 for Global NAK
+// with number of control endpoints = 1 we have
+// RxFIFO = 15 + (largest USB packet used / 4) + 2 * number of OUT endpoints
+// we double the largest USB packet size to be able to hold up to 2 packets
+static inline uint16_t calc_grxfsiz(uint16_t max_ep_size, uint8_t ep_count) {
+ return 15 + 2 * (max_ep_size / 4) + 2 * ep_count;
}
-static void update_grxfsiz(uint8_t rhport)
-{
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+static bool fifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ TU_ASSERT(epnum < ep_count);
+
+ uint16_t fifo_size = tu_div_ceil(packet_size, 4);
+
+ // "USB Data FIFOs" section in reference manual
+ // Peripheral FIFO architecture
+ //
+ // --------------- 320 or 1024 ( 1280 or 4096 bytes )
+ // | IN FIFO 0 |
+ // --------------- (320 or 1024) - 16
+ // | IN FIFO 1 |
+ // --------------- (320 or 1024) - 16 - x
+ // | . . . . |
+ // --------------- (320 or 1024) - 16 - x - y - ... - z
+ // | IN FIFO MAX |
+ // ---------------
+ // | FREE |
+ // --------------- GRXFSIZ
+ // | OUT FIFO |
+ // | ( Shared ) |
+ // --------------- 0
+ //
+ // In FIFO is allocated by following rules:
+ // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
+ if (dir == TUSB_DIR_OUT) {
+ // Calculate required size of RX FIFO
+ uint16_t const sz = calc_grxfsiz(4 * fifo_size, ep_count);
+
+ // If size_rx needs to be extended check if possible and if so enlarge it
+ if (dwc2->grxfsiz < sz) {
+ TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size / 4);
+
+ // Enlarge RX FIFO
+ dwc2->grxfsiz = sz;
+ }
+ } else {
+ // The fifo-empty interrupt fires when the interrupt is half empty. In order
+ // to be able to write a packet at that point, the fifo must be twice the max_size.
+ fifo_size = fifo_size * 2;
+
+ // Check if free space is available
+ TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size / 4);
+ _allocated_fifo_words_tx += fifo_size;
+ TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %lu", fifo_size * 4,
+ _dwc2_controller[rhport].ep_fifo_size - _allocated_fifo_words_tx * 4);
- // Determine largest EP size for RX FIFO
- uint16_t max_epsize = 0;
- for (uint8_t epnum = 0; epnum < ep_count; epnum++)
- {
- max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size);
+ // DIEPTXF starts at FIFO #1.
+ // Both TXFD and TXSA are in unit of 32-bit words.
+ dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) |
+ (_dwc2_controller[rhport].ep_fifo_size / 4 - _allocated_fifo_words_tx);
}
- // Update size of RX FIFO
- dwc2->grxfsiz = calc_grxfsiz(max_epsize, ep_count);
+ return true;
+}
+
+static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
+ uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
+ uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
+
+ xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir);
+ xfer->max_size = tu_edpt_packet_size(p_endpoint_desc);
+ xfer->interval = p_endpoint_desc->bInterval;
+
+ // USBAEP, EPTYP, SD0PID_SEVNFRM, MPSIZ are the same for IN and OUT endpoints.
+ uint32_t const dxepctl = (1 << DOEPCTL_USBAEP_Pos) |
+ (p_endpoint_desc->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) |
+ (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) |
+ (xfer->max_size << DOEPCTL_MPSIZ_Pos);
+
+ if (dir == TUSB_DIR_OUT) {
+ dwc2->epout[epnum].doepctl |= dxepctl;
+ dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum);
+ } else {
+ dwc2->epin[epnum].diepctl |= dxepctl | (epnum << DIEPCTL_TXFNUM_Pos);
+ dwc2->daintmsk |= (1 << (DAINTMSK_IEPM_Pos + epnum));
+ }
+}
+
+static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) {
+ (void) rhport;
+
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ if (dir == TUSB_DIR_IN) {
+ dwc2_epin_t* epin = dwc2->epin;
+
+ // Only disable currently enabled non-control endpoint
+ if ((epnum == 0) || !(epin[epnum].diepctl & DIEPCTL_EPENA)) {
+ epin[epnum].diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0);
+ } else {
+ // Stop transmitting packets and NAK IN xfers.
+ epin[epnum].diepctl |= DIEPCTL_SNAK;
+ while ((epin[epnum].diepint & DIEPINT_INEPNE) == 0) {}
+
+ // Disable the endpoint.
+ epin[epnum].diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0);
+ while ((epin[epnum].diepint & DIEPINT_EPDISD_Msk) == 0) {}
+
+ epin[epnum].diepint = DIEPINT_EPDISD;
+ }
+
+ // Flush the FIFO, and wait until we have confirmed it cleared.
+ dwc2->grstctl = ((epnum << GRSTCTL_TXFNUM_Pos) | GRSTCTL_TXFFLSH);
+ while ((dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) != 0) {}
+ } else {
+ dwc2_epout_t* epout = dwc2->epout;
+
+ // Only disable currently enabled non-control endpoint
+ if ((epnum == 0) || !(epout[epnum].doepctl & DOEPCTL_EPENA)) {
+ epout[epnum].doepctl |= stall ? DOEPCTL_STALL : 0;
+ } else {
+ // Asserting GONAK is required to STALL an OUT endpoint.
+ // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt
+ // anyway, and it can't be cleared by user code. If this while loop never
+ // finishes, we have bigger problems than just the stack.
+ dwc2->dctl |= DCTL_SGONAK;
+ while ((dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0) {}
+
+ // Ditto here- disable the endpoint.
+ epout[epnum].doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0);
+ while ((epout[epnum].doepint & DOEPINT_EPDISD_Msk) == 0) {}
+
+ epout[epnum].doepint = DOEPINT_EPDISD;
+
+ // Allow other OUT endpoints to keep receiving.
+ dwc2->dctl |= DCTL_CGONAK;
+ }
+ }
}
// Start of Bus Reset
-static void bus_reset(uint8_t rhport)
-{
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+static void bus_reset(uint8_t rhport) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
tu_memclr(xfer_status, sizeof(xfer_status));
- _out_ep_closed = false;
_sof_en = false;
@@ -139,15 +264,22 @@ static void bus_reset(uint8_t rhport)
dwc2->dcfg &= ~DCFG_DAD_Msk;
// 1. NAK for all OUT endpoints
- for ( uint8_t n = 0; n < ep_count; n++ )
- {
+ for (uint8_t n = 0; n < ep_count; n++) {
dwc2->epout[n].doepctl |= DOEPCTL_SNAK;
}
+ // flush all TX fifo and wait for it cleared
+ dwc2->grstctl = GRSTCTL_TXFFLSH | (0x10u << GRSTCTL_TXFNUM_Pos);
+ while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {}
+
+ // flush RX fifo and wait for it cleared
+ dwc2->grstctl = GRSTCTL_RXFFLSH;
+ while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {}
+
// 2. Set up interrupt mask
dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos);
- dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM;
- dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM;
+ dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM;
+ dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM;
// "USB Data FIFOs" section in reference manual
// Peripheral FIFO architecture
@@ -206,36 +338,34 @@ static void bus_reset(uint8_t rhport)
_allocated_fifo_words_tx = 16;
// Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word )
- dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx);
+ dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (_dwc2_controller[rhport].ep_fifo_size / 4 - _allocated_fifo_words_tx);
// Fixed control EP0 size to 64 bytes
dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos);
xfer_status[0][TUSB_DIR_OUT].max_size = 64;
- xfer_status[0][TUSB_DIR_IN ].max_size = 64;
+ xfer_status[0][TUSB_DIR_IN].max_size = 64;
dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos);
dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT;
}
-static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes)
-{
+static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets,
+ uint16_t total_bytes) {
(void) rhport;
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
// EP0 is limited to one packet each xfer
// We use multiple transaction of xfer->max_size length to get a whole transfer done
- if ( epnum == 0 )
- {
- xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, dir);
+ if (epnum == 0) {
+ xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, dir);
total_bytes = tu_min16(ep0_pending[dir], xfer->max_size);
ep0_pending[dir] -= total_bytes;
}
// IN and OUT endpoint xfers are interrupt-driven, we just schedule them here.
- if ( dir == TUSB_DIR_IN )
- {
+ if (dir == TUSB_DIR_IN) {
dwc2_epin_t* epin = dwc2->epin;
// A full IN transfer (multiple packets, possibly) triggers XFRC.
@@ -245,20 +375,16 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
epin[epnum].diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK;
// For ISO endpoint set correct odd/even bit for next frame.
- if ( (epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1 )
- {
+ if ((epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) {
// Take odd/even bit from frame counter.
uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos));
epin[epnum].diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk);
}
// Enable fifo empty interrupt only if there are something to put in the fifo.
- if ( total_bytes != 0 )
- {
+ if (total_bytes != 0) {
dwc2->diepempmsk |= (1 << epnum);
}
- }
- else
- {
+ } else {
dwc2_epout_t* epout = dwc2->epout;
// A full OUT transfer (multiple packets, possibly) triggers XFRC.
@@ -267,9 +393,8 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
((total_bytes << DOEPTSIZ_XFRSIZ_Pos) & DOEPTSIZ_XFRSIZ_Msk);
epout[epnum].doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK;
- if ( (epout[epnum].doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 &&
- XFER_CTL_BASE(epnum, dir)->interval == 1 )
- {
+ if ((epout[epnum].doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 &&
+ XFER_CTL_BASE(epnum, dir)->interval == 1) {
// Take odd/even bit from frame counter.
uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos));
epout[epnum].doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk);
@@ -281,93 +406,33 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
/* Controller API
*------------------------------------------------------------------*/
#if CFG_TUSB_DEBUG >= DWC2_DEBUG
-void print_dwc2_info(dwc2_regs_t * dwc2)
-{
- dwc2_ghwcfg2_t const * hw_cfg2 = &dwc2->ghwcfg2_bm;
- dwc2_ghwcfg3_t const * hw_cfg3 = &dwc2->ghwcfg3_bm;
- dwc2_ghwcfg4_t const * hw_cfg4 = &dwc2->ghwcfg4_bm;
-
-// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl);
-// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg);
-// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg);
- TU_LOG_HEX(DWC2_DEBUG, dwc2->guid);
- TU_LOG_HEX(DWC2_DEBUG, dwc2->gsnpsid);
- TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg1);
-
- // HW configure 2
- TU_LOG(DWC2_DEBUG, "\r\n");
- TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg2);
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->op_mode );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->arch );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->point2point );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->hs_phy_type );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->fs_phy_type );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->num_dev_ep );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->num_host_ch );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->period_channel_support );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->enable_dynamic_fifo );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->mul_cpu_int );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->nperiod_tx_q_depth );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->host_period_tx_q_depth );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->dev_token_q_depth );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg2->otg_enable_ic_usb );
-
- // HW configure 3
- TU_LOG(DWC2_DEBUG, "\r\n");
- TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg3);
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->xfer_size_width );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->packet_size_width );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_enable );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->i2c_enable );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->vendor_ctrl_itf );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->optional_feature_removed );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->synch_reset );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_adp_support );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->otg_enable_hsic );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->battery_charger_support );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->lpm_mode );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg3->total_fifo_size );
-
- // HW configure 4
- TU_LOG(DWC2_DEBUG, "\r\n");
- TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg4);
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->num_dev_period_in_ep );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->power_optimized );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->ahb_freq_min );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->hibernation );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->service_interval_mode );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->ipg_isoc_en );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->acg_enable );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->utmi_phy_data_width );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dev_ctrl_ep_num );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->iddg_filter_enabled );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->vbus_valid_filter_enabled );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->a_valid_filter_enabled );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->b_valid_filter_enabled );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dedicated_fifos );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->num_dev_in_eps );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dma_desc_enable );
- TU_LOG_INT(DWC2_DEBUG, hw_cfg4->dma_dynamic );
+void print_dwc2_info(dwc2_regs_t* dwc2) {
+ // print guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4
+ // use dwc2_info.py/md for bit-field value and comparison with other ports
+ volatile uint32_t const* p = (volatile uint32_t const*) &dwc2->guid;
+ TU_LOG(DWC2_DEBUG, "guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4\r\n");
+ for (size_t i = 0; i < 5; i++) {
+ TU_LOG(DWC2_DEBUG, "0x%08lX, ", p[i]);
+ }
+ TU_LOG(DWC2_DEBUG, "0x%08lX\r\n", p[5]);
}
#endif
-static void reset_core(dwc2_regs_t * dwc2)
-{
+static void reset_core(dwc2_regs_t* dwc2) {
// reset core
dwc2->grstctl |= GRSTCTL_CSRST;
// wait for reset bit is cleared
// TODO version 4.20a should wait for RESET DONE mask
- while (dwc2->grstctl & GRSTCTL_CSRST) { }
+ while (dwc2->grstctl & GRSTCTL_CSRST) {}
// wait for AHB master IDLE
- while ( !(dwc2->grstctl & GRSTCTL_AHBIDL) ) { }
+ while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {}
// wait for device mode ?
}
-static bool phy_hs_supported(dwc2_regs_t * dwc2)
-{
+static bool phy_hs_supported(dwc2_regs_t* dwc2) {
// note: esp32 incorrect report its hs_phy_type as utmi
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
return false;
@@ -376,8 +441,7 @@ static bool phy_hs_supported(dwc2_regs_t * dwc2)
#endif
}
-static void phy_fs_init(dwc2_regs_t * dwc2)
-{
+static void phy_fs_init(dwc2_regs_t* dwc2) {
TU_LOG(DWC2_DEBUG, "Fullspeed PHY init\r\n");
// Select FS PHY
@@ -401,15 +465,13 @@ static void phy_fs_init(dwc2_regs_t * dwc2)
dwc2->dcfg = (dwc2->dcfg & ~DCFG_DSPD_Msk) | (DCFG_DSPD_FS << DCFG_DSPD_Pos);
}
-static void phy_hs_init(dwc2_regs_t * dwc2)
-{
+static void phy_hs_init(dwc2_regs_t* dwc2) {
uint32_t gusbcfg = dwc2->gusbcfg;
// De-select FS PHY
gusbcfg &= ~GUSBCFG_PHYSEL;
- if (dwc2->ghwcfg2_bm.hs_phy_type == HS_PHY_TYPE_ULPI)
- {
+ if (dwc2->ghwcfg2_bm.hs_phy_type == HS_PHY_TYPE_ULPI) {
TU_LOG(DWC2_DEBUG, "Highspeed ULPI PHY init\r\n");
// Select ULPI
@@ -423,8 +485,7 @@ static void phy_hs_init(dwc2_regs_t * dwc2)
// Disable FS/LS ULPI
gusbcfg &= ~(GUSBCFG_ULPIFSLS | GUSBCFG_ULPICSM);
- }else
- {
+ } else {
TU_LOG(DWC2_DEBUG, "Highspeed UTMI+ PHY init\r\n");
// Select UTMI+ with 8-bit interface
@@ -465,8 +526,7 @@ static void phy_hs_init(dwc2_regs_t * dwc2)
dwc2->dcfg = dcfg;
}
-static bool check_dwc2(dwc2_regs_t * dwc2)
-{
+static bool check_dwc2(dwc2_regs_t* dwc2) {
#if CFG_TUSB_DEBUG >= DWC2_DEBUG
print_dwc2_info(dwc2);
#endif
@@ -481,41 +541,35 @@ static bool check_dwc2(dwc2_regs_t * dwc2)
return true;
}
-void dcd_init (uint8_t rhport)
-{
+void dcd_init(uint8_t rhport) {
// Programming model begins in the last section of the chapter on the USB
// peripheral in each Reference Manual.
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
// Check Synopsys ID register, failed if controller clock/power is not enabled
- TU_VERIFY(check_dwc2(dwc2), );
-
+ if (!check_dwc2(dwc2)) return;
dcd_disconnect(rhport);
// max number of endpoints & total_fifo_size are:
// hw_cfg2->num_dev_ep, hw_cfg2->total_fifo_size
- if( phy_hs_supported(dwc2) )
- {
- // Highspeed
- phy_hs_init(dwc2);
- }else
- {
- // core does not support highspeed or hs-phy is not present
- phy_fs_init(dwc2);
+ if (phy_hs_supported(dwc2)) {
+ phy_hs_init(dwc2); // Highspeed
+ } else {
+ phy_fs_init(dwc2); // core does not support highspeed or hs phy is not present
}
// Restart PHY clock
dwc2->pcgctl &= ~(PCGCTL_STOPPCLK | PCGCTL_GATEHCLK | PCGCTL_PWRCLMP | PCGCTL_RSTPDWNMODULE);
- /* Set HS/FS Timeout Calibration to 7 (max available value).
- * The number of PHY clocks that the application programs in
- * this field is added to the high/full speed interpacket timeout
- * duration in the core to account for any additional delays
- * introduced by the PHY. This can be required, because the delay
- * introduced by the PHY in generating the linestate condition
- * can vary from one PHY to another.
- */
+ /* Set HS/FS Timeout Calibration to 7 (max available value).
+ * The number of PHY clocks that the application programs in
+ * this field is added to the high/full speed interpacket timeout
+ * duration in the core to account for any additional delays
+ * introduced by the PHY. This can be required, because the delay
+ * introduced by the PHY in generating the linestate condition
+ * can vary from one PHY to another.
+ */
dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos);
// Force device mode
@@ -528,6 +582,14 @@ void dcd_init (uint8_t rhport)
// (non zero-length packet), send STALL back and discard.
dwc2->dcfg |= DCFG_NZLSOHSK;
+ // flush all TX fifo and wait for it cleared
+ dwc2->grstctl = GRSTCTL_TXFFLSH | (0x10u << GRSTCTL_TXFNUM_Pos);
+ while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {}
+
+ // flush RX fifo and wait for it cleared
+ dwc2->grstctl = GRSTCTL_RXFFLSH;
+ while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {}
+
// Clear all interrupts
uint32_t int_mask = dwc2->gintsts;
dwc2->gintsts |= int_mask;
@@ -538,9 +600,7 @@ void dcd_init (uint8_t rhport)
dwc2->gahbcfg &= ~GAHBCFG_TXFELVL;
// Required as part of core initialization.
- // TODO: How should mode mismatch be handled? It will cause
- // the core to stop working/require reset.
- dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_MMISM | GINTMSK_RXFLVLM |
+ dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_RXFLVLM |
GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
// Enable global interrupt
@@ -557,30 +617,26 @@ void dcd_init (uint8_t rhport)
dcd_connect(rhport);
}
-void dcd_int_enable (uint8_t rhport)
-{
+void dcd_int_enable(uint8_t rhport) {
dwc2_dcd_int_enable(rhport);
}
-void dcd_int_disable (uint8_t rhport)
-{
+void dcd_int_disable(uint8_t rhport) {
dwc2_dcd_int_disable(rhport);
}
-void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
-{
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
dwc2->dcfg = (dwc2->dcfg & ~DCFG_DAD_Msk) | (dev_addr << DCFG_DAD_Pos);
// Response with status after changing device address
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
}
-void dcd_remote_wakeup(uint8_t rhport)
-{
+void dcd_remote_wakeup(uint8_t rhport) {
(void) rhport;
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
// set remote wakeup
dwc2->dctl |= DCTL_RWUSIG;
@@ -595,35 +651,29 @@ void dcd_remote_wakeup(uint8_t rhport)
dwc2->dctl &= ~DCTL_RWUSIG;
}
-void dcd_connect(uint8_t rhport)
-{
+void dcd_connect(uint8_t rhport) {
(void) rhport;
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
dwc2->dctl &= ~DCTL_SDIS;
}
-void dcd_disconnect(uint8_t rhport)
-{
+void dcd_disconnect(uint8_t rhport) {
(void) rhport;
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
dwc2->dctl |= DCTL_SDIS;
}
// Be advised: audio, video and possibly other iso-ep classes use dcd_sof_enable() to enable/disable its corresponding ISR on purpose!
-void dcd_sof_enable(uint8_t rhport, bool en)
-{
+void dcd_sof_enable(uint8_t rhport, bool en) {
(void) rhport;
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
_sof_en = en;
- if (en)
- {
+ if (en) {
dwc2->gintsts = GINTSTS_SOF;
dwc2->gintmsk |= GINTMSK_SOFM;
- }
- else
- {
+ } else {
dwc2->gintmsk &= ~GINTMSK_SOFM;
}
}
@@ -632,107 +682,21 @@ void dcd_sof_enable(uint8_t rhport, bool en)
/* DCD Endpoint port
*------------------------------------------------------------------*/
-bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
-{
- (void) rhport;
-
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
- uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
-
- uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
- uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
-
- TU_ASSERT(epnum < ep_count);
-
- xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
- xfer->max_size = tu_edpt_packet_size(desc_edpt);
- xfer->interval = desc_edpt->bInterval;
-
- uint16_t fifo_size = tu_div_ceil(xfer->max_size, 4);
-
- if(dir == TUSB_DIR_OUT)
- {
- // Calculate required size of RX FIFO
- uint16_t const sz = calc_grxfsiz(4*fifo_size, ep_count);
-
- // If size_rx needs to be extended check if possible and if so enlarge it
- if (dwc2->grxfsiz < sz)
- {
- TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size/4);
-
- // Enlarge RX FIFO
- dwc2->grxfsiz = sz;
- }
-
- dwc2->epout[epnum].doepctl |= (1 << DOEPCTL_USBAEP_Pos) |
- (desc_edpt->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) |
- (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) |
- (xfer->max_size << DOEPCTL_MPSIZ_Pos);
-
- dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum);
- }
- else
- {
- // "USB Data FIFOs" section in reference manual
- // Peripheral FIFO architecture
- //
- // --------------- 320 or 1024 ( 1280 or 4096 bytes )
- // | IN FIFO 0 |
- // --------------- (320 or 1024) - 16
- // | IN FIFO 1 |
- // --------------- (320 or 1024) - 16 - x
- // | . . . . |
- // --------------- (320 or 1024) - 16 - x - y - ... - z
- // | IN FIFO MAX |
- // ---------------
- // | FREE |
- // --------------- GRXFSIZ
- // | OUT FIFO |
- // | ( Shared ) |
- // --------------- 0
- //
- // In FIFO is allocated by following rules:
- // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
-
- // The fifo-empty interrupt fires when the interrupt is half empty. In order
- // to be able to write a packet at that point, the fifo must be twice the
- // max_size.
- fifo_size = fifo_size * 2;
-
- // Check if free space is available
- TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size/4);
-
- _allocated_fifo_words_tx += fifo_size;
-
- TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %lu", fifo_size*4, _dwc2_controller[rhport].ep_fifo_size-_allocated_fifo_words_tx*4);
-
- // DIEPTXF starts at FIFO #1.
- // Both TXFD and TXSA are in unit of 32-bit words.
- dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx);
-
- dwc2->epin[epnum].diepctl |= (1 << DIEPCTL_USBAEP_Pos) |
- (epnum << DIEPCTL_TXFNUM_Pos) |
- (desc_edpt->bmAttributes.xfer << DIEPCTL_EPTYP_Pos) |
- (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DIEPCTL_SD0PID_SEVNFRM : 0) |
- (xfer->max_size << DIEPCTL_MPSIZ_Pos);
-
- dwc2->daintmsk |= (1 << (DAINTMSK_IEPM_Pos + epnum));
- }
-
+bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
+ TU_ASSERT(fifo_alloc(rhport, desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt)));
+ edpt_activate(rhport, desc_edpt);
return true;
}
// Close all non-control endpoints, cancel all pending transfers if any.
-void dcd_edpt_close_all (uint8_t rhport)
-{
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+void dcd_edpt_close_all(uint8_t rhport) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
// Disable non-control interrupt
dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos);
- for(uint8_t n = 1; n < ep_count; n++)
- {
+ for (uint8_t n = 1; n < ep_count; n++) {
// disable OUT endpoint
dwc2->epout[n].doepctl = 0;
xfer_status[n][TUSB_DIR_OUT].max_size = 0;
@@ -746,31 +710,41 @@ void dcd_edpt_close_all (uint8_t rhport)
_allocated_fifo_words_tx = 16;
}
-bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
-{
+bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
+ TU_ASSERT(fifo_alloc(rhport, ep_addr, largest_packet_size));
+ return true;
+}
+
+bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) {
+ // Disable EP to clear potential incomplete transfers
+ edpt_disable(rhport, p_endpoint_desc->bEndpointAddress, false);
+
+ edpt_activate(rhport, p_endpoint_desc);
+
+ return true;
+}
+
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
- xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
- xfer->buffer = buffer;
- xfer->ff = NULL;
- xfer->total_len = total_bytes;
+ xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir);
+ xfer->buffer = buffer;
+ xfer->ff = NULL;
+ xfer->total_len = total_bytes;
// EP0 can only handle one packet
- if(epnum == 0)
- {
+ if (epnum == 0) {
ep0_pending[dir] = total_bytes;
// Schedule the first transaction for EP0 transfer
edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]);
- }
- else
- {
+ } else {
uint16_t num_packets = (total_bytes / xfer->max_size);
uint16_t const short_packet_size = total_bytes % xfer->max_size;
// Zero-size packet is special case.
- if ( (short_packet_size > 0) || (total_bytes == 0) ) num_packets++;
+ if ((short_packet_size > 0) || (total_bytes == 0)) num_packets++;
// Schedule packets to be sent within interrupt
edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes);
@@ -783,24 +757,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
// bytes should be written and second to keep the return value free to give back a boolean
// success message. If total_bytes is too big, the FIFO will copy only what is available
// into the USB buffer!
-bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
-{
+bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) {
// USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
TU_ASSERT(ff->item_size == 1);
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
- xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
- xfer->buffer = NULL;
- xfer->ff = ff;
- xfer->total_len = total_bytes;
+ xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir);
+ xfer->buffer = NULL;
+ xfer->ff = ff;
+ xfer->total_len = total_bytes;
uint16_t num_packets = (total_bytes / xfer->max_size);
uint16_t const short_packet_size = total_bytes % xfer->max_size;
// Zero-size packet is special case.
- if ( short_packet_size > 0 || (total_bytes == 0) ) num_packets++;
+ if (short_packet_size > 0 || (total_bytes == 0)) num_packets++;
// Schedule packets to be sent within interrupt
edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes);
@@ -808,123 +781,27 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16
return true;
}
-static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall)
-{
- (void) rhport;
-
- dwc2_regs_t *dwc2 = DWC2_REG(rhport);
-
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- if ( dir == TUSB_DIR_IN )
- {
- dwc2_epin_t* epin = dwc2->epin;
-
- // Only disable currently enabled non-control endpoint
- if ( (epnum == 0) || !(epin[epnum].diepctl & DIEPCTL_EPENA) )
- {
- epin[epnum].diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0);
- }
- else
- {
- // Stop transmitting packets and NAK IN xfers.
- epin[epnum].diepctl |= DIEPCTL_SNAK;
- while ( (epin[epnum].diepint & DIEPINT_INEPNE) == 0 ) {}
-
- // Disable the endpoint.
- epin[epnum].diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0);
- while ( (epin[epnum].diepint & DIEPINT_EPDISD_Msk) == 0 ) {}
-
- epin[epnum].diepint = DIEPINT_EPDISD;
- }
-
- // Flush the FIFO, and wait until we have confirmed it cleared.
- dwc2->grstctl = ((epnum << GRSTCTL_TXFNUM_Pos) | GRSTCTL_TXFFLSH);
- while ( (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) != 0 ) {}
- }
- else
- {
- dwc2_epout_t* epout = dwc2->epout;
-
- // Only disable currently enabled non-control endpoint
- if ( (epnum == 0) || !(epout[epnum].doepctl & DOEPCTL_EPENA) )
- {
- epout[epnum].doepctl |= stall ? DOEPCTL_STALL : 0;
- }
- else
- {
- // Asserting GONAK is required to STALL an OUT endpoint.
- // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt
- // anyway, and it can't be cleared by user code. If this while loop never
- // finishes, we have bigger problems than just the stack.
- dwc2->dctl |= DCTL_SGONAK;
- while ( (dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0 ) {}
-
- // Ditto here- disable the endpoint.
- epout[epnum].doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0);
- while ( (epout[epnum].doepint & DOEPINT_EPDISD_Msk) == 0 ) {}
-
- epout[epnum].doepint = DOEPINT_EPDISD;
-
- // Allow other OUT endpoints to keep receiving.
- dwc2->dctl |= DCTL_CGONAK;
- }
- }
+void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
+ edpt_disable(rhport, ep_addr, false);
}
-/**
- * Close an endpoint.
- */
-void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
-{
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
-
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- dcd_edpt_disable(rhport, ep_addr, false);
-
- // Update max_size
- xfer_status[epnum][dir].max_size = 0; // max_size = 0 marks a disabled EP - required for changing FIFO allocation
-
- if (dir == TUSB_DIR_IN)
- {
- uint16_t const fifo_size = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXFD_Msk) >> DIEPTXF_INEPTXFD_Pos;
- uint16_t const fifo_start = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXSA_Msk) >> DIEPTXF_INEPTXSA_Pos;
-
- // For now only the last opened endpoint can be closed without fuss.
- TU_ASSERT(fifo_start == _dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx,);
- _allocated_fifo_words_tx -= fifo_size;
- }
- else
- {
- _out_ep_closed = true; // Set flag such that RX FIFO gets reduced in size once RX FIFO is empty
- }
-}
-
-void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
-{
- dcd_edpt_disable(rhport, ep_addr, true);
+void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
+ edpt_disable(rhport, ep_addr, true);
}
-void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
-{
+void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
(void) rhport;
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
// Clear stall and reset data toggle
- if ( dir == TUSB_DIR_IN )
- {
+ if (dir == TUSB_DIR_IN) {
dwc2->epin[epnum].diepctl &= ~DIEPCTL_STALL;
dwc2->epin[epnum].diepctl |= DIEPCTL_SD0PID_SEVNFRM;
- }
- else
- {
+ } else {
dwc2->epout[epnum].doepctl &= ~DOEPCTL_STALL;
dwc2->epout[epnum].doepctl |= DOEPCTL_SD0PID_SEVNFRM;
}
@@ -933,70 +810,63 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
/*------------------------------------------------------------------*/
// Read a single data packet from receive FIFO
-static void read_fifo_packet(uint8_t rhport, uint8_t * dst, uint16_t len)
-{
+static void read_fifo_packet(uint8_t rhport, uint8_t* dst, uint16_t len) {
(void) rhport;
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
- volatile const uint32_t * rx_fifo = dwc2->fifo[0];
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
+ volatile const uint32_t* rx_fifo = dwc2->fifo[0];
// Reading full available 32 bit words from fifo
uint16_t full_words = len >> 2;
- while(full_words--)
- {
+ while (full_words--) {
tu_unaligned_write32(dst, *rx_fifo);
dst += 4;
}
// Read the remaining 1-3 bytes from fifo
uint8_t const bytes_rem = len & 0x03;
- if ( bytes_rem != 0 )
- {
+ if (bytes_rem != 0) {
uint32_t const tmp = *rx_fifo;
dst[0] = tu_u32_byte0(tmp);
- if ( bytes_rem > 1 ) dst[1] = tu_u32_byte1(tmp);
- if ( bytes_rem > 2 ) dst[2] = tu_u32_byte2(tmp);
+ if (bytes_rem > 1) dst[1] = tu_u32_byte1(tmp);
+ if (bytes_rem > 2) dst[2] = tu_u32_byte2(tmp);
}
}
// Write a single data packet to EPIN FIFO
-static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const * src, uint16_t len)
-{
+static void write_fifo_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const* src, uint16_t len) {
(void) rhport;
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
- volatile uint32_t * tx_fifo = dwc2->fifo[fifo_num];
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
+ volatile uint32_t* tx_fifo = dwc2->fifo[fifo_num];
// Pushing full available 32 bit words to fifo
uint16_t full_words = len >> 2;
- while(full_words--)
- {
+ while (full_words--) {
*tx_fifo = tu_unaligned_read32(src);
src += 4;
}
// Write the remaining 1-3 bytes into fifo
uint8_t const bytes_rem = len & 0x03;
- if ( bytes_rem )
- {
+ if (bytes_rem) {
uint32_t tmp_word = src[0];
- if ( bytes_rem > 1 ) tmp_word |= (src[1] << 8);
- if ( bytes_rem > 2 ) tmp_word |= (src[2] << 16);
+ if (bytes_rem > 1) tmp_word |= (src[1] << 8);
+ if (bytes_rem > 2) tmp_word |= (src[2] << 16);
*tx_fifo = tmp_word;
}
}
-static void handle_rxflvl_irq(uint8_t rhport)
-{
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
- volatile uint32_t const * rx_fifo = dwc2->fifo[0];
+static void handle_rxflvl_irq(uint8_t rhport) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
+ volatile uint32_t const* rx_fifo = dwc2->fifo[0];
// Pop control word off FIFO
uint32_t const ctl_word = dwc2->grxstsp;
- uint8_t const pktsts = (ctl_word & GRXSTSP_PKTSTS_Msk ) >> GRXSTSP_PKTSTS_Pos;
- uint8_t const epnum = (ctl_word & GRXSTSP_EPNUM_Msk ) >> GRXSTSP_EPNUM_Pos;
- uint16_t const bcnt = (ctl_word & GRXSTSP_BCNT_Msk ) >> GRXSTSP_BCNT_Pos;
+ uint8_t const pktsts = (ctl_word & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos;
+ uint8_t const epnum = (ctl_word & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos;
+ uint16_t const bcnt = (ctl_word & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos;
dwc2_epout_t* epout = &dwc2->epout[epnum];
@@ -1011,10 +881,10 @@ static void handle_rxflvl_irq(uint8_t rhport)
// TU_LOG(DWC2_DEBUG, " daint = %08lX, doepint = %04X\r\n", (unsigned long) dwc2->daint, (unsigned int) epout->doepint);
//#endif
- switch ( pktsts )
- {
+ switch (pktsts) {
// Global OUT NAK: do nothing
- case GRXSTS_PKTSTS_GLOBALOUTNAK: break;
+ case GRXSTS_PKTSTS_GLOBALOUTNAK:
+ break;
case GRXSTS_PKTSTS_SETUPRX:
// Setup packet received
@@ -1023,26 +893,22 @@ static void handle_rxflvl_irq(uint8_t rhport)
// only the last one is valid.
_setup_packet[0] = (*rx_fifo);
_setup_packet[1] = (*rx_fifo);
- break;
+ break;
case GRXSTS_PKTSTS_SETUPDONE:
// Setup packet done (Interrupt)
epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos);
- break;
+ break;
- case GRXSTS_PKTSTS_OUTRX:
- {
+ case GRXSTS_PKTSTS_OUTRX: {
// Out packet received
- xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
+ xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
// Read packet off RxFIFO
- if ( xfer->ff )
- {
+ if (xfer->ff) {
// Ring buffer
tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, bcnt);
- }
- else
- {
+ } else {
// Linear buffer
read_fifo_packet(rhport, xfer->buffer, bcnt);
@@ -1051,73 +917,64 @@ static void handle_rxflvl_irq(uint8_t rhport)
}
// Truncate transfer length in case of short packet
- if ( bcnt < xfer->max_size )
- {
+ if (bcnt < xfer->max_size) {
xfer->total_len -= (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos;
- if ( epnum == 0 )
- {
+ if (epnum == 0) {
xfer->total_len -= ep0_pending[TUSB_DIR_OUT];
ep0_pending[TUSB_DIR_OUT] = 0;
}
}
}
- break;
+ break;
- // Out packet done (Interrupt)
+ // Out packet done (Interrupt)
case GRXSTS_PKTSTS_OUTDONE:
- // Occurred on STM32L47 with dwc2 version 3.10a but not found on other version like 2.80a or 3.30a
- // May (or not) be 3.10a specific feature/bug or depending on MCU configuration
- // XFRC complete is additionally generated when
- // - setup packet is received
- // - complete the data stage of control write is complete
- if ((epnum == 0) && (bcnt == 0) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a))
- {
- uint32_t doepint = epout->doepint;
+ // Occurred on STM32L47 with dwc2 version 3.10a but not found on other version like 2.80a or 3.30a
+ // May (or not) be 3.10a specific feature/bug or depending on MCU configuration
+ // XFRC complete is additionally generated when
+ // - setup packet is received
+ // - complete the data stage of control write is complete
+ if ((epnum == 0) && (bcnt == 0) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) {
+ uint32_t doepint = epout->doepint;
- if (doepint & (DOEPINT_STPKTRX | DOEPINT_OTEPSPR))
- {
- // skip this "no-data" transfer complete event
- // Note: STPKTRX will be clear later by setup received handler
- uint32_t clear_flags = DOEPINT_XFRC;
+ if (doepint & (DOEPINT_STPKTRX | DOEPINT_OTEPSPR)) {
+ // skip this "no-data" transfer complete event
+ // Note: STPKTRX will be clear later by setup received handler
+ uint32_t clear_flags = DOEPINT_XFRC;
- if (doepint & DOEPINT_OTEPSPR) clear_flags |= DOEPINT_OTEPSPR;
+ if (doepint & DOEPINT_OTEPSPR) clear_flags |= DOEPINT_OTEPSPR;
- epout->doepint = clear_flags;
+ epout->doepint = clear_flags;
- // TU_LOG(DWC2_DEBUG, " FIX extra transfer complete on setup/data compete\r\n");
- }
+ // TU_LOG(DWC2_DEBUG, " FIX extra transfer complete on setup/data compete\r\n");
}
- break;
+ }
+ break;
default: // Invalid
TU_BREAKPOINT();
- break;
+ break;
}
}
-static void handle_epout_irq (uint8_t rhport)
-{
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+static void handle_epout_irq(uint8_t rhport) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
// DAINT for a given EP clears when DOEPINTx is cleared.
// OEPINT will be cleared when DAINT's out bits are cleared.
- for ( uint8_t n = 0; n < ep_count; n++ )
- {
- if ( dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n) )
- {
+ for (uint8_t n = 0; n < ep_count; n++) {
+ if (dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n)) {
dwc2_epout_t* epout = &dwc2->epout[n];
uint32_t const doepint = epout->doepint;
// SETUP packet Setup Phase done.
- if ( doepint & DOEPINT_STUP )
- {
+ if (doepint & DOEPINT_STUP) {
uint32_t clear_flag = DOEPINT_STUP;
// STPKTRX is only available for version from 3_00a
- if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a))
- {
+ if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a)) {
clear_flag |= DOEPINT_STPKTRX;
}
@@ -1126,20 +983,16 @@ static void handle_epout_irq (uint8_t rhport)
}
// OUT XFER complete
- if ( epout->doepint & DOEPINT_XFRC )
- {
+ if (epout->doepint & DOEPINT_XFRC) {
epout->doepint = DOEPINT_XFRC;
- xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT);
+ xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT);
// EP0 can only handle one packet
- if ( (n == 0) && ep0_pending[TUSB_DIR_OUT] )
- {
+ if ((n == 0) && ep0_pending[TUSB_DIR_OUT]) {
// Schedule another packet to be received.
edpt_schedule_packets(rhport, n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]);
- }
- else
- {
+ } else {
dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true);
}
}
@@ -1147,40 +1000,32 @@ static void handle_epout_irq (uint8_t rhport)
}
}
-static void handle_epin_irq (uint8_t rhport)
-{
- dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+static void handle_epin_irq(uint8_t rhport) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
- dwc2_epin_t* epin = dwc2->epin;
+ dwc2_epin_t* epin = dwc2->epin;
// DAINT for a given EP clears when DIEPINTx is cleared.
// IEPINT will be cleared when DAINT's out bits are cleared.
- for ( uint8_t n = 0; n < ep_count; n++ )
- {
- if ( dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n) )
- {
+ for (uint8_t n = 0; n < ep_count; n++) {
+ if (dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n)) {
// IN XFER complete (entire xfer).
- xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_IN);
+ xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_IN);
- if ( epin[n].diepint & DIEPINT_XFRC )
- {
+ if (epin[n].diepint & DIEPINT_XFRC) {
epin[n].diepint = DIEPINT_XFRC;
// EP0 can only handle one packet
- if ( (n == 0) && ep0_pending[TUSB_DIR_IN] )
- {
+ if ((n == 0) && ep0_pending[TUSB_DIR_IN]) {
// Schedule another packet to be transmitted.
edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]);
- }
- else
- {
+ } else {
dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
}
}
// XFER FIFO empty
- if ( (epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n)) )
- {
+ if ((epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n))) {
// diepint's TXFE bit is read-only, software cannot clear it.
// It will only be cleared by hardware when written bytes is more than
// - 64 bytes or
@@ -1189,8 +1034,7 @@ static void handle_epin_irq (uint8_t rhport)
uint16_t remaining_packets = (epin[n].dieptsiz & DIEPTSIZ_PKTCNT_Msk) >> DIEPTSIZ_PKTCNT_Pos;
// Process every single packet (only whole packets can be written to fifo)
- for ( uint16_t i = 0; i < remaining_packets; i++ )
- {
+ for (uint16_t i = 0; i < remaining_packets; i++) {
uint16_t const remaining_bytes = (epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos;
// Packet can not be larger than ep max size
@@ -1198,16 +1042,13 @@ static void handle_epin_irq (uint8_t rhport)
// It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current
// EP has to be checked if the buffer can take another WHOLE packet
- if ( packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2) ) break;
+ if (packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) break;
// Push packet to Tx-FIFO
- if ( xfer->ff )
- {
- volatile uint32_t *tx_fifo = dwc2->fifo[n];
+ if (xfer->ff) {
+ volatile uint32_t* tx_fifo = dwc2->fifo[n];
tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, packet_size);
- }
- else
- {
+ } else {
write_fifo_packet(rhport, n, xfer->buffer, packet_size);
// Increment pointer to xfer data
@@ -1216,8 +1057,7 @@ static void handle_epin_irq (uint8_t rhport)
}
// Turn off TXFE if all bytes are written.
- if ( ((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0 )
- {
+ if (((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0) {
dwc2->diepempmsk &= ~(1 << n);
}
}
@@ -1225,55 +1065,50 @@ static void handle_epin_irq (uint8_t rhport)
}
}
-void dcd_int_handler(uint8_t rhport)
-{
- dwc2_regs_t *dwc2 = DWC2_REG(rhport);
+void dcd_int_handler(uint8_t rhport) {
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
uint32_t const int_mask = dwc2->gintmsk;
uint32_t const int_status = dwc2->gintsts & int_mask;
- if(int_status & GINTSTS_USBRST)
- {
+ if (int_status & GINTSTS_USBRST) {
// USBRST is start of reset.
dwc2->gintsts = GINTSTS_USBRST;
bus_reset(rhport);
}
- if(int_status & GINTSTS_ENUMDNE)
- {
+ if (int_status & GINTSTS_ENUMDNE) {
// ENUMDNE is the end of reset where speed of the link is detected
-
dwc2->gintsts = GINTSTS_ENUMDNE;
tusb_speed_t speed;
- switch ((dwc2->dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos)
- {
+ switch ((dwc2->dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos) {
case DSTS_ENUMSPD_HS:
speed = TUSB_SPEED_HIGH;
- break;
+ break;
case DSTS_ENUMSPD_LS:
speed = TUSB_SPEED_LOW;
- break;
+ break;
case DSTS_ENUMSPD_FS_HSPHY:
case DSTS_ENUMSPD_FS:
default:
speed = TUSB_SPEED_FULL;
- break;
+ break;
}
+ // TODO must update GUSBCFG_TRDT according to link speed
+
dcd_event_bus_reset(rhport, speed, true);
}
- if(int_status & GINTSTS_USBSUSP)
- {
+ if (int_status & GINTSTS_USBSUSP) {
dwc2->gintsts = GINTSTS_USBSUSP;
dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
}
- if(int_status & GINTSTS_WKUINT)
- {
+ if (int_status & GINTSTS_WKUINT) {
dwc2->gintsts = GINTSTS_WKUINT;
dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
}
@@ -1281,30 +1116,24 @@ void dcd_int_handler(uint8_t rhport)
// TODO check GINTSTS_DISCINT for disconnect detection
// if(int_status & GINTSTS_DISCINT)
- if(int_status & GINTSTS_OTGINT)
- {
+ if (int_status & GINTSTS_OTGINT) {
// OTG INT bit is read-only
uint32_t const otg_int = dwc2->gotgint;
- if (otg_int & GOTGINT_SEDET)
- {
+ if (otg_int & GOTGINT_SEDET) {
dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
}
dwc2->gotgint = otg_int;
}
- if(int_status & GINTSTS_SOF)
- {
- dwc2->gotgint = GINTSTS_SOF;
+ if(int_status & GINTSTS_SOF) {
+ dwc2->gintsts = GINTSTS_SOF;
- if (_sof_en)
- {
+ if (_sof_en) {
uint32_t frame = (dwc2->dsts & (DSTS_FNSOF)) >> 8;
dcd_event_sof(rhport, frame, true);
- }
- else
- {
+ } else {
// Disable SOF interrupt if SOF was not explicitly enabled. SOF was used for remote wakeup detection
dwc2->gintmsk &= ~GINTMSK_SOFM;
}
@@ -1313,41 +1142,28 @@ void dcd_int_handler(uint8_t rhport)
}
// RxFIFO non-empty interrupt handling.
- if(int_status & GINTSTS_RXFLVL)
- {
+ if (int_status & GINTSTS_RXFLVL) {
// RXFLVL bit is read-only
// Mask out RXFLVL while reading data from FIFO
dwc2->gintmsk &= ~GINTMSK_RXFLVLM;
// Loop until all available packets were handled
- do
- {
+ do {
handle_rxflvl_irq(rhport);
} while(dwc2->gintsts & GINTSTS_RXFLVL);
- // Manage RX FIFO size
- if (_out_ep_closed)
- {
- update_grxfsiz(rhport);
-
- // Disable flag
- _out_ep_closed = false;
- }
-
dwc2->gintmsk |= GINTMSK_RXFLVLM;
}
// OUT endpoint interrupt handling.
- if(int_status & GINTSTS_OEPINT)
- {
+ if (int_status & GINTSTS_OEPINT) {
// OEPINT is read-only, clear using DOEPINTn
handle_epout_irq(rhport);
}
// IN endpoint interrupt handling.
- if(int_status & GINTSTS_IEPINT)
- {
+ if (int_status & GINTSTS_IEPINT) {
// IEPINT bit read-only, clear using DIEPINTn
handle_epin_irq(rhport);
}
diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md
new file mode 100644
index 000000000..8690a0755
--- /dev/null
+++ b/src/portable/synopsys/dwc2/dwc2_info.md
@@ -0,0 +1,55 @@
+| | BCM2711 (Pi4) | EFM32GG FullSpeed | ESP32-S2 | STM32F407 Fullspeed | STM32F407 Highspeed | STM32F411 Fullspeed | STM32F412 Fullspeed | STM32F429 Fullspeed | STM32F429 Highspeed | STM32F723 Fullspeed | STM32F723 HighSpeed | STM32F767 Fullspeed | STM32H743 Highspeed | STM32L476 Fullspeed | STM32U5A5 Highspeed | GD32VF103 Fullspeed | XMC4500 |
+|:----------------------------|:----------------|:--------------------|:-----------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:----------------------|:-----------|
+| guid | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00001200 | 0x00002000 | 0x00001200 | 0x00001100 | 0x00003000 | 0x00003100 | 0x00002000 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00001000 | 0x00AEC000 |
+| gsnpsid | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54281A | 0x4F54281A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x00000000 | 0x4F54292A |
+| - specs version | 2.80a | 3.30a | 4.00a | 2.81a | 2.81a | 2.81a | 3.20a | 2.81a | 2.81a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 0.00W | 2.92a |
+| ghwcfg1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 |
+| ghwcfg2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x229DCD20 | 0x229ED590 | 0x229DCD20 | 0x229ED520 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229FE1D0 | 0x229ED520 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x00000000 | 0x228F5930 |
+| - op_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 |
+| - arch | 2 | 2 | 2 | 0 | 2 | 0 | 0 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 2 |
+| - point2point | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 |
+| - hs_phy_type | 1 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 2 | 0 | 3 | 0 | 2 | 0 | 1 | 0 | 0 |
+| - fs_phy_type | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
+| - num_dev_ep | 7 | 6 | 6 | 3 | 5 | 3 | 5 | 3 | 5 | 5 | 8 | 5 | 8 | 5 | 8 | 0 | 6 |
+| - num_host_ch | 7 | 13 | 7 | 7 | 11 | 7 | 11 | 7 | 11 | 11 | 15 | 11 | 15 | 11 | 15 | 0 | 13 |
+| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
+| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
+| - mul_cpu_int | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
+| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+| - nperiod_tx_q_depth | 2 | 2 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 0 | 2 |
+| - host_period_tx_q_depth | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 0 | 2 |
+| - dev_token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | 8 |
+| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+| ghwcfg3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x020001E8 | 0x03F403E8 | 0x020001E8 | 0x0200D1E8 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x03EED2E8 | 0x0200D1E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x00000000 | 0x027A01E5 |
+| - xfer_size_width | 8 | 8 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | 5 |
+| - packet_size_width | 6 | 6 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | 6 |
+| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
+| - i2c_enable | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 |
+| - vendor_ctrl_itf | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
+| - optional_feature_removed | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+| - otg_adp_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
+| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
+| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 |
+| - total_fifo_size | 4080 | 498 | 200 | 512 | 1012 | 512 | 512 | 512 | 1012 | 512 | 1006 | 512 | 952 | 512 | 952 | 0 | 634 |
+| ghwcfg4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0x0FF08030 | 0x17F00030 | 0x0FF08030 | 0x17F08030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x23F00030 | 0x17F08030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0x00000000 | 0xDBF08030 |
+| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+| - power_optimized | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
+| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
+| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+| - reserved7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 0 | 0 |
+| - service_interval_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+| - ipg_isoc_en | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+| - acg_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+| - reserved13 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
+| - utmi_phy_data_width | 0 | 2 | 2 | 2 | 0 | 2 | 2 | 2 | 0 | 2 | 0 | 2 | 0 | 2 | 0 | 0 | 2 |
+| - dev_ctrl_ep_num | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+| - iddg_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
+| - vbus_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
+| - a_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
+| - b_valid_filter_enabled | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
+| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
+| - num_dev_in_eps | 15 | 13 | 9 | 7 | 11 | 7 | 11 | 7 | 11 | 11 | 1 | 11 | 1 | 11 | 1 | 0 | 13 |
+| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
+| - dma_dynamic | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 |
diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py
new file mode 100644
index 000000000..55bec3d23
--- /dev/null
+++ b/src/portable/synopsys/dwc2/dwc2_info.py
@@ -0,0 +1,169 @@
+import click
+import ctypes
+import pandas as pd
+
+# hex value for register: guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4
+dwc2_reg_list = ['guid', 'gsnpsid', 'ghwcfg1', 'ghwcfg2', 'ghwcfg3', 'ghwcfg4']
+dwc2_reg_value = {
+ 'BCM2711 (Pi4)': [0x2708A000, 0x4F54280A, 0, 0x228DDD50, 0xFF000E8, 0x1FF00020],
+ 'EFM32GG FullSpeed': [0, 0x4F54330A, 0, 0x228F5910, 0x1F204E8, 0x1BF08030],
+ 'ESP32-S2': [0, 0x4F54400A, 0, 0x224DD930, 0xC804B5, 0xD3F0A030],
+ 'STM32F407 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030],
+ 'STM32F407 Highspeed': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030],
+ 'STM32F411 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030],
+ 'STM32F412 Fullspeed': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
+ 'STM32F429 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030],
+ 'STM32F429 Highspeed': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030],
+ 'STM32F723 Fullspeed': [0x3000, 0x4F54330A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
+ 'STM32F723 HighSpeed': [0x3100, 0x4F54330A, 0, 0x229FE1D0, 0x3EED2E8, 0x23F00030],
+ 'STM32F767 Fullspeed': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
+ 'STM32H743 Highspeed': [0x2300, 0x4F54330A, 0, 0x229FE190, 0x3B8D2E8, 0xE3F00030], # both HS cores
+ 'STM32L476 Fullspeed': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
+ 'STM32U5A5 Highspeed': [0x00005000, 0x4F54411A, 0x00000000, 0x228FE052, 0x03B882E8, 0xE2103E30],
+ 'GD32VF103 Fullspeed': [0x1000, 0, 0, 0, 0, 0],
+ 'XMC4500': [0xAEC000, 0x4F54292A, 0, 0x228F5930, 0x27A01E5, 0xDBF08030]
+}
+
+# Combine dwc2_info with dwc2_reg_list
+# dwc2_info = {
+# 'BCM2711 (Pi4)': {
+# 'guid': 0x2708A000,
+# 'gsnpsid': 0x4F54280A,
+# 'ghwcfg1': 0,
+# 'ghwcfg2': 0x228DDD50,
+# 'ghwcfg3': 0xFF000E8,
+# 'ghwcfg4': 0x1FF00020
+# },
+dwc2_info = {key: {field: value for field, value in zip(dwc2_reg_list, values)} for key, values in dwc2_reg_value.items()}
+
+
+class GHWCFG2(ctypes.LittleEndianStructure):
+ _fields_ = [
+ ("op_mode", ctypes.c_uint32, 3),
+ ("arch", ctypes.c_uint32, 2),
+ ("point2point", ctypes.c_uint32, 1),
+ ("hs_phy_type", ctypes.c_uint32, 2),
+ ("fs_phy_type", ctypes.c_uint32, 2),
+ ("num_dev_ep", ctypes.c_uint32, 4),
+ ("num_host_ch", ctypes.c_uint32, 4),
+ ("period_channel_support", ctypes.c_uint32, 1),
+ ("enable_dynamic_fifo", ctypes.c_uint32, 1),
+ ("mul_cpu_int", ctypes.c_uint32, 1),
+ ("reserved21", ctypes.c_uint32, 1),
+ ("nperiod_tx_q_depth", ctypes.c_uint32, 2),
+ ("host_period_tx_q_depth", ctypes.c_uint32, 2),
+ ("dev_token_q_depth", ctypes.c_uint32, 5),
+ ("otg_enable_ic_usb", ctypes.c_uint32, 1)
+ ]
+
+
+class GHWCFG3(ctypes.LittleEndianStructure):
+ _fields_ = [
+ ("xfer_size_width", ctypes.c_uint32, 4),
+ ("packet_size_width", ctypes.c_uint32, 3),
+ ("otg_enable", ctypes.c_uint32, 1),
+ ("i2c_enable", ctypes.c_uint32, 1),
+ ("vendor_ctrl_itf", ctypes.c_uint32, 1),
+ ("optional_feature_removed", ctypes.c_uint32, 1),
+ ("synch_reset", ctypes.c_uint32, 1),
+ ("otg_adp_support", ctypes.c_uint32, 1),
+ ("otg_enable_hsic", ctypes.c_uint32, 1),
+ ("battery_charger_support", ctypes.c_uint32, 1),
+ ("lpm_mode", ctypes.c_uint32, 1),
+ ("total_fifo_size", ctypes.c_uint32, 16)
+ ]
+
+
+class GHWCFG4(ctypes.LittleEndianStructure):
+ _fields_ = [
+ ("num_dev_period_in_ep", ctypes.c_uint32, 4),
+ ("power_optimized", ctypes.c_uint32, 1),
+ ("ahb_freq_min", ctypes.c_uint32, 1),
+ ("hibernation", ctypes.c_uint32, 1),
+ ("reserved7", ctypes.c_uint32, 3),
+ ("service_interval_mode", ctypes.c_uint32, 1),
+ ("ipg_isoc_en", ctypes.c_uint32, 1),
+ ("acg_enable", ctypes.c_uint32, 1),
+ ("reserved13", ctypes.c_uint32, 1),
+ ("utmi_phy_data_width", ctypes.c_uint32, 2),
+ ("dev_ctrl_ep_num", ctypes.c_uint32, 4),
+ ("iddg_filter_enabled", ctypes.c_uint32, 1),
+ ("vbus_valid_filter_enabled", ctypes.c_uint32, 1),
+ ("a_valid_filter_enabled", ctypes.c_uint32, 1),
+ ("b_valid_filter_enabled", ctypes.c_uint32, 1),
+ ("dedicated_fifos", ctypes.c_uint32, 1),
+ ("num_dev_in_eps", ctypes.c_uint32, 4),
+ ("dma_desc_enable", ctypes.c_uint32, 1),
+ ("dma_dynamic", ctypes.c_uint32, 1)
+ ]
+
+
+def cli():
+ pass
+
+
[email protected]('mcus', nargs=-1)
[email protected]('-a', '--all', is_flag=True, help='Print all bit-field values')
+def info(mcus, all):
+ """Print DWC2 register values for given MCU(s)"""
+ if len(mcus) == 0:
+ mcus = dwc2_info
+
+ for mcu in mcus:
+ for entry in dwc2_info:
+ if mcu.lower() in entry.lower():
+ print(f"## {entry}")
+ for r_name, r_value in dwc2_info[entry].items():
+ print(f"{r_name} = 0x{r_value:08X}")
+ # Print bit-field values
+ if all and r_name.upper() in globals():
+ class_name = globals()[r_name.upper()]
+ ghwcfg = class_name.from_buffer_copy(r_value.to_bytes(4, byteorder='little'))
+ for field_name, field_type, _ in class_name._fields_:
+ print(f" {field_name} = {getattr(ghwcfg, field_name)}")
+
+
+def render_md():
+ """Render dwc2_info to Markdown table"""
+ # Create an empty list to hold the dictionaries
+ dwc2_info_list = []
+
+ # Iterate over the dwc2_info dictionary and extract fields
+ for device, reg_values in dwc2_info.items():
+ entry_dict = {"Device": device}
+ for r_name, r_value in reg_values.items():
+ entry_dict[r_name] = f"0x{r_value:08X}"
+
+ if r_name == 'gsnpsid':
+ # Get dwc2 specs version
+ major = ((r_value >> 8) >> 4) & 0x0F
+ minor = (r_value >> 4) & 0xFF
+ patch = chr((r_value & 0x0F) + ord('a') - 0xA)
+ entry_dict[f' - specs version'] = f"{major:X}.{minor:02X}{patch}"
+ elif r_name.upper() in globals():
+ # Get bit-field values which exist as ctypes structures
+ class_name = globals()[r_name.upper()]
+ ghwcfg = class_name.from_buffer_copy(r_value.to_bytes(4, byteorder='little'))
+ for field_name, field_type, _ in class_name._fields_:
+ entry_dict[f' - {field_name}'] = getattr(ghwcfg, field_name)
+
+ dwc2_info_list.append(entry_dict)
+
+ # Create a Pandas DataFrame from the list of dictionaries
+ df = pd.DataFrame(dwc2_info_list).set_index('Device')
+
+ # Transpose the DataFrame to switch rows and columns
+ df = df.T
+ #print(df)
+
+ # Write the Markdown table to a file
+ with open('dwc2_info.md', 'w') as md_file:
+ md_file.write(df.to_markdown())
+ md_file.write('\n')
+
+
+if __name__ == '__main__':
+ cli()
diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h
index cb455bd90..3237a50f6 100644
--- a/src/portable/synopsys/dwc2/dwc2_stm32.h
+++ b/src/portable/synopsys/dwc2/dwc2_stm32.h
@@ -24,11 +24,11 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _DWC2_STM32_H_
-#define _DWC2_STM32_H_
+#ifndef DWC2_STM32_H_
+#define DWC2_STM32_H_
#ifdef __cplusplus
- extern "C" {
+extern "C" {
#endif
// EP_MAX : Max number of bi-directional endpoints including EP0
@@ -84,10 +84,16 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32U5
#include "stm32u5xx.h"
- #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE
- #define EP_MAX_FS 6
- #define EP_FIFO_SIZE_FS 1280
-
+ // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY
+ #ifdef USB_OTG_FS
+ #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE
+ #define EP_MAX_FS 6
+ #define EP_FIFO_SIZE_FS 1280
+ #else
+ #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE
+ #define EP_MAX_HS 9
+ #define EP_FIFO_SIZE_HS 4096
+ #endif
#else
#error "Unsupported MCUs"
#endif
@@ -101,15 +107,14 @@
// On STM32 for consistency we associate
// - Port0 to OTG_FS, and Port1 to OTG_HS
-static const dwc2_controller_t _dwc2_controller[] =
-{
-#ifdef USB_OTG_FS_PERIPH_BASE
- { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS },
-#endif
+static const dwc2_controller_t _dwc2_controller[] = {
+ #ifdef USB_OTG_FS_PERIPH_BASE
+ { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS },
+ #endif
-#ifdef USB_OTG_HS_PERIPH_BASE
- { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS },
-#endif
+ #ifdef USB_OTG_HS_PERIPH_BASE
+ { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS },
+ #endif
};
//--------------------------------------------------------------------+
@@ -119,42 +124,59 @@ static const dwc2_controller_t _dwc2_controller[] =
// SystemCoreClock is already included by family header
// extern uint32_t SystemCoreClock;
-TU_ATTR_ALWAYS_INLINE
-static inline void dwc2_dcd_int_enable(uint8_t rhport)
-{
- NVIC_EnableIRQ((IRQn_Type)_dwc2_controller[rhport].irqnum);
+TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) {
+ NVIC_EnableIRQ((IRQn_Type) _dwc2_controller[rhport].irqnum);
}
-TU_ATTR_ALWAYS_INLINE
-static inline void dwc2_dcd_int_disable (uint8_t rhport)
-{
- NVIC_DisableIRQ((IRQn_Type)_dwc2_controller[rhport].irqnum);
+TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_disable(uint8_t rhport) {
+ NVIC_DisableIRQ((IRQn_Type) _dwc2_controller[rhport].irqnum);
}
-TU_ATTR_ALWAYS_INLINE
-static inline void dwc2_remote_wakeup_delay(void)
-{
+TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) {
// try to delay for 1 ms
uint32_t count = SystemCoreClock / 1000;
- while ( count-- ) __NOP();
+ while (count--) __NOP();
}
// MCU specific PHY init, called BEFORE core reset
-static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
-{
- if ( hs_phy_type == HS_PHY_TYPE_NONE )
- {
+// - dwc2 3.30a (H5) use USB_HS_PHYC
+// - dwc2 4.11a (U5) use femtoPHY
+static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) {
+ if (hs_phy_type == HS_PHY_TYPE_NONE) {
// Enable on-chip FS PHY
dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN;
- }else
- {
- // Disable FS PHY
+
+ // https://community.st.com/t5/stm32cubemx-mcus/why-stm32h743-usb-fs-doesn-t-work-if-freertos-tickless-idle/m-p/349480#M18867
+ // H7 running on full-speed phy need to disable ULPI clock in sleep mode.
+ // Otherwise, USB won't work when mcu executing WFI/WFE instruction i.e tick-less RTOS.
+ // Note: there may be other family that is affected by this, but only H7 and F7 is tested so far
+ #if defined(USB_OTG_FS_PERIPH_BASE) && defined(RCC_AHB1LPENR_USB2OTGFSULPILPEN)
+ if ( USB_OTG_FS_PERIPH_BASE == (uint32_t) dwc2 ) {
+ RCC->AHB1LPENR &= ~RCC_AHB1LPENR_USB2OTGFSULPILPEN;
+ }
+ #endif
+
+ #if defined(USB_OTG_HS_PERIPH_BASE) && defined(RCC_AHB1LPENR_USB1OTGHSULPILPEN)
+ if ( USB_OTG_HS_PERIPH_BASE == (uint32_t) dwc2 ) {
+ RCC->AHB1LPENR &= ~RCC_AHB1LPENR_USB1OTGHSULPILPEN;
+ }
+ #endif
+
+ #if defined(USB_OTG_HS_PERIPH_BASE) && defined(RCC_AHB1LPENR_OTGHSULPILPEN)
+ if ( USB_OTG_HS_PERIPH_BASE == (uint32_t) dwc2 ) {
+ RCC->AHB1LPENR &= ~RCC_AHB1LPENR_OTGHSULPILPEN;
+ }
+ #endif
+
+ } else {
+#if CFG_TUSB_MCU != OPT_MCU_STM32U5
+ // Disable FS PHY, TODO on U5A5 (dwc2 4.11a) 16th bit is 'Host CDP behavior enable'
dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN;
+#endif
// Enable on-chip HS PHY
- if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI)
- {
-#ifdef USB_HS_PHYC
+ if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI) {
+ #ifdef USB_HS_PHYC
// Enable UTMI HS PHY
dwc2->stm32_gccfg |= STM32_GCCFG_PHYHSEN;
@@ -186,40 +208,47 @@ static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
// Enable PLL internal PHY
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN;
-#endif
+ #else
+
+ #endif
}
}
}
// MCU specific PHY update, it is called AFTER init() and core reset
-static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
-{
+static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) {
// used to set turnaround time for fullspeed, nothing to do in highspeed mode
- if ( hs_phy_type == HS_PHY_TYPE_NONE )
- {
+ if (hs_phy_type == HS_PHY_TYPE_NONE) {
// Turnaround timeout depends on the AHB clock dictated by STM32 Reference Manual
uint32_t turnaround;
- if ( SystemCoreClock >= 32000000u )
+ if (SystemCoreClock >= 32000000u) {
turnaround = 0x6u;
- else if ( SystemCoreClock >= 27500000u )
+ } else if (SystemCoreClock >= 27500000u) {
turnaround = 0x7u;
- else if ( SystemCoreClock >= 24000000u )
+ } else if (SystemCoreClock >= 24000000u) {
turnaround = 0x8u;
- else if ( SystemCoreClock >= 21800000u )
+ } else if (SystemCoreClock >= 21800000u) {
turnaround = 0x9u;
- else if ( SystemCoreClock >= 20000000u )
+ }
+ else if (SystemCoreClock >= 20000000u) {
turnaround = 0xAu;
- else if ( SystemCoreClock >= 18500000u )
+ }
+ else if (SystemCoreClock >= 18500000u) {
turnaround = 0xBu;
- else if ( SystemCoreClock >= 17200000u )
+ }
+ else if (SystemCoreClock >= 17200000u) {
turnaround = 0xCu;
- else if ( SystemCoreClock >= 16000000u )
+ }
+ else if (SystemCoreClock >= 16000000u) {
turnaround = 0xDu;
- else if ( SystemCoreClock >= 15000000u )
+ }
+ else if (SystemCoreClock >= 15000000u) {
turnaround = 0xEu;
- else
+ }
+ else {
turnaround = 0xFu;
+ }
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (turnaround << GUSBCFG_TRDT_Pos);
}
@@ -229,4 +258,4 @@ static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type)
}
#endif
-#endif /* _DWC2_STM32_H_ */
+#endif
diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h
index 3fc979337..c15771237 100644
--- a/src/portable/synopsys/dwc2/dwc2_type.h
+++ b/src/portable/synopsys/dwc2/dwc2_type.h
@@ -32,7 +32,7 @@ typedef struct
uint32_t ep_fifo_size;
}dwc2_controller_t;
-/* DWC OTG HW Release versions */
+// DWC OTG HW Release versions
#define DWC2_CORE_REV_2_71a 0x4f54271a
#define DWC2_CORE_REV_2_72a 0x4f54272a
#define DWC2_CORE_REV_2_80a 0x4f54280a
@@ -43,12 +43,13 @@ typedef struct
#define DWC2_CORE_REV_3_00a 0x4f54300a
#define DWC2_CORE_REV_3_10a 0x4f54310a
#define DWC2_CORE_REV_4_00a 0x4f54400a
+#define DWC2_CORE_REV_4_11a 0x4f54411a
#define DWC2_CORE_REV_4_20a 0x4f54420a
#define DWC2_FS_IOT_REV_1_00a 0x5531100a
#define DWC2_HS_IOT_REV_1_00a 0x5532100a
#define DWC2_CORE_REV_MASK 0x0000ffff
-/* DWC OTG HW Core ID */
+// DWC OTG HW Core ID
#define DWC2_OTG_ID 0x4f540000
#define DWC2_FS_IOT_ID 0x55310000
#define DWC2_HS_IOT_ID 0x55320000
@@ -57,13 +58,13 @@ typedef struct
// HS PHY
typedef struct
{
- volatile uint32_t HS_PHYC_PLL; // This register is used to control the PLL of the HS PHY. 000h */
- volatile uint32_t Reserved04; // Reserved 004h */
- volatile uint32_t Reserved08; // Reserved 008h */
- volatile uint32_t HS_PHYC_TUNE; // This register is used to control the tuning interface of the High Speed PHY. 00Ch */
- volatile uint32_t Reserved10; // Reserved 010h */
- volatile uint32_t Reserved14; // Reserved 014h */
- volatile uint32_t HS_PHYC_LDO; // This register is used to control the regulator (LDO). 018h */
+ volatile uint32_t HS_PHYC_PLL; // 000h This register is used to control the PLL of the HS PHY.
+ volatile uint32_t Reserved04; // 004h Reserved
+ volatile uint32_t Reserved08; // 008h Reserved
+ volatile uint32_t HS_PHYC_TUNE; // 00Ch This register is used to control the tuning interface of the High Speed PHY.
+ volatile uint32_t Reserved10; // 010h Reserved
+ volatile uint32_t Reserved14; // 014h Reserved
+ volatile uint32_t HS_PHYC_LDO; // 018h This register is used to control the regulator (LDO).
} HS_PHYC_GlobalTypeDef;
#endif
@@ -298,103 +299,103 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size");
/******************** Bit definition for GOTGCTL register ********************/
#define GOTGCTL_SRQSCS_Pos (0U)
-#define GOTGCTL_SRQSCS_Msk (0x1UL << GOTGCTL_SRQSCS_Pos) // 0x00000001 */
-#define GOTGCTL_SRQSCS GOTGCTL_SRQSCS_Msk // Session request success */
+#define GOTGCTL_SRQSCS_Msk (0x1UL << GOTGCTL_SRQSCS_Pos) // 0x00000001
+#define GOTGCTL_SRQSCS GOTGCTL_SRQSCS_Msk // Session request success
#define GOTGCTL_SRQ_Pos (1U)
-#define GOTGCTL_SRQ_Msk (0x1UL << GOTGCTL_SRQ_Pos) // 0x00000002 */
-#define GOTGCTL_SRQ GOTGCTL_SRQ_Msk // Session request */
+#define GOTGCTL_SRQ_Msk (0x1UL << GOTGCTL_SRQ_Pos) // 0x00000002
+#define GOTGCTL_SRQ GOTGCTL_SRQ_Msk // Session request
#define GOTGCTL_VBVALOEN_Pos (2U)
-#define GOTGCTL_VBVALOEN_Msk (0x1UL << GOTGCTL_VBVALOEN_Pos) // 0x00000004 */
-#define GOTGCTL_VBVALOEN GOTGCTL_VBVALOEN_Msk // VBUS valid override enable */
+#define GOTGCTL_VBVALOEN_Msk (0x1UL << GOTGCTL_VBVALOEN_Pos) // 0x00000004
+#define GOTGCTL_VBVALOEN GOTGCTL_VBVALOEN_Msk // VBUS valid override enable
#define GOTGCTL_VBVALOVAL_Pos (3U)
-#define GOTGCTL_VBVALOVAL_Msk (0x1UL << GOTGCTL_VBVALOVAL_Pos) // 0x00000008 */
-#define GOTGCTL_VBVALOVAL GOTGCTL_VBVALOVAL_Msk // VBUS valid override value */
+#define GOTGCTL_VBVALOVAL_Msk (0x1UL << GOTGCTL_VBVALOVAL_Pos) // 0x00000008
+#define GOTGCTL_VBVALOVAL GOTGCTL_VBVALOVAL_Msk // VBUS valid override value
#define GOTGCTL_AVALOEN_Pos (4U)
-#define GOTGCTL_AVALOEN_Msk (0x1UL << GOTGCTL_AVALOEN_Pos) // 0x00000010 */
-#define GOTGCTL_AVALOEN GOTGCTL_AVALOEN_Msk // A-peripheral session valid override enable */
+#define GOTGCTL_AVALOEN_Msk (0x1UL << GOTGCTL_AVALOEN_Pos) // 0x00000010
+#define GOTGCTL_AVALOEN GOTGCTL_AVALOEN_Msk // A-peripheral session valid override enable
#define GOTGCTL_AVALOVAL_Pos (5U)
-#define GOTGCTL_AVALOVAL_Msk (0x1UL << GOTGCTL_AVALOVAL_Pos) // 0x00000020 */
-#define GOTGCTL_AVALOVAL GOTGCTL_AVALOVAL_Msk // A-peripheral session valid override value */
+#define GOTGCTL_AVALOVAL_Msk (0x1UL << GOTGCTL_AVALOVAL_Pos) // 0x00000020
+#define GOTGCTL_AVALOVAL GOTGCTL_AVALOVAL_Msk // A-peripheral session valid override value
#define GOTGCTL_BVALOEN_Pos (6U)
-#define GOTGCTL_BVALOEN_Msk (0x1UL << GOTGCTL_BVALOEN_Pos) // 0x00000040 */
-#define GOTGCTL_BVALOEN GOTGCTL_BVALOEN_Msk // B-peripheral session valid override enable */
+#define GOTGCTL_BVALOEN_Msk (0x1UL << GOTGCTL_BVALOEN_Pos) // 0x00000040
+#define GOTGCTL_BVALOEN GOTGCTL_BVALOEN_Msk // B-peripheral session valid override enable
#define GOTGCTL_BVALOVAL_Pos (7U)
-#define GOTGCTL_BVALOVAL_Msk (0x1UL << GOTGCTL_BVALOVAL_Pos) // 0x00000080 */
-#define GOTGCTL_BVALOVAL GOTGCTL_BVALOVAL_Msk // B-peripheral session valid override value */
+#define GOTGCTL_BVALOVAL_Msk (0x1UL << GOTGCTL_BVALOVAL_Pos) // 0x00000080
+#define GOTGCTL_BVALOVAL GOTGCTL_BVALOVAL_Msk // B-peripheral session valid override value
#define GOTGCTL_HNGSCS_Pos (8U)
-#define GOTGCTL_HNGSCS_Msk (0x1UL << GOTGCTL_HNGSCS_Pos) // 0x00000100 */
-#define GOTGCTL_HNGSCS GOTGCTL_HNGSCS_Msk // Host set HNP enable */
+#define GOTGCTL_HNGSCS_Msk (0x1UL << GOTGCTL_HNGSCS_Pos) // 0x00000100
+#define GOTGCTL_HNGSCS GOTGCTL_HNGSCS_Msk // Host set HNP enable
#define GOTGCTL_HNPRQ_Pos (9U)
-#define GOTGCTL_HNPRQ_Msk (0x1UL << GOTGCTL_HNPRQ_Pos) // 0x00000200 */
-#define GOTGCTL_HNPRQ GOTGCTL_HNPRQ_Msk // HNP request */
+#define GOTGCTL_HNPRQ_Msk (0x1UL << GOTGCTL_HNPRQ_Pos) // 0x00000200
+#define GOTGCTL_HNPRQ GOTGCTL_HNPRQ_Msk // HNP request
#define GOTGCTL_HSHNPEN_Pos (10U)
-#define GOTGCTL_HSHNPEN_Msk (0x1UL << GOTGCTL_HSHNPEN_Pos) // 0x00000400 */
-#define GOTGCTL_HSHNPEN GOTGCTL_HSHNPEN_Msk // Host set HNP enable */
+#define GOTGCTL_HSHNPEN_Msk (0x1UL << GOTGCTL_HSHNPEN_Pos) // 0x00000400
+#define GOTGCTL_HSHNPEN GOTGCTL_HSHNPEN_Msk // Host set HNP enable
#define GOTGCTL_DHNPEN_Pos (11U)
-#define GOTGCTL_DHNPEN_Msk (0x1UL << GOTGCTL_DHNPEN_Pos) // 0x00000800 */
-#define GOTGCTL_DHNPEN GOTGCTL_DHNPEN_Msk // Device HNP enabled */
+#define GOTGCTL_DHNPEN_Msk (0x1UL << GOTGCTL_DHNPEN_Pos) // 0x00000800
+#define GOTGCTL_DHNPEN GOTGCTL_DHNPEN_Msk // Device HNP enabled
#define GOTGCTL_EHEN_Pos (12U)
-#define GOTGCTL_EHEN_Msk (0x1UL << GOTGCTL_EHEN_Pos) // 0x00001000 */
-#define GOTGCTL_EHEN GOTGCTL_EHEN_Msk // Embedded host enable */
+#define GOTGCTL_EHEN_Msk (0x1UL << GOTGCTL_EHEN_Pos) // 0x00001000
+#define GOTGCTL_EHEN GOTGCTL_EHEN_Msk // Embedded host enable
#define GOTGCTL_CIDSTS_Pos (16U)
-#define GOTGCTL_CIDSTS_Msk (0x1UL << GOTGCTL_CIDSTS_Pos) // 0x00010000 */
-#define GOTGCTL_CIDSTS GOTGCTL_CIDSTS_Msk // Connector ID status */
+#define GOTGCTL_CIDSTS_Msk (0x1UL << GOTGCTL_CIDSTS_Pos) // 0x00010000
+#define GOTGCTL_CIDSTS GOTGCTL_CIDSTS_Msk // Connector ID status
#define GOTGCTL_DBCT_Pos (17U)
-#define GOTGCTL_DBCT_Msk (0x1UL << GOTGCTL_DBCT_Pos) // 0x00020000 */
-#define GOTGCTL_DBCT GOTGCTL_DBCT_Msk // Long/short debounce time */
+#define GOTGCTL_DBCT_Msk (0x1UL << GOTGCTL_DBCT_Pos) // 0x00020000
+#define GOTGCTL_DBCT GOTGCTL_DBCT_Msk // Long/short debounce time
#define GOTGCTL_ASVLD_Pos (18U)
-#define GOTGCTL_ASVLD_Msk (0x1UL << GOTGCTL_ASVLD_Pos) // 0x00040000 */
-#define GOTGCTL_ASVLD GOTGCTL_ASVLD_Msk // A-session valid */
+#define GOTGCTL_ASVLD_Msk (0x1UL << GOTGCTL_ASVLD_Pos) // 0x00040000
+#define GOTGCTL_ASVLD GOTGCTL_ASVLD_Msk // A-session valid
#define GOTGCTL_BSESVLD_Pos (19U)
-#define GOTGCTL_BSESVLD_Msk (0x1UL << GOTGCTL_BSESVLD_Pos) // 0x00080000 */
-#define GOTGCTL_BSESVLD GOTGCTL_BSESVLD_Msk // B-session valid */
+#define GOTGCTL_BSESVLD_Msk (0x1UL << GOTGCTL_BSESVLD_Pos) // 0x00080000
+#define GOTGCTL_BSESVLD GOTGCTL_BSESVLD_Msk // B-session valid
#define GOTGCTL_OTGVER_Pos (20U)
-#define GOTGCTL_OTGVER_Msk (0x1UL << GOTGCTL_OTGVER_Pos) // 0x00100000 */
-#define GOTGCTL_OTGVER GOTGCTL_OTGVER_Msk // OTG version */
+#define GOTGCTL_OTGVER_Msk (0x1UL << GOTGCTL_OTGVER_Pos) // 0x00100000
+#define GOTGCTL_OTGVER GOTGCTL_OTGVER_Msk // OTG version
/******************** Bit definition for HCFG register ********************/
#define HCFG_FSLSPCS_Pos (0U)
-#define HCFG_FSLSPCS_Msk (0x3UL << HCFG_FSLSPCS_Pos) // 0x00000003 */
-#define HCFG_FSLSPCS HCFG_FSLSPCS_Msk // FS/LS PHY clock select */
-#define HCFG_FSLSPCS_0 (0x1UL << HCFG_FSLSPCS_Pos) // 0x00000001 */
-#define HCFG_FSLSPCS_1 (0x2UL << HCFG_FSLSPCS_Pos) // 0x00000002 */
+#define HCFG_FSLSPCS_Msk (0x3UL << HCFG_FSLSPCS_Pos) // 0x00000003
+#define HCFG_FSLSPCS HCFG_FSLSPCS_Msk // FS/LS PHY clock select
+#define HCFG_FSLSPCS_0 (0x1UL << HCFG_FSLSPCS_Pos) // 0x00000001
+#define HCFG_FSLSPCS_1 (0x2UL << HCFG_FSLSPCS_Pos) // 0x00000002
#define HCFG_FSLSS_Pos (2U)
-#define HCFG_FSLSS_Msk (0x1UL << HCFG_FSLSS_Pos) // 0x00000004 */
-#define HCFG_FSLSS HCFG_FSLSS_Msk // FS- and LS-only support */
+#define HCFG_FSLSS_Msk (0x1UL << HCFG_FSLSS_Pos) // 0x00000004
+#define HCFG_FSLSS HCFG_FSLSS_Msk // FS- and LS-only support
/******************** Bit definition for PCGCR register ********************/
#define PCGCR_STPPCLK_Pos (0U)
-#define PCGCR_STPPCLK_Msk (0x1UL << PCGCR_STPPCLK_Pos) // 0x00000001 */
-#define PCGCR_STPPCLK PCGCR_STPPCLK_Msk // Stop PHY clock */
+#define PCGCR_STPPCLK_Msk (0x1UL << PCGCR_STPPCLK_Pos) // 0x00000001
+#define PCGCR_STPPCLK PCGCR_STPPCLK_Msk // Stop PHY clock
#define PCGCR_GATEHCLK_Pos (1U)
-#define PCGCR_GATEHCLK_Msk (0x1UL << PCGCR_GATEHCLK_Pos) // 0x00000002 */
-#define PCGCR_GATEHCLK PCGCR_GATEHCLK_Msk // Gate HCLK */
+#define PCGCR_GATEHCLK_Msk (0x1UL << PCGCR_GATEHCLK_Pos) // 0x00000002
+#define PCGCR_GATEHCLK PCGCR_GATEHCLK_Msk // Gate HCLK
#define PCGCR_PHYSUSP_Pos (4U)
-#define PCGCR_PHYSUSP_Msk (0x1UL << PCGCR_PHYSUSP_Pos) // 0x00000010 */
-#define PCGCR_PHYSUSP PCGCR_PHYSUSP_Msk // PHY suspended */
+#define PCGCR_PHYSUSP_Msk (0x1UL << PCGCR_PHYSUSP_Pos) // 0x00000010
+#define PCGCR_PHYSUSP PCGCR_PHYSUSP_Msk // PHY suspended
/******************** Bit definition for GOTGINT register ********************/
#define GOTGINT_SEDET_Pos (2U)
-#define GOTGINT_SEDET_Msk (0x1UL << GOTGINT_SEDET_Pos) // 0x00000004 */
-#define GOTGINT_SEDET GOTGINT_SEDET_Msk // Session end detected */
+#define GOTGINT_SEDET_Msk (0x1UL << GOTGINT_SEDET_Pos) // 0x00000004
+#define GOTGINT_SEDET GOTGINT_SEDET_Msk // Session end detected
#define GOTGINT_SRSSCHG_Pos (8U)
-#define GOTGINT_SRSSCHG_Msk (0x1UL << GOTGINT_SRSSCHG_Pos) // 0x00000100 */
-#define GOTGINT_SRSSCHG GOTGINT_SRSSCHG_Msk // Session request success status change */
+#define GOTGINT_SRSSCHG_Msk (0x1UL << GOTGINT_SRSSCHG_Pos) // 0x00000100
+#define GOTGINT_SRSSCHG GOTGINT_SRSSCHG_Msk // Session request success status change
#define GOTGINT_HNSSCHG_Pos (9U)
-#define GOTGINT_HNSSCHG_Msk (0x1UL << GOTGINT_HNSSCHG_Pos) // 0x00000200 */
-#define GOTGINT_HNSSCHG GOTGINT_HNSSCHG_Msk // Host negotiation success status change */
+#define GOTGINT_HNSSCHG_Msk (0x1UL << GOTGINT_HNSSCHG_Pos) // 0x00000200
+#define GOTGINT_HNSSCHG GOTGINT_HNSSCHG_Msk // Host negotiation success status change
#define GOTGINT_HNGDET_Pos (17U)
-#define GOTGINT_HNGDET_Msk (0x1UL << GOTGINT_HNGDET_Pos) // 0x00020000 */
-#define GOTGINT_HNGDET GOTGINT_HNGDET_Msk // Host negotiation detected */
+#define GOTGINT_HNGDET_Msk (0x1UL << GOTGINT_HNGDET_Pos) // 0x00020000
+#define GOTGINT_HNGDET GOTGINT_HNGDET_Msk // Host negotiation detected
#define GOTGINT_ADTOCHG_Pos (18U)
-#define GOTGINT_ADTOCHG_Msk (0x1UL << GOTGINT_ADTOCHG_Pos) // 0x00040000 */
-#define GOTGINT_ADTOCHG GOTGINT_ADTOCHG_Msk // A-device timeout change */
+#define GOTGINT_ADTOCHG_Msk (0x1UL << GOTGINT_ADTOCHG_Pos) // 0x00040000
+#define GOTGINT_ADTOCHG GOTGINT_ADTOCHG_Msk // A-device timeout change
#define GOTGINT_DBCDNE_Pos (19U)
-#define GOTGINT_DBCDNE_Msk (0x1UL << GOTGINT_DBCDNE_Pos) // 0x00080000 */
-#define GOTGINT_DBCDNE GOTGINT_DBCDNE_Msk // Debounce done */
+#define GOTGINT_DBCDNE_Msk (0x1UL << GOTGINT_DBCDNE_Pos) // 0x00080000
+#define GOTGINT_DBCDNE GOTGINT_DBCDNE_Msk // Debounce done
#define GOTGINT_IDCHNG_Pos (20U)
-#define GOTGINT_IDCHNG_Msk (0x1UL << GOTGINT_IDCHNG_Pos) // 0x00100000 */
-#define GOTGINT_IDCHNG GOTGINT_IDCHNG_Msk // Change in ID pin input value */
+#define GOTGINT_IDCHNG_Msk (0x1UL << GOTGINT_IDCHNG_Pos) // 0x00100000
+#define GOTGINT_IDCHNG GOTGINT_IDCHNG_Msk // Change in ID pin input value
/******************** Bit definition for DCFG register ********************/
#define DCFG_DSPD_Pos (0U)
@@ -405,92 +406,92 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size");
#define DCFG_DSPD_FS 3 // Fullspeed on FS PHY
#define DCFG_NZLSOHSK_Pos (2U)
-#define DCFG_NZLSOHSK_Msk (0x1UL << DCFG_NZLSOHSK_Pos) // 0x00000004 */
-#define DCFG_NZLSOHSK DCFG_NZLSOHSK_Msk // Nonzero-length status OUT handshake */
+#define DCFG_NZLSOHSK_Msk (0x1UL << DCFG_NZLSOHSK_Pos) // 0x00000004
+#define DCFG_NZLSOHSK DCFG_NZLSOHSK_Msk // Nonzero-length status OUT handshake
#define DCFG_DAD_Pos (4U)
-#define DCFG_DAD_Msk (0x7FUL << DCFG_DAD_Pos) // 0x000007F0 */
-#define DCFG_DAD DCFG_DAD_Msk // Device address */
-#define DCFG_DAD_0 (0x01UL << DCFG_DAD_Pos) // 0x00000010 */
-#define DCFG_DAD_1 (0x02UL << DCFG_DAD_Pos) // 0x00000020 */
-#define DCFG_DAD_2 (0x04UL << DCFG_DAD_Pos) // 0x00000040 */
-#define DCFG_DAD_3 (0x08UL << DCFG_DAD_Pos) // 0x00000080 */
-#define DCFG_DAD_4 (0x10UL << DCFG_DAD_Pos) // 0x00000100 */
-#define DCFG_DAD_5 (0x20UL << DCFG_DAD_Pos) // 0x00000200 */
-#define DCFG_DAD_6 (0x40UL << DCFG_DAD_Pos) // 0x00000400 */
+#define DCFG_DAD_Msk (0x7FUL << DCFG_DAD_Pos) // 0x000007F0
+#define DCFG_DAD DCFG_DAD_Msk // Device address
+#define DCFG_DAD_0 (0x01UL << DCFG_DAD_Pos) // 0x00000010
+#define DCFG_DAD_1 (0x02UL << DCFG_DAD_Pos) // 0x00000020
+#define DCFG_DAD_2 (0x04UL << DCFG_DAD_Pos) // 0x00000040
+#define DCFG_DAD_3 (0x08UL << DCFG_DAD_Pos) // 0x00000080
+#define DCFG_DAD_4 (0x10UL << DCFG_DAD_Pos) // 0x00000100
+#define DCFG_DAD_5 (0x20UL << DCFG_DAD_Pos) // 0x00000200
+#define DCFG_DAD_6 (0x40UL << DCFG_DAD_Pos) // 0x00000400
#define DCFG_PFIVL_Pos (11U)
-#define DCFG_PFIVL_Msk (0x3UL << DCFG_PFIVL_Pos) // 0x00001800 */
-#define DCFG_PFIVL DCFG_PFIVL_Msk // Periodic (micro)frame interval */
-#define DCFG_PFIVL_0 (0x1UL << DCFG_PFIVL_Pos) // 0x00000800 */
-#define DCFG_PFIVL_1 (0x2UL << DCFG_PFIVL_Pos) // 0x00001000 */
+#define DCFG_PFIVL_Msk (0x3UL << DCFG_PFIVL_Pos) // 0x00001800
+#define DCFG_PFIVL DCFG_PFIVL_Msk // Periodic (micro)frame interval
+#define DCFG_PFIVL_0 (0x1UL << DCFG_PFIVL_Pos) // 0x00000800
+#define DCFG_PFIVL_1 (0x2UL << DCFG_PFIVL_Pos) // 0x00001000
#define DCFG_XCVRDLY_Pos (14U)
-#define DCFG_XCVRDLY_Msk (0x1UL << DCFG_XCVRDLY_Pos) /*!< 0x00004000 */
+#define DCFG_XCVRDLY_Msk (0x1UL << DCFG_XCVRDLY_Pos) // 0x00004000
#define DCFG_XCVRDLY DCFG_XCVRDLY_Msk // Enables delay between xcvr_sel and txvalid during device chirp
#define DCFG_PERSCHIVL_Pos (24U)
-#define DCFG_PERSCHIVL_Msk (0x3UL << DCFG_PERSCHIVL_Pos) // 0x03000000 */
-#define DCFG_PERSCHIVL DCFG_PERSCHIVL_Msk // Periodic scheduling interval */
-#define DCFG_PERSCHIVL_0 (0x1UL << DCFG_PERSCHIVL_Pos) // 0x01000000 */
-#define DCFG_PERSCHIVL_1 (0x2UL << DCFG_PERSCHIVL_Pos) // 0x02000000 */
+#define DCFG_PERSCHIVL_Msk (0x3UL << DCFG_PERSCHIVL_Pos) // 0x03000000
+#define DCFG_PERSCHIVL DCFG_PERSCHIVL_Msk // Periodic scheduling interval
+#define DCFG_PERSCHIVL_0 (0x1UL << DCFG_PERSCHIVL_Pos) // 0x01000000
+#define DCFG_PERSCHIVL_1 (0x2UL << DCFG_PERSCHIVL_Pos) // 0x02000000
/******************** Bit definition for DCTL register ********************/
#define DCTL_RWUSIG_Pos (0U)
-#define DCTL_RWUSIG_Msk (0x1UL << DCTL_RWUSIG_Pos) // 0x00000001 */
-#define DCTL_RWUSIG DCTL_RWUSIG_Msk // Remote wakeup signaling */
+#define DCTL_RWUSIG_Msk (0x1UL << DCTL_RWUSIG_Pos) // 0x00000001
+#define DCTL_RWUSIG DCTL_RWUSIG_Msk // Remote wakeup signaling
#define DCTL_SDIS_Pos (1U)
-#define DCTL_SDIS_Msk (0x1UL << DCTL_SDIS_Pos) // 0x00000002 */
-#define DCTL_SDIS DCTL_SDIS_Msk // Soft disconnect */
+#define DCTL_SDIS_Msk (0x1UL << DCTL_SDIS_Pos) // 0x00000002
+#define DCTL_SDIS DCTL_SDIS_Msk // Soft disconnect
#define DCTL_GINSTS_Pos (2U)
-#define DCTL_GINSTS_Msk (0x1UL << DCTL_GINSTS_Pos) // 0x00000004 */
-#define DCTL_GINSTS DCTL_GINSTS_Msk // Global IN NAK status */
+#define DCTL_GINSTS_Msk (0x1UL << DCTL_GINSTS_Pos) // 0x00000004
+#define DCTL_GINSTS DCTL_GINSTS_Msk // Global IN NAK status
#define DCTL_GONSTS_Pos (3U)
-#define DCTL_GONSTS_Msk (0x1UL << DCTL_GONSTS_Pos) // 0x00000008 */
-#define DCTL_GONSTS DCTL_GONSTS_Msk // Global OUT NAK status */
+#define DCTL_GONSTS_Msk (0x1UL << DCTL_GONSTS_Pos) // 0x00000008
+#define DCTL_GONSTS DCTL_GONSTS_Msk // Global OUT NAK status
#define DCTL_TCTL_Pos (4U)
-#define DCTL_TCTL_Msk (0x7UL << DCTL_TCTL_Pos) // 0x00000070 */
-#define DCTL_TCTL DCTL_TCTL_Msk // Test control */
-#define DCTL_TCTL_0 (0x1UL << DCTL_TCTL_Pos) // 0x00000010 */
-#define DCTL_TCTL_1 (0x2UL << DCTL_TCTL_Pos) // 0x00000020 */
-#define DCTL_TCTL_2 (0x4UL << DCTL_TCTL_Pos) // 0x00000040 */
+#define DCTL_TCTL_Msk (0x7UL << DCTL_TCTL_Pos) // 0x00000070
+#define DCTL_TCTL DCTL_TCTL_Msk // Test control
+#define DCTL_TCTL_0 (0x1UL << DCTL_TCTL_Pos) // 0x00000010
+#define DCTL_TCTL_1 (0x2UL << DCTL_TCTL_Pos) // 0x00000020
+#define DCTL_TCTL_2 (0x4UL << DCTL_TCTL_Pos) // 0x00000040
#define DCTL_SGINAK_Pos (7U)
-#define DCTL_SGINAK_Msk (0x1UL << DCTL_SGINAK_Pos) // 0x00000080 */
-#define DCTL_SGINAK DCTL_SGINAK_Msk // Set global IN NAK */
+#define DCTL_SGINAK_Msk (0x1UL << DCTL_SGINAK_Pos) // 0x00000080
+#define DCTL_SGINAK DCTL_SGINAK_Msk // Set global IN NAK
#define DCTL_CGINAK_Pos (8U)
-#define DCTL_CGINAK_Msk (0x1UL << DCTL_CGINAK_Pos) // 0x00000100 */
-#define DCTL_CGINAK DCTL_CGINAK_Msk // Clear global IN NAK */
+#define DCTL_CGINAK_Msk (0x1UL << DCTL_CGINAK_Pos) // 0x00000100
+#define DCTL_CGINAK DCTL_CGINAK_Msk // Clear global IN NAK
#define DCTL_SGONAK_Pos (9U)
-#define DCTL_SGONAK_Msk (0x1UL << DCTL_SGONAK_Pos) // 0x00000200 */
-#define DCTL_SGONAK DCTL_SGONAK_Msk // Set global OUT NAK */
+#define DCTL_SGONAK_Msk (0x1UL << DCTL_SGONAK_Pos) // 0x00000200
+#define DCTL_SGONAK DCTL_SGONAK_Msk // Set global OUT NAK
#define DCTL_CGONAK_Pos (10U)
-#define DCTL_CGONAK_Msk (0x1UL << DCTL_CGONAK_Pos) // 0x00000400 */
-#define DCTL_CGONAK DCTL_CGONAK_Msk // Clear global OUT NAK */
+#define DCTL_CGONAK_Msk (0x1UL << DCTL_CGONAK_Pos) // 0x00000400
+#define DCTL_CGONAK DCTL_CGONAK_Msk // Clear global OUT NAK
#define DCTL_POPRGDNE_Pos (11U)
-#define DCTL_POPRGDNE_Msk (0x1UL << DCTL_POPRGDNE_Pos) // 0x00000800 */
-#define DCTL_POPRGDNE DCTL_POPRGDNE_Msk // Power-on programming done */
+#define DCTL_POPRGDNE_Msk (0x1UL << DCTL_POPRGDNE_Pos) // 0x00000800
+#define DCTL_POPRGDNE DCTL_POPRGDNE_Msk // Power-on programming done
/******************** Bit definition for HFIR register ********************/
#define HFIR_FRIVL_Pos (0U)
-#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF */
-#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval */
+#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF
+#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval
/******************** Bit definition for HFNUM register ********************/
#define HFNUM_FRNUM_Pos (0U)
-#define HFNUM_FRNUM_Msk (0xFFFFUL << HFNUM_FRNUM_Pos) // 0x0000FFFF */
-#define HFNUM_FRNUM HFNUM_FRNUM_Msk // Frame number */
+#define HFNUM_FRNUM_Msk (0xFFFFUL << HFNUM_FRNUM_Pos) // 0x0000FFFF
+#define HFNUM_FRNUM HFNUM_FRNUM_Msk // Frame number
#define HFNUM_FTREM_Pos (16U)
-#define HFNUM_FTREM_Msk (0xFFFFUL << HFNUM_FTREM_Pos) // 0xFFFF0000 */
-#define HFNUM_FTREM HFNUM_FTREM_Msk // Frame time remaining */
+#define HFNUM_FTREM_Msk (0xFFFFUL << HFNUM_FTREM_Pos) // 0xFFFF0000
+#define HFNUM_FTREM HFNUM_FTREM_Msk // Frame time remaining
/******************** Bit definition for DSTS register ********************/
#define DSTS_SUSPSTS_Pos (0U)
-#define DSTS_SUSPSTS_Msk (0x1UL << DSTS_SUSPSTS_Pos) // 0x00000001 */
-#define DSTS_SUSPSTS DSTS_SUSPSTS_Msk // Suspend status */
+#define DSTS_SUSPSTS_Msk (0x1UL << DSTS_SUSPSTS_Pos) // 0x00000001
+#define DSTS_SUSPSTS DSTS_SUSPSTS_Msk // Suspend status
#define DSTS_ENUMSPD_Pos (1U)
-#define DSTS_ENUMSPD_Msk (0x3UL << DSTS_ENUMSPD_Pos) // 0x00000006 */
-#define DSTS_ENUMSPD DSTS_ENUMSPD_Msk // Enumerated speed */
+#define DSTS_ENUMSPD_Msk (0x3UL << DSTS_ENUMSPD_Pos) // 0x00000006
+#define DSTS_ENUMSPD DSTS_ENUMSPD_Msk // Enumerated speed
#define DSTS_ENUMSPD_HS 0 // Highspeed
#define DSTS_ENUMSPD_FS_HSPHY 1 // Fullspeed on HS PHY
#define DSTS_ENUMSPD_LS 2 // Lowspeed
@@ -498,427 +499,427 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size");
#define DSTS_EERR_Pos (3U)
-#define DSTS_EERR_Msk (0x1UL << DSTS_EERR_Pos) // 0x00000008 */
-#define DSTS_EERR DSTS_EERR_Msk // Erratic error */
+#define DSTS_EERR_Msk (0x1UL << DSTS_EERR_Pos) // 0x00000008
+#define DSTS_EERR DSTS_EERR_Msk // Erratic error
#define DSTS_FNSOF_Pos (8U)
-#define DSTS_FNSOF_Msk (0x3FFFUL << DSTS_FNSOF_Pos) // 0x003FFF00 */
-#define DSTS_FNSOF DSTS_FNSOF_Msk // Frame number of the received SOF */
+#define DSTS_FNSOF_Msk (0x3FFFUL << DSTS_FNSOF_Pos) // 0x003FFF00
+#define DSTS_FNSOF DSTS_FNSOF_Msk // Frame number of the received SOF
/******************** Bit definition for GAHBCFG register ********************/
#define GAHBCFG_GINT_Pos (0U)
-#define GAHBCFG_GINT_Msk (0x1UL << GAHBCFG_GINT_Pos) // 0x00000001 */
-#define GAHBCFG_GINT GAHBCFG_GINT_Msk // Global interrupt mask */
+#define GAHBCFG_GINT_Msk (0x1UL << GAHBCFG_GINT_Pos) // 0x00000001
+#define GAHBCFG_GINT GAHBCFG_GINT_Msk // Global interrupt mask
#define GAHBCFG_HBSTLEN_Pos (1U)
-#define GAHBCFG_HBSTLEN_Msk (0xFUL << GAHBCFG_HBSTLEN_Pos) // 0x0000001E */
-#define GAHBCFG_HBSTLEN GAHBCFG_HBSTLEN_Msk // Burst length/type */
-#define GAHBCFG_HBSTLEN_0 (0x0UL << GAHBCFG_HBSTLEN_Pos) // Single */
-#define GAHBCFG_HBSTLEN_1 (0x1UL << GAHBCFG_HBSTLEN_Pos) // INCR */
-#define GAHBCFG_HBSTLEN_2 (0x3UL << GAHBCFG_HBSTLEN_Pos) // INCR4 */
-#define GAHBCFG_HBSTLEN_3 (0x5UL << GAHBCFG_HBSTLEN_Pos) // INCR8 */
-#define GAHBCFG_HBSTLEN_4 (0x7UL << GAHBCFG_HBSTLEN_Pos) // INCR16 */
+#define GAHBCFG_HBSTLEN_Msk (0xFUL << GAHBCFG_HBSTLEN_Pos) // 0x0000001E
+#define GAHBCFG_HBSTLEN GAHBCFG_HBSTLEN_Msk // Burst length/type
+#define GAHBCFG_HBSTLEN_0 (0x0UL << GAHBCFG_HBSTLEN_Pos) // Single
+#define GAHBCFG_HBSTLEN_1 (0x1UL << GAHBCFG_HBSTLEN_Pos) // INCR
+#define GAHBCFG_HBSTLEN_2 (0x3UL << GAHBCFG_HBSTLEN_Pos) // INCR4
+#define GAHBCFG_HBSTLEN_3 (0x5UL << GAHBCFG_HBSTLEN_Pos) // INCR8
+#define GAHBCFG_HBSTLEN_4 (0x7UL << GAHBCFG_HBSTLEN_Pos) // INCR16
#define GAHBCFG_DMAEN_Pos (5U)
-#define GAHBCFG_DMAEN_Msk (0x1UL << GAHBCFG_DMAEN_Pos) // 0x00000020 */
-#define GAHBCFG_DMAEN GAHBCFG_DMAEN_Msk // DMA enable */
+#define GAHBCFG_DMAEN_Msk (0x1UL << GAHBCFG_DMAEN_Pos) // 0x00000020
+#define GAHBCFG_DMAEN GAHBCFG_DMAEN_Msk // DMA enable
#define GAHBCFG_TXFELVL_Pos (7U)
-#define GAHBCFG_TXFELVL_Msk (0x1UL << GAHBCFG_TXFELVL_Pos) // 0x00000080 */
-#define GAHBCFG_TXFELVL GAHBCFG_TXFELVL_Msk // TxFIFO empty level */
+#define GAHBCFG_TXFELVL_Msk (0x1UL << GAHBCFG_TXFELVL_Pos) // 0x00000080
+#define GAHBCFG_TXFELVL GAHBCFG_TXFELVL_Msk // TxFIFO empty level
#define GAHBCFG_PTXFELVL_Pos (8U)
-#define GAHBCFG_PTXFELVL_Msk (0x1UL << GAHBCFG_PTXFELVL_Pos) // 0x00000100 */
-#define GAHBCFG_PTXFELVL GAHBCFG_PTXFELVL_Msk // Periodic TxFIFO empty level */
+#define GAHBCFG_PTXFELVL_Msk (0x1UL << GAHBCFG_PTXFELVL_Pos) // 0x00000100
+#define GAHBCFG_PTXFELVL GAHBCFG_PTXFELVL_Msk // Periodic TxFIFO empty level
#define GSNPSID_ID_MASK TU_GENMASK(31, 16)
/******************** Bit definition for GUSBCFG register ********************/
#define GUSBCFG_TOCAL_Pos (0U)
-#define GUSBCFG_TOCAL_Msk (0x7UL << GUSBCFG_TOCAL_Pos) // 0x00000007 */
-#define GUSBCFG_TOCAL GUSBCFG_TOCAL_Msk // FS timeout calibration */
+#define GUSBCFG_TOCAL_Msk (0x7UL << GUSBCFG_TOCAL_Pos) // 0x00000007
+#define GUSBCFG_TOCAL GUSBCFG_TOCAL_Msk // FS timeout calibration
#define GUSBCFG_PHYIF16_Pos (3U)
-#define GUSBCFG_PHYIF16_Msk (0x1UL << GUSBCFG_PHYIF16_Pos) // 0x00000008 */
-#define GUSBCFG_PHYIF16 GUSBCFG_PHYIF16_Msk // PHY Interface (PHYIf) */
+#define GUSBCFG_PHYIF16_Msk (0x1UL << GUSBCFG_PHYIF16_Pos) // 0x00000008
+#define GUSBCFG_PHYIF16 GUSBCFG_PHYIF16_Msk // PHY Interface (PHYIf)
#define GUSBCFG_ULPI_UTMI_SEL_Pos (4U)
-#define GUSBCFG_ULPI_UTMI_SEL_Msk (0x1UL << GUSBCFG_ULPI_UTMI_SEL_Pos) // 0x00000010 */
-#define GUSBCFG_ULPI_UTMI_SEL GUSBCFG_ULPI_UTMI_SEL_Msk // ULPI or UTMI+ Select (ULPI_UTMI_Sel) */
+#define GUSBCFG_ULPI_UTMI_SEL_Msk (0x1UL << GUSBCFG_ULPI_UTMI_SEL_Pos) // 0x00000010
+#define GUSBCFG_ULPI_UTMI_SEL GUSBCFG_ULPI_UTMI_SEL_Msk // ULPI or UTMI+ Select (ULPI_UTMI_Sel)
#define GUSBCFG_PHYSEL_Pos (6U)
-#define GUSBCFG_PHYSEL_Msk (0x1UL << GUSBCFG_PHYSEL_Pos) // 0x00000040 */
-#define GUSBCFG_PHYSEL GUSBCFG_PHYSEL_Msk // USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */
+#define GUSBCFG_PHYSEL_Msk (0x1UL << GUSBCFG_PHYSEL_Pos) // 0x00000040
+#define GUSBCFG_PHYSEL GUSBCFG_PHYSEL_Msk // USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select
#define GUSBCFG_DDRSEL TU_BIT(7) // Single Data Rate (SDR) or Double Data Rate (DDR) or ULPI interface.
#define GUSBCFG_SRPCAP_Pos (8U)
-#define GUSBCFG_SRPCAP_Msk (0x1UL << GUSBCFG_SRPCAP_Pos) // 0x00000100 */
-#define GUSBCFG_SRPCAP GUSBCFG_SRPCAP_Msk // SRP-capable */
+#define GUSBCFG_SRPCAP_Msk (0x1UL << GUSBCFG_SRPCAP_Pos) // 0x00000100
+#define GUSBCFG_SRPCAP GUSBCFG_SRPCAP_Msk // SRP-capable
#define GUSBCFG_HNPCAP_Pos (9U)
-#define GUSBCFG_HNPCAP_Msk (0x1UL << GUSBCFG_HNPCAP_Pos) // 0x00000200 */
-#define GUSBCFG_HNPCAP GUSBCFG_HNPCAP_Msk // HNP-capable */
+#define GUSBCFG_HNPCAP_Msk (0x1UL << GUSBCFG_HNPCAP_Pos) // 0x00000200
+#define GUSBCFG_HNPCAP GUSBCFG_HNPCAP_Msk // HNP-capable
#define GUSBCFG_TRDT_Pos (10U)
-#define GUSBCFG_TRDT_Msk (0xFUL << GUSBCFG_TRDT_Pos) // 0x00003C00 */
-#define GUSBCFG_TRDT GUSBCFG_TRDT_Msk // USB turnaround time */
+#define GUSBCFG_TRDT_Msk (0xFUL << GUSBCFG_TRDT_Pos) // 0x00003C00
+#define GUSBCFG_TRDT GUSBCFG_TRDT_Msk // USB turnaround time
#define GUSBCFG_PHYLPCS_Pos (15U)
-#define GUSBCFG_PHYLPCS_Msk (0x1UL << GUSBCFG_PHYLPCS_Pos) // 0x00008000 */
-#define GUSBCFG_PHYLPCS GUSBCFG_PHYLPCS_Msk // PHY Low-power clock select */
+#define GUSBCFG_PHYLPCS_Msk (0x1UL << GUSBCFG_PHYLPCS_Pos) // 0x00008000
+#define GUSBCFG_PHYLPCS GUSBCFG_PHYLPCS_Msk // PHY Low-power clock select
#define GUSBCFG_ULPIFSLS_Pos (17U)
-#define GUSBCFG_ULPIFSLS_Msk (0x1UL << GUSBCFG_ULPIFSLS_Pos) // 0x00020000 */
-#define GUSBCFG_ULPIFSLS GUSBCFG_ULPIFSLS_Msk // ULPI FS/LS select */
+#define GUSBCFG_ULPIFSLS_Msk (0x1UL << GUSBCFG_ULPIFSLS_Pos) // 0x00020000
+#define GUSBCFG_ULPIFSLS GUSBCFG_ULPIFSLS_Msk // ULPI FS/LS select
#define GUSBCFG_ULPIAR_Pos (18U)
-#define GUSBCFG_ULPIAR_Msk (0x1UL << GUSBCFG_ULPIAR_Pos) // 0x00040000 */
-#define GUSBCFG_ULPIAR GUSBCFG_ULPIAR_Msk // ULPI Auto-resume */
+#define GUSBCFG_ULPIAR_Msk (0x1UL << GUSBCFG_ULPIAR_Pos) // 0x00040000
+#define GUSBCFG_ULPIAR GUSBCFG_ULPIAR_Msk // ULPI Auto-resume
#define GUSBCFG_ULPICSM_Pos (19U)
-#define GUSBCFG_ULPICSM_Msk (0x1UL << GUSBCFG_ULPICSM_Pos) // 0x00080000 */
-#define GUSBCFG_ULPICSM GUSBCFG_ULPICSM_Msk // ULPI Clock SuspendM */
+#define GUSBCFG_ULPICSM_Msk (0x1UL << GUSBCFG_ULPICSM_Pos) // 0x00080000
+#define GUSBCFG_ULPICSM GUSBCFG_ULPICSM_Msk // ULPI Clock SuspendM
#define GUSBCFG_ULPIEVBUSD_Pos (20U)
-#define GUSBCFG_ULPIEVBUSD_Msk (0x1UL << GUSBCFG_ULPIEVBUSD_Pos) // 0x00100000 */
-#define GUSBCFG_ULPIEVBUSD GUSBCFG_ULPIEVBUSD_Msk // ULPI External VBUS Drive */
+#define GUSBCFG_ULPIEVBUSD_Msk (0x1UL << GUSBCFG_ULPIEVBUSD_Pos) // 0x00100000
+#define GUSBCFG_ULPIEVBUSD GUSBCFG_ULPIEVBUSD_Msk // ULPI External VBUS Drive
#define GUSBCFG_ULPIEVBUSI_Pos (21U)
-#define GUSBCFG_ULPIEVBUSI_Msk (0x1UL << GUSBCFG_ULPIEVBUSI_Pos) // 0x00200000 */
-#define GUSBCFG_ULPIEVBUSI GUSBCFG_ULPIEVBUSI_Msk // ULPI external VBUS indicator */
+#define GUSBCFG_ULPIEVBUSI_Msk (0x1UL << GUSBCFG_ULPIEVBUSI_Pos) // 0x00200000
+#define GUSBCFG_ULPIEVBUSI GUSBCFG_ULPIEVBUSI_Msk // ULPI external VBUS indicator
#define GUSBCFG_TSDPS_Pos (22U)
-#define GUSBCFG_TSDPS_Msk (0x1UL << GUSBCFG_TSDPS_Pos) // 0x00400000 */
-#define GUSBCFG_TSDPS GUSBCFG_TSDPS_Msk // TermSel DLine pulsing selection */
+#define GUSBCFG_TSDPS_Msk (0x1UL << GUSBCFG_TSDPS_Pos) // 0x00400000
+#define GUSBCFG_TSDPS GUSBCFG_TSDPS_Msk // TermSel DLine pulsing selection
#define GUSBCFG_PCCI_Pos (23U)
-#define GUSBCFG_PCCI_Msk (0x1UL << GUSBCFG_PCCI_Pos) // 0x00800000 */
-#define GUSBCFG_PCCI GUSBCFG_PCCI_Msk // Indicator complement */
+#define GUSBCFG_PCCI_Msk (0x1UL << GUSBCFG_PCCI_Pos) // 0x00800000
+#define GUSBCFG_PCCI GUSBCFG_PCCI_Msk // Indicator complement
#define GUSBCFG_PTCI_Pos (24U)
-#define GUSBCFG_PTCI_Msk (0x1UL << GUSBCFG_PTCI_Pos) // 0x01000000 */
-#define GUSBCFG_PTCI GUSBCFG_PTCI_Msk // Indicator pass through */
+#define GUSBCFG_PTCI_Msk (0x1UL << GUSBCFG_PTCI_Pos) // 0x01000000
+#define GUSBCFG_PTCI GUSBCFG_PTCI_Msk // Indicator pass through
#define GUSBCFG_ULPIIPD_Pos (25U)
-#define GUSBCFG_ULPIIPD_Msk (0x1UL << GUSBCFG_ULPIIPD_Pos) // 0x02000000 */
-#define GUSBCFG_ULPIIPD GUSBCFG_ULPIIPD_Msk // ULPI interface protect disable */
+#define GUSBCFG_ULPIIPD_Msk (0x1UL << GUSBCFG_ULPIIPD_Pos) // 0x02000000
+#define GUSBCFG_ULPIIPD GUSBCFG_ULPIIPD_Msk // ULPI interface protect disable
#define GUSBCFG_FHMOD_Pos (29U)
-#define GUSBCFG_FHMOD_Msk (0x1UL << GUSBCFG_FHMOD_Pos) // 0x20000000 */
-#define GUSBCFG_FHMOD GUSBCFG_FHMOD_Msk // Forced host mode */
+#define GUSBCFG_FHMOD_Msk (0x1UL << GUSBCFG_FHMOD_Pos) // 0x20000000
+#define GUSBCFG_FHMOD GUSBCFG_FHMOD_Msk // Forced host mode
#define GUSBCFG_FDMOD_Pos (30U)
-#define GUSBCFG_FDMOD_Msk (0x1UL << GUSBCFG_FDMOD_Pos) // 0x40000000 */
-#define GUSBCFG_FDMOD GUSBCFG_FDMOD_Msk // Forced peripheral mode */
+#define GUSBCFG_FDMOD_Msk (0x1UL << GUSBCFG_FDMOD_Pos) // 0x40000000
+#define GUSBCFG_FDMOD GUSBCFG_FDMOD_Msk // Forced peripheral mode
#define GUSBCFG_CTXPKT_Pos (31U)
-#define GUSBCFG_CTXPKT_Msk (0x1UL << GUSBCFG_CTXPKT_Pos) // 0x80000000 */
-#define GUSBCFG_CTXPKT GUSBCFG_CTXPKT_Msk // Corrupt Tx packet */
+#define GUSBCFG_CTXPKT_Msk (0x1UL << GUSBCFG_CTXPKT_Pos) // 0x80000000
+#define GUSBCFG_CTXPKT GUSBCFG_CTXPKT_Msk // Corrupt Tx packet
/******************** Bit definition for GRSTCTL register ********************/
#define GRSTCTL_CSRST_Pos (0U)
-#define GRSTCTL_CSRST_Msk (0x1UL << GRSTCTL_CSRST_Pos) // 0x00000001 */
-#define GRSTCTL_CSRST GRSTCTL_CSRST_Msk // Core soft reset */
+#define GRSTCTL_CSRST_Msk (0x1UL << GRSTCTL_CSRST_Pos) // 0x00000001
+#define GRSTCTL_CSRST GRSTCTL_CSRST_Msk // Core soft reset
#define GRSTCTL_HSRST_Pos (1U)
-#define GRSTCTL_HSRST_Msk (0x1UL << GRSTCTL_HSRST_Pos) // 0x00000002 */
-#define GRSTCTL_HSRST GRSTCTL_HSRST_Msk // HCLK soft reset */
+#define GRSTCTL_HSRST_Msk (0x1UL << GRSTCTL_HSRST_Pos) // 0x00000002
+#define GRSTCTL_HSRST GRSTCTL_HSRST_Msk // HCLK soft reset
#define GRSTCTL_FCRST_Pos (2U)
-#define GRSTCTL_FCRST_Msk (0x1UL << GRSTCTL_FCRST_Pos) // 0x00000004 */
-#define GRSTCTL_FCRST GRSTCTL_FCRST_Msk // Host frame counter reset */
+#define GRSTCTL_FCRST_Msk (0x1UL << GRSTCTL_FCRST_Pos) // 0x00000004
+#define GRSTCTL_FCRST GRSTCTL_FCRST_Msk // Host frame counter reset
#define GRSTCTL_RXFFLSH_Pos (4U)
-#define GRSTCTL_RXFFLSH_Msk (0x1UL << GRSTCTL_RXFFLSH_Pos) // 0x00000010 */
-#define GRSTCTL_RXFFLSH GRSTCTL_RXFFLSH_Msk // RxFIFO flush */
+#define GRSTCTL_RXFFLSH_Msk (0x1UL << GRSTCTL_RXFFLSH_Pos) // 0x00000010
+#define GRSTCTL_RXFFLSH GRSTCTL_RXFFLSH_Msk // RxFIFO flush
#define GRSTCTL_TXFFLSH_Pos (5U)
-#define GRSTCTL_TXFFLSH_Msk (0x1UL << GRSTCTL_TXFFLSH_Pos) // 0x00000020 */
-#define GRSTCTL_TXFFLSH GRSTCTL_TXFFLSH_Msk // TxFIFO flush */
+#define GRSTCTL_TXFFLSH_Msk (0x1UL << GRSTCTL_TXFFLSH_Pos) // 0x00000020
+#define GRSTCTL_TXFFLSH GRSTCTL_TXFFLSH_Msk // TxFIFO flush
#define GRSTCTL_TXFNUM_Pos (6U)
-#define GRSTCTL_TXFNUM_Msk (0x1FUL << GRSTCTL_TXFNUM_Pos) // 0x000007C0 */
-#define GRSTCTL_TXFNUM GRSTCTL_TXFNUM_Msk // TxFIFO number */
-#define GRSTCTL_TXFNUM_0 (0x01UL << GRSTCTL_TXFNUM_Pos) // 0x00000040 */
-#define GRSTCTL_TXFNUM_1 (0x02UL << GRSTCTL_TXFNUM_Pos) // 0x00000080 */
-#define GRSTCTL_TXFNUM_2 (0x04UL << GRSTCTL_TXFNUM_Pos) // 0x00000100 */
-#define GRSTCTL_TXFNUM_3 (0x08UL << GRSTCTL_TXFNUM_Pos) // 0x00000200 */
-#define GRSTCTL_TXFNUM_4 (0x10UL << GRSTCTL_TXFNUM_Pos) // 0x00000400 */
+#define GRSTCTL_TXFNUM_Msk (0x1FUL << GRSTCTL_TXFNUM_Pos) // 0x000007C0
+#define GRSTCTL_TXFNUM GRSTCTL_TXFNUM_Msk // TxFIFO number
+#define GRSTCTL_TXFNUM_0 (0x01UL << GRSTCTL_TXFNUM_Pos) // 0x00000040
+#define GRSTCTL_TXFNUM_1 (0x02UL << GRSTCTL_TXFNUM_Pos) // 0x00000080
+#define GRSTCTL_TXFNUM_2 (0x04UL << GRSTCTL_TXFNUM_Pos) // 0x00000100
+#define GRSTCTL_TXFNUM_3 (0x08UL << GRSTCTL_TXFNUM_Pos) // 0x00000200
+#define GRSTCTL_TXFNUM_4 (0x10UL << GRSTCTL_TXFNUM_Pos) // 0x00000400
#define GRSTCTL_CSFTRST_DONE_Pos (29)
#define GRSTCTL_CSFTRST_DONE (1u << GRSTCTL_CSFTRST_DONE_Pos) // Reset Done, only available from v4.20a
#define GRSTCTL_DMAREQ_Pos (30U)
-#define GRSTCTL_DMAREQ_Msk (0x1UL << GRSTCTL_DMAREQ_Pos) // 0x40000000 */
-#define GRSTCTL_DMAREQ GRSTCTL_DMAREQ_Msk // DMA request signal */
+#define GRSTCTL_DMAREQ_Msk (0x1UL << GRSTCTL_DMAREQ_Pos) // 0x40000000
+#define GRSTCTL_DMAREQ GRSTCTL_DMAREQ_Msk // DMA request signal
#define GRSTCTL_AHBIDL_Pos (31U)
-#define GRSTCTL_AHBIDL_Msk (0x1UL << GRSTCTL_AHBIDL_Pos) // 0x80000000 */
-#define GRSTCTL_AHBIDL GRSTCTL_AHBIDL_Msk // AHB master idle */
+#define GRSTCTL_AHBIDL_Msk (0x1UL << GRSTCTL_AHBIDL_Pos) // 0x80000000
+#define GRSTCTL_AHBIDL GRSTCTL_AHBIDL_Msk // AHB master idle
/******************** Bit definition for DIEPMSK register ********************/
#define DIEPMSK_XFRCM_Pos (0U)
-#define DIEPMSK_XFRCM_Msk (0x1UL << DIEPMSK_XFRCM_Pos) // 0x00000001 */
-#define DIEPMSK_XFRCM DIEPMSK_XFRCM_Msk // Transfer completed interrupt mask */
+#define DIEPMSK_XFRCM_Msk (0x1UL << DIEPMSK_XFRCM_Pos) // 0x00000001
+#define DIEPMSK_XFRCM DIEPMSK_XFRCM_Msk // Transfer completed interrupt mask
#define DIEPMSK_EPDM_Pos (1U)
-#define DIEPMSK_EPDM_Msk (0x1UL << DIEPMSK_EPDM_Pos) // 0x00000002 */
-#define DIEPMSK_EPDM DIEPMSK_EPDM_Msk // Endpoint disabled interrupt mask */
+#define DIEPMSK_EPDM_Msk (0x1UL << DIEPMSK_EPDM_Pos) // 0x00000002
+#define DIEPMSK_EPDM DIEPMSK_EPDM_Msk // Endpoint disabled interrupt mask
#define DIEPMSK_TOM_Pos (3U)
-#define DIEPMSK_TOM_Msk (0x1UL << DIEPMSK_TOM_Pos) // 0x00000008 */
-#define DIEPMSK_TOM DIEPMSK_TOM_Msk // Timeout condition mask (nonisochronous endpoints) */
+#define DIEPMSK_TOM_Msk (0x1UL << DIEPMSK_TOM_Pos) // 0x00000008
+#define DIEPMSK_TOM DIEPMSK_TOM_Msk // Timeout condition mask (nonisochronous endpoints)
#define DIEPMSK_ITTXFEMSK_Pos (4U)
-#define DIEPMSK_ITTXFEMSK_Msk (0x1UL << DIEPMSK_ITTXFEMSK_Pos) // 0x00000010 */
-#define DIEPMSK_ITTXFEMSK DIEPMSK_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */
+#define DIEPMSK_ITTXFEMSK_Msk (0x1UL << DIEPMSK_ITTXFEMSK_Pos) // 0x00000010
+#define DIEPMSK_ITTXFEMSK DIEPMSK_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask
#define DIEPMSK_INEPNMM_Pos (5U)
-#define DIEPMSK_INEPNMM_Msk (0x1UL << DIEPMSK_INEPNMM_Pos) // 0x00000020 */
-#define DIEPMSK_INEPNMM DIEPMSK_INEPNMM_Msk // IN token received with EP mismatch mask */
+#define DIEPMSK_INEPNMM_Msk (0x1UL << DIEPMSK_INEPNMM_Pos) // 0x00000020
+#define DIEPMSK_INEPNMM DIEPMSK_INEPNMM_Msk // IN token received with EP mismatch mask
#define DIEPMSK_INEPNEM_Pos (6U)
-#define DIEPMSK_INEPNEM_Msk (0x1UL << DIEPMSK_INEPNEM_Pos) // 0x00000040 */
-#define DIEPMSK_INEPNEM DIEPMSK_INEPNEM_Msk // IN endpoint NAK effective mask */
+#define DIEPMSK_INEPNEM_Msk (0x1UL << DIEPMSK_INEPNEM_Pos) // 0x00000040
+#define DIEPMSK_INEPNEM DIEPMSK_INEPNEM_Msk // IN endpoint NAK effective mask
#define DIEPMSK_TXFURM_Pos (8U)
-#define DIEPMSK_TXFURM_Msk (0x1UL << DIEPMSK_TXFURM_Pos) // 0x00000100 */
-#define DIEPMSK_TXFURM DIEPMSK_TXFURM_Msk // FIFO underrun mask */
+#define DIEPMSK_TXFURM_Msk (0x1UL << DIEPMSK_TXFURM_Pos) // 0x00000100
+#define DIEPMSK_TXFURM DIEPMSK_TXFURM_Msk // FIFO underrun mask
#define DIEPMSK_BIM_Pos (9U)
-#define DIEPMSK_BIM_Msk (0x1UL << DIEPMSK_BIM_Pos) // 0x00000200 */
-#define DIEPMSK_BIM DIEPMSK_BIM_Msk // BNA interrupt mask */
+#define DIEPMSK_BIM_Msk (0x1UL << DIEPMSK_BIM_Pos) // 0x00000200
+#define DIEPMSK_BIM DIEPMSK_BIM_Msk // BNA interrupt mask
/******************** Bit definition for HPTXSTS register ********************/
#define HPTXSTS_PTXFSAVL_Pos (0U)
-#define HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << HPTXSTS_PTXFSAVL_Pos) // 0x0000FFFF */
-#define HPTXSTS_PTXFSAVL HPTXSTS_PTXFSAVL_Msk // Periodic transmit data FIFO space available */
+#define HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << HPTXSTS_PTXFSAVL_Pos) // 0x0000FFFF
+#define HPTXSTS_PTXFSAVL HPTXSTS_PTXFSAVL_Msk // Periodic transmit data FIFO space available
#define HPTXSTS_PTXQSAV_Pos (16U)
-#define HPTXSTS_PTXQSAV_Msk (0xFFUL << HPTXSTS_PTXQSAV_Pos) // 0x00FF0000 */
-#define HPTXSTS_PTXQSAV HPTXSTS_PTXQSAV_Msk // Periodic transmit request queue space available */
-#define HPTXSTS_PTXQSAV_0 (0x01UL << HPTXSTS_PTXQSAV_Pos) // 0x00010000 */
-#define HPTXSTS_PTXQSAV_1 (0x02UL << HPTXSTS_PTXQSAV_Pos) // 0x00020000 */
-#define HPTXSTS_PTXQSAV_2 (0x04UL << HPTXSTS_PTXQSAV_Pos) // 0x00040000 */
-#define HPTXSTS_PTXQSAV_3 (0x08UL << HPTXSTS_PTXQSAV_Pos) // 0x00080000 */
-#define HPTXSTS_PTXQSAV_4 (0x10UL << HPTXSTS_PTXQSAV_Pos) // 0x00100000 */
-#define HPTXSTS_PTXQSAV_5 (0x20UL << HPTXSTS_PTXQSAV_Pos) // 0x00200000 */
-#define HPTXSTS_PTXQSAV_6 (0x40UL << HPTXSTS_PTXQSAV_Pos) // 0x00400000 */
-#define HPTXSTS_PTXQSAV_7 (0x80UL << HPTXSTS_PTXQSAV_Pos) // 0x00800000 */
+#define HPTXSTS_PTXQSAV_Msk (0xFFUL << HPTXSTS_PTXQSAV_Pos) // 0x00FF0000
+#define HPTXSTS_PTXQSAV HPTXSTS_PTXQSAV_Msk // Periodic transmit request queue space available
+#define HPTXSTS_PTXQSAV_0 (0x01UL << HPTXSTS_PTXQSAV_Pos) // 0x00010000
+#define HPTXSTS_PTXQSAV_1 (0x02UL << HPTXSTS_PTXQSAV_Pos) // 0x00020000
+#define HPTXSTS_PTXQSAV_2 (0x04UL << HPTXSTS_PTXQSAV_Pos) // 0x00040000
+#define HPTXSTS_PTXQSAV_3 (0x08UL << HPTXSTS_PTXQSAV_Pos) // 0x00080000
+#define HPTXSTS_PTXQSAV_4 (0x10UL << HPTXSTS_PTXQSAV_Pos) // 0x00100000
+#define HPTXSTS_PTXQSAV_5 (0x20UL << HPTXSTS_PTXQSAV_Pos) // 0x00200000
+#define HPTXSTS_PTXQSAV_6 (0x40UL << HPTXSTS_PTXQSAV_Pos) // 0x00400000
+#define HPTXSTS_PTXQSAV_7 (0x80UL << HPTXSTS_PTXQSAV_Pos) // 0x00800000
#define HPTXSTS_PTXQTOP_Pos (24U)
-#define HPTXSTS_PTXQTOP_Msk (0xFFUL << HPTXSTS_PTXQTOP_Pos) // 0xFF000000 */
-#define HPTXSTS_PTXQTOP HPTXSTS_PTXQTOP_Msk // Top of the periodic transmit request queue */
-#define HPTXSTS_PTXQTOP_0 (0x01UL << HPTXSTS_PTXQTOP_Pos) // 0x01000000 */
-#define HPTXSTS_PTXQTOP_1 (0x02UL << HPTXSTS_PTXQTOP_Pos) // 0x02000000 */
-#define HPTXSTS_PTXQTOP_2 (0x04UL << HPTXSTS_PTXQTOP_Pos) // 0x04000000 */
-#define HPTXSTS_PTXQTOP_3 (0x08UL << HPTXSTS_PTXQTOP_Pos) // 0x08000000 */
-#define HPTXSTS_PTXQTOP_4 (0x10UL << HPTXSTS_PTXQTOP_Pos) // 0x10000000 */
-#define HPTXSTS_PTXQTOP_5 (0x20UL << HPTXSTS_PTXQTOP_Pos) // 0x20000000 */
-#define HPTXSTS_PTXQTOP_6 (0x40UL << HPTXSTS_PTXQTOP_Pos) // 0x40000000 */
-#define HPTXSTS_PTXQTOP_7 (0x80UL << HPTXSTS_PTXQTOP_Pos) // 0x80000000 */
+#define HPTXSTS_PTXQTOP_Msk (0xFFUL << HPTXSTS_PTXQTOP_Pos) // 0xFF000000
+#define HPTXSTS_PTXQTOP HPTXSTS_PTXQTOP_Msk // Top of the periodic transmit request queue
+#define HPTXSTS_PTXQTOP_0 (0x01UL << HPTXSTS_PTXQTOP_Pos) // 0x01000000
+#define HPTXSTS_PTXQTOP_1 (0x02UL << HPTXSTS_PTXQTOP_Pos) // 0x02000000
+#define HPTXSTS_PTXQTOP_2 (0x04UL << HPTXSTS_PTXQTOP_Pos) // 0x04000000
+#define HPTXSTS_PTXQTOP_3 (0x08UL << HPTXSTS_PTXQTOP_Pos) // 0x08000000
+#define HPTXSTS_PTXQTOP_4 (0x10UL << HPTXSTS_PTXQTOP_Pos) // 0x10000000
+#define HPTXSTS_PTXQTOP_5 (0x20UL << HPTXSTS_PTXQTOP_Pos) // 0x20000000
+#define HPTXSTS_PTXQTOP_6 (0x40UL << HPTXSTS_PTXQTOP_Pos) // 0x40000000
+#define HPTXSTS_PTXQTOP_7 (0x80UL << HPTXSTS_PTXQTOP_Pos) // 0x80000000
/******************** Bit definition for HAINT register ********************/
#define HAINT_HAINT_Pos (0U)
-#define HAINT_HAINT_Msk (0xFFFFUL << HAINT_HAINT_Pos) // 0x0000FFFF */
-#define HAINT_HAINT HAINT_HAINT_Msk // Channel interrupts */
+#define HAINT_HAINT_Msk (0xFFFFUL << HAINT_HAINT_Pos) // 0x0000FFFF
+#define HAINT_HAINT HAINT_HAINT_Msk // Channel interrupts
/******************** Bit definition for DOEPMSK register ********************/
#define DOEPMSK_XFRCM_Pos (0U)
-#define DOEPMSK_XFRCM_Msk (0x1UL << DOEPMSK_XFRCM_Pos) // 0x00000001 */
-#define DOEPMSK_XFRCM DOEPMSK_XFRCM_Msk // Transfer completed interrupt mask */
+#define DOEPMSK_XFRCM_Msk (0x1UL << DOEPMSK_XFRCM_Pos) // 0x00000001
+#define DOEPMSK_XFRCM DOEPMSK_XFRCM_Msk // Transfer completed interrupt mask
#define DOEPMSK_EPDM_Pos (1U)
-#define DOEPMSK_EPDM_Msk (0x1UL << DOEPMSK_EPDM_Pos) // 0x00000002 */
-#define DOEPMSK_EPDM DOEPMSK_EPDM_Msk // Endpoint disabled interrupt mask */
+#define DOEPMSK_EPDM_Msk (0x1UL << DOEPMSK_EPDM_Pos) // 0x00000002
+#define DOEPMSK_EPDM DOEPMSK_EPDM_Msk // Endpoint disabled interrupt mask
#define DOEPMSK_AHBERRM_Pos (2U)
-#define DOEPMSK_AHBERRM_Msk (0x1UL << DOEPMSK_AHBERRM_Pos) // 0x00000004 */
-#define DOEPMSK_AHBERRM DOEPMSK_AHBERRM_Msk // OUT transaction AHB Error interrupt mask */
+#define DOEPMSK_AHBERRM_Msk (0x1UL << DOEPMSK_AHBERRM_Pos) // 0x00000004
+#define DOEPMSK_AHBERRM DOEPMSK_AHBERRM_Msk // OUT transaction AHB Error interrupt mask
#define DOEPMSK_STUPM_Pos (3U)
-#define DOEPMSK_STUPM_Msk (0x1UL << DOEPMSK_STUPM_Pos) // 0x00000008 */
-#define DOEPMSK_STUPM DOEPMSK_STUPM_Msk // SETUP phase done mask */
+#define DOEPMSK_STUPM_Msk (0x1UL << DOEPMSK_STUPM_Pos) // 0x00000008
+#define DOEPMSK_STUPM DOEPMSK_STUPM_Msk // SETUP phase done mask
#define DOEPMSK_OTEPDM_Pos (4U)
-#define DOEPMSK_OTEPDM_Msk (0x1UL << DOEPMSK_OTEPDM_Pos) // 0x00000010 */
-#define DOEPMSK_OTEPDM DOEPMSK_OTEPDM_Msk // OUT token received when endpoint disabled mask */
+#define DOEPMSK_OTEPDM_Msk (0x1UL << DOEPMSK_OTEPDM_Pos) // 0x00000010
+#define DOEPMSK_OTEPDM DOEPMSK_OTEPDM_Msk // OUT token received when endpoint disabled mask
#define DOEPMSK_OTEPSPRM_Pos (5U)
-#define DOEPMSK_OTEPSPRM_Msk (0x1UL << DOEPMSK_OTEPSPRM_Pos) // 0x00000020 */
-#define DOEPMSK_OTEPSPRM DOEPMSK_OTEPSPRM_Msk // Status Phase Received mask */
+#define DOEPMSK_OTEPSPRM_Msk (0x1UL << DOEPMSK_OTEPSPRM_Pos) // 0x00000020
+#define DOEPMSK_OTEPSPRM DOEPMSK_OTEPSPRM_Msk // Status Phase Received mask
#define DOEPMSK_B2BSTUP_Pos (6U)
-#define DOEPMSK_B2BSTUP_Msk (0x1UL << DOEPMSK_B2BSTUP_Pos) // 0x00000040 */
-#define DOEPMSK_B2BSTUP DOEPMSK_B2BSTUP_Msk // Back-to-back SETUP packets received mask */
+#define DOEPMSK_B2BSTUP_Msk (0x1UL << DOEPMSK_B2BSTUP_Pos) // 0x00000040
+#define DOEPMSK_B2BSTUP DOEPMSK_B2BSTUP_Msk // Back-to-back SETUP packets received mask
#define DOEPMSK_OPEM_Pos (8U)
-#define DOEPMSK_OPEM_Msk (0x1UL << DOEPMSK_OPEM_Pos) // 0x00000100 */
-#define DOEPMSK_OPEM DOEPMSK_OPEM_Msk // OUT packet error mask */
+#define DOEPMSK_OPEM_Msk (0x1UL << DOEPMSK_OPEM_Pos) // 0x00000100
+#define DOEPMSK_OPEM DOEPMSK_OPEM_Msk // OUT packet error mask
#define DOEPMSK_BOIM_Pos (9U)
-#define DOEPMSK_BOIM_Msk (0x1UL << DOEPMSK_BOIM_Pos) // 0x00000200 */
-#define DOEPMSK_BOIM DOEPMSK_BOIM_Msk // BNA interrupt mask */
+#define DOEPMSK_BOIM_Msk (0x1UL << DOEPMSK_BOIM_Pos) // 0x00000200
+#define DOEPMSK_BOIM DOEPMSK_BOIM_Msk // BNA interrupt mask
#define DOEPMSK_BERRM_Pos (12U)
-#define DOEPMSK_BERRM_Msk (0x1UL << DOEPMSK_BERRM_Pos) // 0x00001000 */
-#define DOEPMSK_BERRM DOEPMSK_BERRM_Msk // Babble error interrupt mask */
+#define DOEPMSK_BERRM_Msk (0x1UL << DOEPMSK_BERRM_Pos) // 0x00001000
+#define DOEPMSK_BERRM DOEPMSK_BERRM_Msk // Babble error interrupt mask
#define DOEPMSK_NAKM_Pos (13U)
-#define DOEPMSK_NAKM_Msk (0x1UL << DOEPMSK_NAKM_Pos) // 0x00002000 */
-#define DOEPMSK_NAKM DOEPMSK_NAKM_Msk // OUT Packet NAK interrupt mask */
+#define DOEPMSK_NAKM_Msk (0x1UL << DOEPMSK_NAKM_Pos) // 0x00002000
+#define DOEPMSK_NAKM DOEPMSK_NAKM_Msk // OUT Packet NAK interrupt mask
#define DOEPMSK_NYETM_Pos (14U)
-#define DOEPMSK_NYETM_Msk (0x1UL << DOEPMSK_NYETM_Pos) // 0x00004000 */
-#define DOEPMSK_NYETM DOEPMSK_NYETM_Msk // NYET interrupt mask */
+#define DOEPMSK_NYETM_Msk (0x1UL << DOEPMSK_NYETM_Pos) // 0x00004000
+#define DOEPMSK_NYETM DOEPMSK_NYETM_Msk // NYET interrupt mask
/******************** Bit definition for GINTSTS register ********************/
#define GINTSTS_CMOD_Pos (0U)
-#define GINTSTS_CMOD_Msk (0x1UL << GINTSTS_CMOD_Pos) // 0x00000001 */
-#define GINTSTS_CMOD GINTSTS_CMOD_Msk // Current mode of operation */
+#define GINTSTS_CMOD_Msk (0x1UL << GINTSTS_CMOD_Pos) // 0x00000001
+#define GINTSTS_CMOD GINTSTS_CMOD_Msk // Current mode of operation
#define GINTSTS_MMIS_Pos (1U)
-#define GINTSTS_MMIS_Msk (0x1UL << GINTSTS_MMIS_Pos) // 0x00000002 */
-#define GINTSTS_MMIS GINTSTS_MMIS_Msk // Mode mismatch interrupt */
+#define GINTSTS_MMIS_Msk (0x1UL << GINTSTS_MMIS_Pos) // 0x00000002
+#define GINTSTS_MMIS GINTSTS_MMIS_Msk // Mode mismatch interrupt
#define GINTSTS_OTGINT_Pos (2U)
-#define GINTSTS_OTGINT_Msk (0x1UL << GINTSTS_OTGINT_Pos) // 0x00000004 */
-#define GINTSTS_OTGINT GINTSTS_OTGINT_Msk // OTG interrupt */
+#define GINTSTS_OTGINT_Msk (0x1UL << GINTSTS_OTGINT_Pos) // 0x00000004
+#define GINTSTS_OTGINT GINTSTS_OTGINT_Msk // OTG interrupt
#define GINTSTS_SOF_Pos (3U)
-#define GINTSTS_SOF_Msk (0x1UL << GINTSTS_SOF_Pos) // 0x00000008 */
-#define GINTSTS_SOF GINTSTS_SOF_Msk // Start of frame */
+#define GINTSTS_SOF_Msk (0x1UL << GINTSTS_SOF_Pos) // 0x00000008
+#define GINTSTS_SOF GINTSTS_SOF_Msk // Start of frame
#define GINTSTS_RXFLVL_Pos (4U)
-#define GINTSTS_RXFLVL_Msk (0x1UL << GINTSTS_RXFLVL_Pos) // 0x00000010 */
-#define GINTSTS_RXFLVL GINTSTS_RXFLVL_Msk // RxFIFO nonempty */
+#define GINTSTS_RXFLVL_Msk (0x1UL << GINTSTS_RXFLVL_Pos) // 0x00000010
+#define GINTSTS_RXFLVL GINTSTS_RXFLVL_Msk // RxFIFO nonempty
#define GINTSTS_NPTXFE_Pos (5U)
-#define GINTSTS_NPTXFE_Msk (0x1UL << GINTSTS_NPTXFE_Pos) // 0x00000020 */
-#define GINTSTS_NPTXFE GINTSTS_NPTXFE_Msk // Nonperiodic TxFIFO empty */
+#define GINTSTS_NPTXFE_Msk (0x1UL << GINTSTS_NPTXFE_Pos) // 0x00000020
+#define GINTSTS_NPTXFE GINTSTS_NPTXFE_Msk // Nonperiodic TxFIFO empty
#define GINTSTS_GINAKEFF_Pos (6U)
-#define GINTSTS_GINAKEFF_Msk (0x1UL << GINTSTS_GINAKEFF_Pos) // 0x00000040 */
-#define GINTSTS_GINAKEFF GINTSTS_GINAKEFF_Msk // Global IN nonperiodic NAK effective */
+#define GINTSTS_GINAKEFF_Msk (0x1UL << GINTSTS_GINAKEFF_Pos) // 0x00000040
+#define GINTSTS_GINAKEFF GINTSTS_GINAKEFF_Msk // Global IN nonperiodic NAK effective
#define GINTSTS_BOUTNAKEFF_Pos (7U)
-#define GINTSTS_BOUTNAKEFF_Msk (0x1UL << GINTSTS_BOUTNAKEFF_Pos) // 0x00000080 */
-#define GINTSTS_BOUTNAKEFF GINTSTS_BOUTNAKEFF_Msk // Global OUT NAK effective */
+#define GINTSTS_BOUTNAKEFF_Msk (0x1UL << GINTSTS_BOUTNAKEFF_Pos) // 0x00000080
+#define GINTSTS_BOUTNAKEFF GINTSTS_BOUTNAKEFF_Msk // Global OUT NAK effective
#define GINTSTS_ESUSP_Pos (10U)
-#define GINTSTS_ESUSP_Msk (0x1UL << GINTSTS_ESUSP_Pos) // 0x00000400 */
-#define GINTSTS_ESUSP GINTSTS_ESUSP_Msk // Early suspend */
+#define GINTSTS_ESUSP_Msk (0x1UL << GINTSTS_ESUSP_Pos) // 0x00000400
+#define GINTSTS_ESUSP GINTSTS_ESUSP_Msk // Early suspend
#define GINTSTS_USBSUSP_Pos (11U)
-#define GINTSTS_USBSUSP_Msk (0x1UL << GINTSTS_USBSUSP_Pos) // 0x00000800 */
-#define GINTSTS_USBSUSP GINTSTS_USBSUSP_Msk // USB suspend */
+#define GINTSTS_USBSUSP_Msk (0x1UL << GINTSTS_USBSUSP_Pos) // 0x00000800
+#define GINTSTS_USBSUSP GINTSTS_USBSUSP_Msk // USB suspend
#define GINTSTS_USBRST_Pos (12U)
-#define GINTSTS_USBRST_Msk (0x1UL << GINTSTS_USBRST_Pos) // 0x00001000 */
-#define GINTSTS_USBRST GINTSTS_USBRST_Msk // USB reset */
+#define GINTSTS_USBRST_Msk (0x1UL << GINTSTS_USBRST_Pos) // 0x00001000
+#define GINTSTS_USBRST GINTSTS_USBRST_Msk // USB reset
#define GINTSTS_ENUMDNE_Pos (13U)
-#define GINTSTS_ENUMDNE_Msk (0x1UL << GINTSTS_ENUMDNE_Pos) // 0x00002000 */
-#define GINTSTS_ENUMDNE GINTSTS_ENUMDNE_Msk // Enumeration done */
+#define GINTSTS_ENUMDNE_Msk (0x1UL << GINTSTS_ENUMDNE_Pos) // 0x00002000
+#define GINTSTS_ENUMDNE GINTSTS_ENUMDNE_Msk // Enumeration done
#define GINTSTS_ISOODRP_Pos (14U)
-#define GINTSTS_ISOODRP_Msk (0x1UL << GINTSTS_ISOODRP_Pos) // 0x00004000 */
-#define GINTSTS_ISOODRP GINTSTS_ISOODRP_Msk // Isochronous OUT packet dropped interrupt */
+#define GINTSTS_ISOODRP_Msk (0x1UL << GINTSTS_ISOODRP_Pos) // 0x00004000
+#define GINTSTS_ISOODRP GINTSTS_ISOODRP_Msk // Isochronous OUT packet dropped interrupt
#define GINTSTS_EOPF_Pos (15U)
-#define GINTSTS_EOPF_Msk (0x1UL << GINTSTS_EOPF_Pos) // 0x00008000 */
-#define GINTSTS_EOPF GINTSTS_EOPF_Msk // End of periodic frame interrupt */
+#define GINTSTS_EOPF_Msk (0x1UL << GINTSTS_EOPF_Pos) // 0x00008000
+#define GINTSTS_EOPF GINTSTS_EOPF_Msk // End of periodic frame interrupt
#define GINTSTS_IEPINT_Pos (18U)
-#define GINTSTS_IEPINT_Msk (0x1UL << GINTSTS_IEPINT_Pos) // 0x00040000 */
-#define GINTSTS_IEPINT GINTSTS_IEPINT_Msk // IN endpoint interrupt */
+#define GINTSTS_IEPINT_Msk (0x1UL << GINTSTS_IEPINT_Pos) // 0x00040000
+#define GINTSTS_IEPINT GINTSTS_IEPINT_Msk // IN endpoint interrupt
#define GINTSTS_OEPINT_Pos (19U)
-#define GINTSTS_OEPINT_Msk (0x1UL << GINTSTS_OEPINT_Pos) // 0x00080000 */
-#define GINTSTS_OEPINT GINTSTS_OEPINT_Msk // OUT endpoint interrupt */
+#define GINTSTS_OEPINT_Msk (0x1UL << GINTSTS_OEPINT_Pos) // 0x00080000
+#define GINTSTS_OEPINT GINTSTS_OEPINT_Msk // OUT endpoint interrupt
#define GINTSTS_IISOIXFR_Pos (20U)
-#define GINTSTS_IISOIXFR_Msk (0x1UL << GINTSTS_IISOIXFR_Pos) // 0x00100000 */
-#define GINTSTS_IISOIXFR GINTSTS_IISOIXFR_Msk // Incomplete isochronous IN transfer */
+#define GINTSTS_IISOIXFR_Msk (0x1UL << GINTSTS_IISOIXFR_Pos) // 0x00100000
+#define GINTSTS_IISOIXFR GINTSTS_IISOIXFR_Msk // Incomplete isochronous IN transfer
#define GINTSTS_PXFR_INCOMPISOOUT_Pos (21U)
-#define GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << GINTSTS_PXFR_INCOMPISOOUT_Pos) // 0x00200000 */
-#define GINTSTS_PXFR_INCOMPISOOUT GINTSTS_PXFR_INCOMPISOOUT_Msk // Incomplete periodic transfer */
+#define GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << GINTSTS_PXFR_INCOMPISOOUT_Pos) // 0x00200000
+#define GINTSTS_PXFR_INCOMPISOOUT GINTSTS_PXFR_INCOMPISOOUT_Msk // Incomplete periodic transfer
#define GINTSTS_DATAFSUSP_Pos (22U)
-#define GINTSTS_DATAFSUSP_Msk (0x1UL << GINTSTS_DATAFSUSP_Pos) // 0x00400000 */
-#define GINTSTS_DATAFSUSP GINTSTS_DATAFSUSP_Msk // Data fetch suspended */
+#define GINTSTS_DATAFSUSP_Msk (0x1UL << GINTSTS_DATAFSUSP_Pos) // 0x00400000
+#define GINTSTS_DATAFSUSP GINTSTS_DATAFSUSP_Msk // Data fetch suspended
#define GINTSTS_RSTDET_Pos (23U)
-#define GINTSTS_RSTDET_Msk (0x1UL << GINTSTS_RSTDET_Pos) // 0x00800000 */
-#define GINTSTS_RSTDET GINTSTS_RSTDET_Msk // Reset detected interrupt */
+#define GINTSTS_RSTDET_Msk (0x1UL << GINTSTS_RSTDET_Pos) // 0x00800000
+#define GINTSTS_RSTDET GINTSTS_RSTDET_Msk // Reset detected interrupt
#define GINTSTS_HPRTINT_Pos (24U)
-#define GINTSTS_HPRTINT_Msk (0x1UL << GINTSTS_HPRTINT_Pos) // 0x01000000 */
-#define GINTSTS_HPRTINT GINTSTS_HPRTINT_Msk // Host port interrupt */
+#define GINTSTS_HPRTINT_Msk (0x1UL << GINTSTS_HPRTINT_Pos) // 0x01000000
+#define GINTSTS_HPRTINT GINTSTS_HPRTINT_Msk // Host port interrupt
#define GINTSTS_HCINT_Pos (25U)
-#define GINTSTS_HCINT_Msk (0x1UL << GINTSTS_HCINT_Pos) // 0x02000000 */
-#define GINTSTS_HCINT GINTSTS_HCINT_Msk // Host channels interrupt */
+#define GINTSTS_HCINT_Msk (0x1UL << GINTSTS_HCINT_Pos) // 0x02000000
+#define GINTSTS_HCINT GINTSTS_HCINT_Msk // Host channels interrupt
#define GINTSTS_PTXFE_Pos (26U)
-#define GINTSTS_PTXFE_Msk (0x1UL << GINTSTS_PTXFE_Pos) // 0x04000000 */
-#define GINTSTS_PTXFE GINTSTS_PTXFE_Msk // Periodic TxFIFO empty */
+#define GINTSTS_PTXFE_Msk (0x1UL << GINTSTS_PTXFE_Pos) // 0x04000000
+#define GINTSTS_PTXFE GINTSTS_PTXFE_Msk // Periodic TxFIFO empty
#define GINTSTS_LPMINT_Pos (27U)
-#define GINTSTS_LPMINT_Msk (0x1UL << GINTSTS_LPMINT_Pos) // 0x08000000 */
-#define GINTSTS_LPMINT GINTSTS_LPMINT_Msk // LPM interrupt */
+#define GINTSTS_LPMINT_Msk (0x1UL << GINTSTS_LPMINT_Pos) // 0x08000000
+#define GINTSTS_LPMINT GINTSTS_LPMINT_Msk // LPM interrupt
#define GINTSTS_CIDSCHG_Pos (28U)
-#define GINTSTS_CIDSCHG_Msk (0x1UL << GINTSTS_CIDSCHG_Pos) // 0x10000000 */
-#define GINTSTS_CIDSCHG GINTSTS_CIDSCHG_Msk // Connector ID status change */
+#define GINTSTS_CIDSCHG_Msk (0x1UL << GINTSTS_CIDSCHG_Pos) // 0x10000000
+#define GINTSTS_CIDSCHG GINTSTS_CIDSCHG_Msk // Connector ID status change
#define GINTSTS_DISCINT_Pos (29U)
-#define GINTSTS_DISCINT_Msk (0x1UL << GINTSTS_DISCINT_Pos) // 0x20000000 */
-#define GINTSTS_DISCINT GINTSTS_DISCINT_Msk // Disconnect detected interrupt */
+#define GINTSTS_DISCINT_Msk (0x1UL << GINTSTS_DISCINT_Pos) // 0x20000000
+#define GINTSTS_DISCINT GINTSTS_DISCINT_Msk // Disconnect detected interrupt
#define GINTSTS_SRQINT_Pos (30U)
-#define GINTSTS_SRQINT_Msk (0x1UL << GINTSTS_SRQINT_Pos) // 0x40000000 */
-#define GINTSTS_SRQINT GINTSTS_SRQINT_Msk // Session request/new session detected interrupt */
+#define GINTSTS_SRQINT_Msk (0x1UL << GINTSTS_SRQINT_Pos) // 0x40000000
+#define GINTSTS_SRQINT GINTSTS_SRQINT_Msk // Session request/new session detected interrupt
#define GINTSTS_WKUINT_Pos (31U)
-#define GINTSTS_WKUINT_Msk (0x1UL << GINTSTS_WKUINT_Pos) // 0x80000000 */
-#define GINTSTS_WKUINT GINTSTS_WKUINT_Msk // Resume/remote wakeup detected interrupt */
+#define GINTSTS_WKUINT_Msk (0x1UL << GINTSTS_WKUINT_Pos) // 0x80000000
+#define GINTSTS_WKUINT GINTSTS_WKUINT_Msk // Resume/remote wakeup detected interrupt
/******************** Bit definition for GINTMSK register ********************/
#define GINTMSK_MMISM_Pos (1U)
-#define GINTMSK_MMISM_Msk (0x1UL << GINTMSK_MMISM_Pos) // 0x00000002 */
-#define GINTMSK_MMISM GINTMSK_MMISM_Msk // Mode mismatch interrupt mask */
+#define GINTMSK_MMISM_Msk (0x1UL << GINTMSK_MMISM_Pos) // 0x00000002
+#define GINTMSK_MMISM GINTMSK_MMISM_Msk // Mode mismatch interrupt mask
#define GINTMSK_OTGINT_Pos (2U)
-#define GINTMSK_OTGINT_Msk (0x1UL << GINTMSK_OTGINT_Pos) // 0x00000004 */
-#define GINTMSK_OTGINT GINTMSK_OTGINT_Msk // OTG interrupt mask */
+#define GINTMSK_OTGINT_Msk (0x1UL << GINTMSK_OTGINT_Pos) // 0x00000004
+#define GINTMSK_OTGINT GINTMSK_OTGINT_Msk // OTG interrupt mask
#define GINTMSK_SOFM_Pos (3U)
-#define GINTMSK_SOFM_Msk (0x1UL << GINTMSK_SOFM_Pos) // 0x00000008 */
-#define GINTMSK_SOFM GINTMSK_SOFM_Msk // Start of frame mask */
+#define GINTMSK_SOFM_Msk (0x1UL << GINTMSK_SOFM_Pos) // 0x00000008
+#define GINTMSK_SOFM GINTMSK_SOFM_Msk // Start of frame mask
#define GINTMSK_RXFLVLM_Pos (4U)
-#define GINTMSK_RXFLVLM_Msk (0x1UL << GINTMSK_RXFLVLM_Pos) // 0x00000010 */
-#define GINTMSK_RXFLVLM GINTMSK_RXFLVLM_Msk // Receive FIFO nonempty mask */
+#define GINTMSK_RXFLVLM_Msk (0x1UL << GINTMSK_RXFLVLM_Pos) // 0x00000010
+#define GINTMSK_RXFLVLM GINTMSK_RXFLVLM_Msk // Receive FIFO nonempty mask
#define GINTMSK_NPTXFEM_Pos (5U)
-#define GINTMSK_NPTXFEM_Msk (0x1UL << GINTMSK_NPTXFEM_Pos) // 0x00000020 */
-#define GINTMSK_NPTXFEM GINTMSK_NPTXFEM_Msk // Nonperiodic TxFIFO empty mask */
+#define GINTMSK_NPTXFEM_Msk (0x1UL << GINTMSK_NPTXFEM_Pos) // 0x00000020
+#define GINTMSK_NPTXFEM GINTMSK_NPTXFEM_Msk // Nonperiodic TxFIFO empty mask
#define GINTMSK_GINAKEFFM_Pos (6U)
-#define GINTMSK_GINAKEFFM_Msk (0x1UL << GINTMSK_GINAKEFFM_Pos) // 0x00000040 */
-#define GINTMSK_GINAKEFFM GINTMSK_GINAKEFFM_Msk // Global nonperiodic IN NAK effective mask */
+#define GINTMSK_GINAKEFFM_Msk (0x1UL << GINTMSK_GINAKEFFM_Pos) // 0x00000040
+#define GINTMSK_GINAKEFFM GINTMSK_GINAKEFFM_Msk // Global nonperiodic IN NAK effective mask
#define GINTMSK_GONAKEFFM_Pos (7U)
-#define GINTMSK_GONAKEFFM_Msk (0x1UL << GINTMSK_GONAKEFFM_Pos) // 0x00000080 */
-#define GINTMSK_GONAKEFFM GINTMSK_GONAKEFFM_Msk // Global OUT NAK effective mask */
+#define GINTMSK_GONAKEFFM_Msk (0x1UL << GINTMSK_GONAKEFFM_Pos) // 0x00000080
+#define GINTMSK_GONAKEFFM GINTMSK_GONAKEFFM_Msk // Global OUT NAK effective mask
#define GINTMSK_ESUSPM_Pos (10U)
-#define GINTMSK_ESUSPM_Msk (0x1UL << GINTMSK_ESUSPM_Pos) // 0x00000400 */
-#define GINTMSK_ESUSPM GINTMSK_ESUSPM_Msk // Early suspend mask */
+#define GINTMSK_ESUSPM_Msk (0x1UL << GINTMSK_ESUSPM_Pos) // 0x00000400
+#define GINTMSK_ESUSPM GINTMSK_ESUSPM_Msk // Early suspend mask
#define GINTMSK_USBSUSPM_Pos (11U)
-#define GINTMSK_USBSUSPM_Msk (0x1UL << GINTMSK_USBSUSPM_Pos) // 0x00000800 */
-#define GINTMSK_USBSUSPM GINTMSK_USBSUSPM_Msk // USB suspend mask */
+#define GINTMSK_USBSUSPM_Msk (0x1UL << GINTMSK_USBSUSPM_Pos) // 0x00000800
+#define GINTMSK_USBSUSPM GINTMSK_USBSUSPM_Msk // USB suspend mask
#define GINTMSK_USBRST_Pos (12U)
-#define GINTMSK_USBRST_Msk (0x1UL << GINTMSK_USBRST_Pos) // 0x00001000 */
-#define GINTMSK_USBRST GINTMSK_USBRST_Msk // USB reset mask */
+#define GINTMSK_USBRST_Msk (0x1UL << GINTMSK_USBRST_Pos) // 0x00001000
+#define GINTMSK_USBRST GINTMSK_USBRST_Msk // USB reset mask
#define GINTMSK_ENUMDNEM_Pos (13U)
-#define GINTMSK_ENUMDNEM_Msk (0x1UL << GINTMSK_ENUMDNEM_Pos) // 0x00002000 */
-#define GINTMSK_ENUMDNEM GINTMSK_ENUMDNEM_Msk // Enumeration done mask */
+#define GINTMSK_ENUMDNEM_Msk (0x1UL << GINTMSK_ENUMDNEM_Pos) // 0x00002000
+#define GINTMSK_ENUMDNEM GINTMSK_ENUMDNEM_Msk // Enumeration done mask
#define GINTMSK_ISOODRPM_Pos (14U)
-#define GINTMSK_ISOODRPM_Msk (0x1UL << GINTMSK_ISOODRPM_Pos) // 0x00004000 */
-#define GINTMSK_ISOODRPM GINTMSK_ISOODRPM_Msk // Isochronous OUT packet dropped interrupt mask */
+#define GINTMSK_ISOODRPM_Msk (0x1UL << GINTMSK_ISOODRPM_Pos) // 0x00004000
+#define GINTMSK_ISOODRPM GINTMSK_ISOODRPM_Msk // Isochronous OUT packet dropped interrupt mask
#define GINTMSK_EOPFM_Pos (15U)
-#define GINTMSK_EOPFM_Msk (0x1UL << GINTMSK_EOPFM_Pos) // 0x00008000 */
-#define GINTMSK_EOPFM GINTMSK_EOPFM_Msk // End of periodic frame interrupt mask */
+#define GINTMSK_EOPFM_Msk (0x1UL << GINTMSK_EOPFM_Pos) // 0x00008000
+#define GINTMSK_EOPFM GINTMSK_EOPFM_Msk // End of periodic frame interrupt mask
#define GINTMSK_EPMISM_Pos (17U)
-#define GINTMSK_EPMISM_Msk (0x1UL << GINTMSK_EPMISM_Pos) // 0x00020000 */
-#define GINTMSK_EPMISM GINTMSK_EPMISM_Msk // Endpoint mismatch interrupt mask */
+#define GINTMSK_EPMISM_Msk (0x1UL << GINTMSK_EPMISM_Pos) // 0x00020000
+#define GINTMSK_EPMISM GINTMSK_EPMISM_Msk // Endpoint mismatch interrupt mask
#define GINTMSK_IEPINT_Pos (18U)
-#define GINTMSK_IEPINT_Msk (0x1UL << GINTMSK_IEPINT_Pos) // 0x00040000 */
-#define GINTMSK_IEPINT GINTMSK_IEPINT_Msk // IN endpoints interrupt mask */
+#define GINTMSK_IEPINT_Msk (0x1UL << GINTMSK_IEPINT_Pos) // 0x00040000
+#define GINTMSK_IEPINT GINTMSK_IEPINT_Msk // IN endpoints interrupt mask
#define GINTMSK_OEPINT_Pos (19U)
-#define GINTMSK_OEPINT_Msk (0x1UL << GINTMSK_OEPINT_Pos) // 0x00080000 */
-#define GINTMSK_OEPINT GINTMSK_OEPINT_Msk // OUT endpoints interrupt mask */
+#define GINTMSK_OEPINT_Msk (0x1UL << GINTMSK_OEPINT_Pos) // 0x00080000
+#define GINTMSK_OEPINT GINTMSK_OEPINT_Msk // OUT endpoints interrupt mask
#define GINTMSK_IISOIXFRM_Pos (20U)
-#define GINTMSK_IISOIXFRM_Msk (0x1UL << GINTMSK_IISOIXFRM_Pos) // 0x00100000 */
-#define GINTMSK_IISOIXFRM GINTMSK_IISOIXFRM_Msk // Incomplete isochronous IN transfer mask */
+#define GINTMSK_IISOIXFRM_Msk (0x1UL << GINTMSK_IISOIXFRM_Pos) // 0x00100000
+#define GINTMSK_IISOIXFRM GINTMSK_IISOIXFRM_Msk // Incomplete isochronous IN transfer mask
#define GINTMSK_PXFRM_IISOOXFRM_Pos (21U)
-#define GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << GINTMSK_PXFRM_IISOOXFRM_Pos) // 0x00200000 */
-#define GINTMSK_PXFRM_IISOOXFRM GINTMSK_PXFRM_IISOOXFRM_Msk // Incomplete periodic transfer mask */
+#define GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << GINTMSK_PXFRM_IISOOXFRM_Pos) // 0x00200000
+#define GINTMSK_PXFRM_IISOOXFRM GINTMSK_PXFRM_IISOOXFRM_Msk // Incomplete periodic transfer mask
#define GINTMSK_FSUSPM_Pos (22U)
-#define GINTMSK_FSUSPM_Msk (0x1UL << GINTMSK_FSUSPM_Pos) // 0x00400000 */
-#define GINTMSK_FSUSPM GINTMSK_FSUSPM_Msk // Data fetch suspended mask */
+#define GINTMSK_FSUSPM_Msk (0x1UL << GINTMSK_FSUSPM_Pos) // 0x00400000
+#define GINTMSK_FSUSPM GINTMSK_FSUSPM_Msk // Data fetch suspended mask
#define GINTMSK_RSTDEM_Pos (23U)
-#define GINTMSK_RSTDEM_Msk (0x1UL << GINTMSK_RSTDEM_Pos) // 0x00800000 */
-#define GINTMSK_RSTDEM GINTMSK_RSTDEM_Msk // Reset detected interrupt mask */
+#define GINTMSK_RSTDEM_Msk (0x1UL << GINTMSK_RSTDEM_Pos) // 0x00800000
+#define GINTMSK_RSTDEM GINTMSK_RSTDEM_Msk // Reset detected interrupt mask
#define GINTMSK_PRTIM_Pos (24U)
-#define GINTMSK_PRTIM_Msk (0x1UL << GINTMSK_PRTIM_Pos) // 0x01000000 */
-#define GINTMSK_PRTIM GINTMSK_PRTIM_Msk // Host port interrupt mask */
+#define GINTMSK_PRTIM_Msk (0x1UL << GINTMSK_PRTIM_Pos) // 0x01000000
+#define GINTMSK_PRTIM GINTMSK_PRTIM_Msk // Host port interrupt mask
#define GINTMSK_HCIM_Pos (25U)
-#define GINTMSK_HCIM_Msk (0x1UL << GINTMSK_HCIM_Pos) // 0x02000000 */
-#define GINTMSK_HCIM GINTMSK_HCIM_Msk // Host channels interrupt mask */
+#define GINTMSK_HCIM_Msk (0x1UL << GINTMSK_HCIM_Pos) // 0x02000000
+#define GINTMSK_HCIM GINTMSK_HCIM_Msk // Host channels interrupt mask
#define GINTMSK_PTXFEM_Pos (26U)
-#define GINTMSK_PTXFEM_Msk (0x1UL << GINTMSK_PTXFEM_Pos) // 0x04000000 */
-#define GINTMSK_PTXFEM GINTMSK_PTXFEM_Msk // Periodic TxFIFO empty mask */
+#define GINTMSK_PTXFEM_Msk (0x1UL << GINTMSK_PTXFEM_Pos) // 0x04000000
+#define GINTMSK_PTXFEM GINTMSK_PTXFEM_Msk // Periodic TxFIFO empty mask
#define GINTMSK_LPMINTM_Pos (27U)
-#define GINTMSK_LPMINTM_Msk (0x1UL << GINTMSK_LPMINTM_Pos) // 0x08000000 */
-#define GINTMSK_LPMINTM GINTMSK_LPMINTM_Msk // LPM interrupt Mask */
+#define GINTMSK_LPMINTM_Msk (0x1UL << GINTMSK_LPMINTM_Pos) // 0x08000000
+#define GINTMSK_LPMINTM GINTMSK_LPMINTM_Msk // LPM interrupt Mask
#define GINTMSK_CIDSCHGM_Pos (28U)
-#define GINTMSK_CIDSCHGM_Msk (0x1UL << GINTMSK_CIDSCHGM_Pos) // 0x10000000 */
-#define GINTMSK_CIDSCHGM GINTMSK_CIDSCHGM_Msk // Connector ID status change mask */
+#define GINTMSK_CIDSCHGM_Msk (0x1UL << GINTMSK_CIDSCHGM_Pos) // 0x10000000
+#define GINTMSK_CIDSCHGM GINTMSK_CIDSCHGM_Msk // Connector ID status change mask
#define GINTMSK_DISCINT_Pos (29U)
-#define GINTMSK_DISCINT_Msk (0x1UL << GINTMSK_DISCINT_Pos) // 0x20000000 */
-#define GINTMSK_DISCINT GINTMSK_DISCINT_Msk // Disconnect detected interrupt mask */
+#define GINTMSK_DISCINT_Msk (0x1UL << GINTMSK_DISCINT_Pos) // 0x20000000
+#define GINTMSK_DISCINT GINTMSK_DISCINT_Msk // Disconnect detected interrupt mask
#define GINTMSK_SRQIM_Pos (30U)
-#define GINTMSK_SRQIM_Msk (0x1UL << GINTMSK_SRQIM_Pos) // 0x40000000 */
-#define GINTMSK_SRQIM GINTMSK_SRQIM_Msk // Session request/new session detected interrupt mask */
+#define GINTMSK_SRQIM_Msk (0x1UL << GINTMSK_SRQIM_Pos) // 0x40000000
+#define GINTMSK_SRQIM GINTMSK_SRQIM_Msk // Session request/new session detected interrupt mask
#define GINTMSK_WUIM_Pos (31U)
-#define GINTMSK_WUIM_Msk (0x1UL << GINTMSK_WUIM_Pos) // 0x80000000 */
-#define GINTMSK_WUIM GINTMSK_WUIM_Msk // Resume/remote wakeup detected interrupt mask */
+#define GINTMSK_WUIM_Msk (0x1UL << GINTMSK_WUIM_Pos) // 0x80000000
+#define GINTMSK_WUIM GINTMSK_WUIM_Msk // Resume/remote wakeup detected interrupt mask
/******************** Bit definition for DAINT register ********************/
#define DAINT_IEPINT_Pos (0U)
-#define DAINT_IEPINT_Msk (0xFFFFUL << DAINT_IEPINT_Pos) // 0x0000FFFF */
-#define DAINT_IEPINT DAINT_IEPINT_Msk // IN endpoint interrupt bits */
+#define DAINT_IEPINT_Msk (0xFFFFUL << DAINT_IEPINT_Pos) // 0x0000FFFF
+#define DAINT_IEPINT DAINT_IEPINT_Msk // IN endpoint interrupt bits
#define DAINT_OEPINT_Pos (16U)
-#define DAINT_OEPINT_Msk (0xFFFFUL << DAINT_OEPINT_Pos) // 0xFFFF0000 */
-#define DAINT_OEPINT DAINT_OEPINT_Msk // OUT endpoint interrupt bits */
+#define DAINT_OEPINT_Msk (0xFFFFUL << DAINT_OEPINT_Pos) // 0xFFFF0000
+#define DAINT_OEPINT DAINT_OEPINT_Msk // OUT endpoint interrupt bits
/******************** Bit definition for HAINTMSK register ********************/
#define HAINTMSK_HAINTM_Pos (0U)
-#define HAINTMSK_HAINTM_Msk (0xFFFFUL << HAINTMSK_HAINTM_Pos) // 0x0000FFFF */
-#define HAINTMSK_HAINTM HAINTMSK_HAINTM_Msk // Channel interrupt mask */
+#define HAINTMSK_HAINTM_Msk (0xFFFFUL << HAINTMSK_HAINTM_Pos) // 0x0000FFFF
+#define HAINTMSK_HAINTM HAINTMSK_HAINTM_Msk // Channel interrupt mask
/******************** Bit definition for GRXSTSP register ********************/
#define GRXSTSP_EPNUM_Pos (0U)
-#define GRXSTSP_EPNUM_Msk (0xFUL << GRXSTSP_EPNUM_Pos) // 0x0000000F */
-#define GRXSTSP_EPNUM GRXSTSP_EPNUM_Msk // IN EP interrupt mask bits */
+#define GRXSTSP_EPNUM_Msk (0xFUL << GRXSTSP_EPNUM_Pos) // 0x0000000F
+#define GRXSTSP_EPNUM GRXSTSP_EPNUM_Msk // IN EP interrupt mask bits
#define GRXSTSP_BCNT_Pos (4U)
-#define GRXSTSP_BCNT_Msk (0x7FFUL << GRXSTSP_BCNT_Pos) // 0x00007FF0 */
-#define GRXSTSP_BCNT GRXSTSP_BCNT_Msk // OUT EP interrupt mask bits */
+#define GRXSTSP_BCNT_Msk (0x7FFUL << GRXSTSP_BCNT_Pos) // 0x00007FF0
+#define GRXSTSP_BCNT GRXSTSP_BCNT_Msk // OUT EP interrupt mask bits
#define GRXSTSP_DPID_Pos (15U)
-#define GRXSTSP_DPID_Msk (0x3UL << GRXSTSP_DPID_Pos) // 0x00018000 */
-#define GRXSTSP_DPID GRXSTSP_DPID_Msk // OUT EP interrupt mask bits */
+#define GRXSTSP_DPID_Msk (0x3UL << GRXSTSP_DPID_Pos) // 0x00018000
+#define GRXSTSP_DPID GRXSTSP_DPID_Msk // OUT EP interrupt mask bits
#define GRXSTSP_PKTSTS_Pos (17U)
-#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000 */
-#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits */
+#define GRXSTSP_PKTSTS_Msk (0xFUL << GRXSTSP_PKTSTS_Pos) // 0x001E0000
+#define GRXSTSP_PKTSTS GRXSTSP_PKTSTS_Msk // OUT EP interrupt mask bits
#define GRXSTS_PKTSTS_GLOBALOUTNAK 1
#define GRXSTS_PKTSTS_OUTRX 2
@@ -933,773 +934,803 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size");
/******************** Bit definition for DAINTMSK register ********************/
#define DAINTMSK_IEPM_Pos (0U)
-#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF */
-#define DAINTMSK_IEPM DAINTMSK_IEPM_Msk // IN EP interrupt mask bits */
+#define DAINTMSK_IEPM_Msk (0xFFFFUL << DAINTMSK_IEPM_Pos) // 0x0000FFFF
+#define DAINTMSK_IEPM DAINTMSK_IEPM_Msk // IN EP interrupt mask bits
#define DAINTMSK_OEPM_Pos (16U)
-#define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000 */
-#define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits */
+#define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000
+#define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits
#if 0
/******************** Bit definition for OTG register ********************/
#define CHNUM_Pos (0U)
-#define CHNUM_Msk (0xFUL << CHNUM_Pos) // 0x0000000F */
-#define CHNUM CHNUM_Msk // Channel number */
-#define CHNUM_0 (0x1UL << CHNUM_Pos) // 0x00000001 */
-#define CHNUM_1 (0x2UL << CHNUM_Pos) // 0x00000002 */
-#define CHNUM_2 (0x4UL << CHNUM_Pos) // 0x00000004 */
-#define CHNUM_3 (0x8UL << CHNUM_Pos) // 0x00000008 */
+#define CHNUM_Msk (0xFUL << CHNUM_Pos) // 0x0000000F
+#define CHNUM CHNUM_Msk // Channel number
+#define CHNUM_0 (0x1UL << CHNUM_Pos) // 0x00000001
+#define CHNUM_1 (0x2UL << CHNUM_Pos) // 0x00000002
+#define CHNUM_2 (0x4UL << CHNUM_Pos) // 0x00000004
+#define CHNUM_3 (0x8UL << CHNUM_Pos) // 0x00000008
#define BCNT_Pos (4U)
-#define BCNT_Msk (0x7FFUL << BCNT_Pos) // 0x00007FF0 */
-#define BCNT BCNT_Msk // Byte count */
+#define BCNT_Msk (0x7FFUL << BCNT_Pos) // 0x00007FF0
+#define BCNT BCNT_Msk // Byte count
#define DPID_Pos (15U)
-#define DPID_Msk (0x3UL << DPID_Pos) // 0x00018000 */
-#define DPID DPID_Msk // Data PID */
-#define DPID_0 (0x1UL << DPID_Pos) // 0x00008000 */
-#define DPID_1 (0x2UL << DPID_Pos) // 0x00010000 */
+#define DPID_Msk (0x3UL << DPID_Pos) // 0x00018000
+#define DPID DPID_Msk // Data PID
+#define DPID_0 (0x1UL << DPID_Pos) // 0x00008000
+#define DPID_1 (0x2UL << DPID_Pos) // 0x00010000
#define PKTSTS_Pos (17U)
-#define PKTSTS_Msk (0xFUL << PKTSTS_Pos) // 0x001E0000 */
-#define PKTSTS PKTSTS_Msk // Packet status */
-#define PKTSTS_0 (0x1UL << PKTSTS_Pos) // 0x00020000 */
-#define PKTSTS_1 (0x2UL << PKTSTS_Pos) // 0x00040000 */
-#define PKTSTS_2 (0x4UL << PKTSTS_Pos) // 0x00080000 */
-#define PKTSTS_3 (0x8UL << PKTSTS_Pos) // 0x00100000 */
+#define PKTSTS_Msk (0xFUL << PKTSTS_Pos) // 0x001E0000
+#define PKTSTS PKTSTS_Msk // Packet status
+#define PKTSTS_0 (0x1UL << PKTSTS_Pos) // 0x00020000
+#define PKTSTS_1 (0x2UL << PKTSTS_Pos) // 0x00040000
+#define PKTSTS_2 (0x4UL << PKTSTS_Pos) // 0x00080000
+#define PKTSTS_3 (0x8UL << PKTSTS_Pos) // 0x00100000
#define EPNUM_Pos (0U)
-#define EPNUM_Msk (0xFUL << EPNUM_Pos) // 0x0000000F */
-#define EPNUM EPNUM_Msk // Endpoint number */
-#define EPNUM_0 (0x1UL << EPNUM_Pos) // 0x00000001 */
-#define EPNUM_1 (0x2UL << EPNUM_Pos) // 0x00000002 */
-#define EPNUM_2 (0x4UL << EPNUM_Pos) // 0x00000004 */
-#define EPNUM_3 (0x8UL << EPNUM_Pos) // 0x00000008 */
+#define EPNUM_Msk (0xFUL << EPNUM_Pos) // 0x0000000F
+#define EPNUM EPNUM_Msk // Endpoint number
+#define EPNUM_0 (0x1UL << EPNUM_Pos) // 0x00000001
+#define EPNUM_1 (0x2UL << EPNUM_Pos) // 0x00000002
+#define EPNUM_2 (0x4UL << EPNUM_Pos) // 0x00000004
+#define EPNUM_3 (0x8UL << EPNUM_Pos) // 0x00000008
#define FRMNUM_Pos (21U)
-#define FRMNUM_Msk (0xFUL << FRMNUM_Pos) // 0x01E00000 */
-#define FRMNUM FRMNUM_Msk // Frame number */
-#define FRMNUM_0 (0x1UL << FRMNUM_Pos) // 0x00200000 */
-#define FRMNUM_1 (0x2UL << FRMNUM_Pos) // 0x00400000 */
-#define FRMNUM_2 (0x4UL << FRMNUM_Pos) // 0x00800000 */
-#define FRMNUM_3 (0x8UL << FRMNUM_Pos) // 0x01000000 */
+#define FRMNUM_Msk (0xFUL << FRMNUM_Pos) // 0x01E00000
+#define FRMNUM FRMNUM_Msk // Frame number
+#define FRMNUM_0 (0x1UL << FRMNUM_Pos) // 0x00200000
+#define FRMNUM_1 (0x2UL << FRMNUM_Pos) // 0x00400000
+#define FRMNUM_2 (0x4UL << FRMNUM_Pos) // 0x00800000
+#define FRMNUM_3 (0x8UL << FRMNUM_Pos) // 0x01000000
#endif
/******************** Bit definition for GRXFSIZ register ********************/
#define GRXFSIZ_RXFD_Pos (0U)
-#define GRXFSIZ_RXFD_Msk (0xFFFFUL << GRXFSIZ_RXFD_Pos) // 0x0000FFFF */
-#define GRXFSIZ_RXFD GRXFSIZ_RXFD_Msk // RxFIFO depth */
+#define GRXFSIZ_RXFD_Msk (0xFFFFUL << GRXFSIZ_RXFD_Pos) // 0x0000FFFF
+#define GRXFSIZ_RXFD GRXFSIZ_RXFD_Msk // RxFIFO depth
/******************** Bit definition for DVBUSDIS register ********************/
#define DVBUSDIS_VBUSDT_Pos (0U)
-#define DVBUSDIS_VBUSDT_Msk (0xFFFFUL << DVBUSDIS_VBUSDT_Pos) // 0x0000FFFF */
-#define DVBUSDIS_VBUSDT DVBUSDIS_VBUSDT_Msk // Device VBUS discharge time */
+#define DVBUSDIS_VBUSDT_Msk (0xFFFFUL << DVBUSDIS_VBUSDT_Pos) // 0x0000FFFF
+#define DVBUSDIS_VBUSDT DVBUSDIS_VBUSDT_Msk // Device VBUS discharge time
/******************** Bit definition for OTG register ********************/
#define GNPTXFSIZ_NPTXFSA_Pos (0U)
-#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFSA_Pos) // 0x0000FFFF */
-#define GNPTXFSIZ_NPTXFSA GNPTXFSIZ_NPTXFSA_Msk // Nonperiodic transmit RAM start address */
+#define GNPTXFSIZ_NPTXFSA_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFSA_Pos) // 0x0000FFFF
+#define GNPTXFSIZ_NPTXFSA GNPTXFSIZ_NPTXFSA_Msk // Nonperiodic transmit RAM start address
#define GNPTXFSIZ_NPTXFD_Pos (16U)
-#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFD_Pos) // 0xFFFF0000 */
-#define GNPTXFSIZ_NPTXFD GNPTXFSIZ_NPTXFD_Msk // Nonperiodic TxFIFO depth */
+#define GNPTXFSIZ_NPTXFD_Msk (0xFFFFUL << GNPTXFSIZ_NPTXFD_Pos) // 0xFFFF0000
+#define GNPTXFSIZ_NPTXFD GNPTXFSIZ_NPTXFD_Msk // Nonperiodic TxFIFO depth
#define DIEPTXF0_TX0FSA_Pos (0U)
-#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << DIEPTXF0_TX0FSA_Pos) // 0x0000FFFF */
-#define DIEPTXF0_TX0FSA DIEPTXF0_TX0FSA_Msk // Endpoint 0 transmit RAM start address */
+#define DIEPTXF0_TX0FSA_Msk (0xFFFFUL << DIEPTXF0_TX0FSA_Pos) // 0x0000FFFF
+#define DIEPTXF0_TX0FSA DIEPTXF0_TX0FSA_Msk // Endpoint 0 transmit RAM start address
#define DIEPTXF0_TX0FD_Pos (16U)
-#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << DIEPTXF0_TX0FD_Pos) // 0xFFFF0000 */
-#define DIEPTXF0_TX0FD DIEPTXF0_TX0FD_Msk // Endpoint 0 TxFIFO depth */
+#define DIEPTXF0_TX0FD_Msk (0xFFFFUL << DIEPTXF0_TX0FD_Pos) // 0xFFFF0000
+#define DIEPTXF0_TX0FD DIEPTXF0_TX0FD_Msk // Endpoint 0 TxFIFO depth
/******************** Bit definition for DVBUSPULSE register ********************/
#define DVBUSPULSE_DVBUSP_Pos (0U)
-#define DVBUSPULSE_DVBUSP_Msk (0xFFFUL << DVBUSPULSE_DVBUSP_Pos) // 0x00000FFF */
-#define DVBUSPULSE_DVBUSP DVBUSPULSE_DVBUSP_Msk // Device VBUS pulsing time */
+#define DVBUSPULSE_DVBUSP_Msk (0xFFFUL << DVBUSPULSE_DVBUSP_Pos) // 0x00000FFF
+#define DVBUSPULSE_DVBUSP DVBUSPULSE_DVBUSP_Msk // Device VBUS pulsing time
/******************** Bit definition for GNPTXSTS register ********************/
#define GNPTXSTS_NPTXFSAV_Pos (0U)
-#define GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << GNPTXSTS_NPTXFSAV_Pos) // 0x0000FFFF */
-#define GNPTXSTS_NPTXFSAV GNPTXSTS_NPTXFSAV_Msk // Nonperiodic TxFIFO space available */
+#define GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << GNPTXSTS_NPTXFSAV_Pos) // 0x0000FFFF
+#define GNPTXSTS_NPTXFSAV GNPTXSTS_NPTXFSAV_Msk // Nonperiodic TxFIFO space available
#define GNPTXSTS_NPTQXSAV_Pos (16U)
-#define GNPTXSTS_NPTQXSAV_Msk (0xFFUL << GNPTXSTS_NPTQXSAV_Pos) // 0x00FF0000 */
-#define GNPTXSTS_NPTQXSAV GNPTXSTS_NPTQXSAV_Msk // Nonperiodic transmit request queue space available */
-#define GNPTXSTS_NPTQXSAV_0 (0x01UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00010000 */
-#define GNPTXSTS_NPTQXSAV_1 (0x02UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00020000 */
-#define GNPTXSTS_NPTQXSAV_2 (0x04UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00040000 */
-#define GNPTXSTS_NPTQXSAV_3 (0x08UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00080000 */
-#define GNPTXSTS_NPTQXSAV_4 (0x10UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00100000 */
-#define GNPTXSTS_NPTQXSAV_5 (0x20UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00200000 */
-#define GNPTXSTS_NPTQXSAV_6 (0x40UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00400000 */
-#define GNPTXSTS_NPTQXSAV_7 (0x80UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00800000 */
+#define GNPTXSTS_NPTQXSAV_Msk (0xFFUL << GNPTXSTS_NPTQXSAV_Pos) // 0x00FF0000
+#define GNPTXSTS_NPTQXSAV GNPTXSTS_NPTQXSAV_Msk // Nonperiodic transmit request queue space available
+#define GNPTXSTS_NPTQXSAV_0 (0x01UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00010000
+#define GNPTXSTS_NPTQXSAV_1 (0x02UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00020000
+#define GNPTXSTS_NPTQXSAV_2 (0x04UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00040000
+#define GNPTXSTS_NPTQXSAV_3 (0x08UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00080000
+#define GNPTXSTS_NPTQXSAV_4 (0x10UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00100000
+#define GNPTXSTS_NPTQXSAV_5 (0x20UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00200000
+#define GNPTXSTS_NPTQXSAV_6 (0x40UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00400000
+#define GNPTXSTS_NPTQXSAV_7 (0x80UL << GNPTXSTS_NPTQXSAV_Pos) // 0x00800000
#define GNPTXSTS_NPTXQTOP_Pos (24U)
-#define GNPTXSTS_NPTXQTOP_Msk (0x7FUL << GNPTXSTS_NPTXQTOP_Pos) // 0x7F000000 */
-#define GNPTXSTS_NPTXQTOP GNPTXSTS_NPTXQTOP_Msk // Top of the nonperiodic transmit request queue */
-#define GNPTXSTS_NPTXQTOP_0 (0x01UL << GNPTXSTS_NPTXQTOP_Pos) // 0x01000000 */
-#define GNPTXSTS_NPTXQTOP_1 (0x02UL << GNPTXSTS_NPTXQTOP_Pos) // 0x02000000 */
-#define GNPTXSTS_NPTXQTOP_2 (0x04UL << GNPTXSTS_NPTXQTOP_Pos) // 0x04000000 */
-#define GNPTXSTS_NPTXQTOP_3 (0x08UL << GNPTXSTS_NPTXQTOP_Pos) // 0x08000000 */
-#define GNPTXSTS_NPTXQTOP_4 (0x10UL << GNPTXSTS_NPTXQTOP_Pos) // 0x10000000 */
-#define GNPTXSTS_NPTXQTOP_5 (0x20UL << GNPTXSTS_NPTXQTOP_Pos) // 0x20000000 */
-#define GNPTXSTS_NPTXQTOP_6 (0x40UL << GNPTXSTS_NPTXQTOP_Pos) // 0x40000000 */
+#define GNPTXSTS_NPTXQTOP_Msk (0x7FUL << GNPTXSTS_NPTXQTOP_Pos) // 0x7F000000
+#define GNPTXSTS_NPTXQTOP GNPTXSTS_NPTXQTOP_Msk // Top of the nonperiodic transmit request queue
+#define GNPTXSTS_NPTXQTOP_0 (0x01UL << GNPTXSTS_NPTXQTOP_Pos) // 0x01000000
+#define GNPTXSTS_NPTXQTOP_1 (0x02UL << GNPTXSTS_NPTXQTOP_Pos) // 0x02000000
+#define GNPTXSTS_NPTXQTOP_2 (0x04UL << GNPTXSTS_NPTXQTOP_Pos) // 0x04000000
+#define GNPTXSTS_NPTXQTOP_3 (0x08UL << GNPTXSTS_NPTXQTOP_Pos) // 0x08000000
+#define GNPTXSTS_NPTXQTOP_4 (0x10UL << GNPTXSTS_NPTXQTOP_Pos) // 0x10000000
+#define GNPTXSTS_NPTXQTOP_5 (0x20UL << GNPTXSTS_NPTXQTOP_Pos) // 0x20000000
+#define GNPTXSTS_NPTXQTOP_6 (0x40UL << GNPTXSTS_NPTXQTOP_Pos) // 0x40000000
/******************** Bit definition for DTHRCTL register ********************/
#define DTHRCTL_NONISOTHREN_Pos (0U)
-#define DTHRCTL_NONISOTHREN_Msk (0x1UL << DTHRCTL_NONISOTHREN_Pos) // 0x00000001 */
-#define DTHRCTL_NONISOTHREN DTHRCTL_NONISOTHREN_Msk // Nonisochronous IN endpoints threshold enable */
+#define DTHRCTL_NONISOTHREN_Msk (0x1UL << DTHRCTL_NONISOTHREN_Pos) // 0x00000001
+#define DTHRCTL_NONISOTHREN DTHRCTL_NONISOTHREN_Msk // Nonisochronous IN endpoints threshold enable
#define DTHRCTL_ISOTHREN_Pos (1U)
-#define DTHRCTL_ISOTHREN_Msk (0x1UL << DTHRCTL_ISOTHREN_Pos) // 0x00000002 */
-#define DTHRCTL_ISOTHREN DTHRCTL_ISOTHREN_Msk // ISO IN endpoint threshold enable */
+#define DTHRCTL_ISOTHREN_Msk (0x1UL << DTHRCTL_ISOTHREN_Pos) // 0x00000002
+#define DTHRCTL_ISOTHREN DTHRCTL_ISOTHREN_Msk // ISO IN endpoint threshold enable
#define DTHRCTL_TXTHRLEN_Pos (2U)
-#define DTHRCTL_TXTHRLEN_Msk (0x1FFUL << DTHRCTL_TXTHRLEN_Pos) // 0x000007FC */
-#define DTHRCTL_TXTHRLEN DTHRCTL_TXTHRLEN_Msk // Transmit threshold length */
-#define DTHRCTL_TXTHRLEN_0 (0x001UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000004 */
-#define DTHRCTL_TXTHRLEN_1 (0x002UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000008 */
-#define DTHRCTL_TXTHRLEN_2 (0x004UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000010 */
-#define DTHRCTL_TXTHRLEN_3 (0x008UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000020 */
-#define DTHRCTL_TXTHRLEN_4 (0x010UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000040 */
-#define DTHRCTL_TXTHRLEN_5 (0x020UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000080 */
-#define DTHRCTL_TXTHRLEN_6 (0x040UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000100 */
-#define DTHRCTL_TXTHRLEN_7 (0x080UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000200 */
-#define DTHRCTL_TXTHRLEN_8 (0x100UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000400 */
+#define DTHRCTL_TXTHRLEN_Msk (0x1FFUL << DTHRCTL_TXTHRLEN_Pos) // 0x000007FC
+#define DTHRCTL_TXTHRLEN DTHRCTL_TXTHRLEN_Msk // Transmit threshold length
+#define DTHRCTL_TXTHRLEN_0 (0x001UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000004
+#define DTHRCTL_TXTHRLEN_1 (0x002UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000008
+#define DTHRCTL_TXTHRLEN_2 (0x004UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000010
+#define DTHRCTL_TXTHRLEN_3 (0x008UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000020
+#define DTHRCTL_TXTHRLEN_4 (0x010UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000040
+#define DTHRCTL_TXTHRLEN_5 (0x020UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000080
+#define DTHRCTL_TXTHRLEN_6 (0x040UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000100
+#define DTHRCTL_TXTHRLEN_7 (0x080UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000200
+#define DTHRCTL_TXTHRLEN_8 (0x100UL << DTHRCTL_TXTHRLEN_Pos) // 0x00000400
#define DTHRCTL_RXTHREN_Pos (16U)
-#define DTHRCTL_RXTHREN_Msk (0x1UL << DTHRCTL_RXTHREN_Pos) // 0x00010000 */
-#define DTHRCTL_RXTHREN DTHRCTL_RXTHREN_Msk // Receive threshold enable */
+#define DTHRCTL_RXTHREN_Msk (0x1UL << DTHRCTL_RXTHREN_Pos) // 0x00010000
+#define DTHRCTL_RXTHREN DTHRCTL_RXTHREN_Msk // Receive threshold enable
#define DTHRCTL_RXTHRLEN_Pos (17U)
-#define DTHRCTL_RXTHRLEN_Msk (0x1FFUL << DTHRCTL_RXTHRLEN_Pos) // 0x03FE0000 */
-#define DTHRCTL_RXTHRLEN DTHRCTL_RXTHRLEN_Msk // Receive threshold length */
-#define DTHRCTL_RXTHRLEN_0 (0x001UL << DTHRCTL_RXTHRLEN_Pos) // 0x00020000 */
-#define DTHRCTL_RXTHRLEN_1 (0x002UL << DTHRCTL_RXTHRLEN_Pos) // 0x00040000 */
-#define DTHRCTL_RXTHRLEN_2 (0x004UL << DTHRCTL_RXTHRLEN_Pos) // 0x00080000 */
-#define DTHRCTL_RXTHRLEN_3 (0x008UL << DTHRCTL_RXTHRLEN_Pos) // 0x00100000 */
-#define DTHRCTL_RXTHRLEN_4 (0x010UL << DTHRCTL_RXTHRLEN_Pos) // 0x00200000 */
-#define DTHRCTL_RXTHRLEN_5 (0x020UL << DTHRCTL_RXTHRLEN_Pos) // 0x00400000 */
-#define DTHRCTL_RXTHRLEN_6 (0x040UL << DTHRCTL_RXTHRLEN_Pos) // 0x00800000 */
-#define DTHRCTL_RXTHRLEN_7 (0x080UL << DTHRCTL_RXTHRLEN_Pos) // 0x01000000 */
-#define DTHRCTL_RXTHRLEN_8 (0x100UL << DTHRCTL_RXTHRLEN_Pos) // 0x02000000 */
+#define DTHRCTL_RXTHRLEN_Msk (0x1FFUL << DTHRCTL_RXTHRLEN_Pos) // 0x03FE0000
+#define DTHRCTL_RXTHRLEN DTHRCTL_RXTHRLEN_Msk // Receive threshold length
+#define DTHRCTL_RXTHRLEN_0 (0x001UL << DTHRCTL_RXTHRLEN_Pos) // 0x00020000
+#define DTHRCTL_RXTHRLEN_1 (0x002UL << DTHRCTL_RXTHRLEN_Pos) // 0x00040000
+#define DTHRCTL_RXTHRLEN_2 (0x004UL << DTHRCTL_RXTHRLEN_Pos) // 0x00080000
+#define DTHRCTL_RXTHRLEN_3 (0x008UL << DTHRCTL_RXTHRLEN_Pos) // 0x00100000
+#define DTHRCTL_RXTHRLEN_4 (0x010UL << DTHRCTL_RXTHRLEN_Pos) // 0x00200000
+#define DTHRCTL_RXTHRLEN_5 (0x020UL << DTHRCTL_RXTHRLEN_Pos) // 0x00400000
+#define DTHRCTL_RXTHRLEN_6 (0x040UL << DTHRCTL_RXTHRLEN_Pos) // 0x00800000
+#define DTHRCTL_RXTHRLEN_7 (0x080UL << DTHRCTL_RXTHRLEN_Pos) // 0x01000000
+#define DTHRCTL_RXTHRLEN_8 (0x100UL << DTHRCTL_RXTHRLEN_Pos) // 0x02000000
#define DTHRCTL_ARPEN_Pos (27U)
-#define DTHRCTL_ARPEN_Msk (0x1UL << DTHRCTL_ARPEN_Pos) // 0x08000000 */
-#define DTHRCTL_ARPEN DTHRCTL_ARPEN_Msk // Arbiter parking enable */
+#define DTHRCTL_ARPEN_Msk (0x1UL << DTHRCTL_ARPEN_Pos) // 0x08000000
+#define DTHRCTL_ARPEN DTHRCTL_ARPEN_Msk // Arbiter parking enable
/******************** Bit definition for DIEPEMPMSK register ********************/
#define DIEPEMPMSK_INEPTXFEM_Pos (0U)
-#define DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << DIEPEMPMSK_INEPTXFEM_Pos) // 0x0000FFFF */
-#define DIEPEMPMSK_INEPTXFEM DIEPEMPMSK_INEPTXFEM_Msk // IN EP Tx FIFO empty interrupt mask bits */
+#define DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << DIEPEMPMSK_INEPTXFEM_Pos) // 0x0000FFFF
+#define DIEPEMPMSK_INEPTXFEM DIEPEMPMSK_INEPTXFEM_Msk // IN EP Tx FIFO empty interrupt mask bits
/******************** Bit definition for DEACHINT register ********************/
#define DEACHINT_IEP1INT_Pos (1U)
-#define DEACHINT_IEP1INT_Msk (0x1UL << DEACHINT_IEP1INT_Pos) // 0x00000002 */
-#define DEACHINT_IEP1INT DEACHINT_IEP1INT_Msk // IN endpoint 1interrupt bit */
+#define DEACHINT_IEP1INT_Msk (0x1UL << DEACHINT_IEP1INT_Pos) // 0x00000002
+#define DEACHINT_IEP1INT DEACHINT_IEP1INT_Msk // IN endpoint 1interrupt bit
#define DEACHINT_OEP1INT_Pos (17U)
-#define DEACHINT_OEP1INT_Msk (0x1UL << DEACHINT_OEP1INT_Pos) // 0x00020000 */
-#define DEACHINT_OEP1INT DEACHINT_OEP1INT_Msk // OUT endpoint 1 interrupt bit */
+#define DEACHINT_OEP1INT_Msk (0x1UL << DEACHINT_OEP1INT_Pos) // 0x00020000
+#define DEACHINT_OEP1INT DEACHINT_OEP1INT_Msk // OUT endpoint 1 interrupt bit
/******************** Bit definition for GCCFG register ********************/
#define STM32_GCCFG_DCDET_Pos (0U)
-#define STM32_GCCFG_DCDET_Msk (0x1UL << STM32_GCCFG_DCDET_Pos) // 0x00000001 */
-#define STM32_GCCFG_DCDET STM32_GCCFG_DCDET_Msk // Data contact detection (DCD) status */
+#define STM32_GCCFG_DCDET_Msk (0x1UL << STM32_GCCFG_DCDET_Pos) // 0x00000001
+#define STM32_GCCFG_DCDET STM32_GCCFG_DCDET_Msk // Data contact detection (DCD) status
+
#define STM32_GCCFG_PDET_Pos (1U)
-#define STM32_GCCFG_PDET_Msk (0x1UL << STM32_GCCFG_PDET_Pos) // 0x00000002 */
-#define STM32_GCCFG_PDET STM32_GCCFG_PDET_Msk // Primary detection (PD) status */
+#define STM32_GCCFG_PDET_Msk (0x1UL << STM32_GCCFG_PDET_Pos) // 0x00000002
+#define STM32_GCCFG_PDET STM32_GCCFG_PDET_Msk // Primary detection (PD) status
+
#define STM32_GCCFG_SDET_Pos (2U)
-#define STM32_GCCFG_SDET_Msk (0x1UL << STM32_GCCFG_SDET_Pos) // 0x00000004 */
-#define STM32_GCCFG_SDET STM32_GCCFG_SDET_Msk // Secondary detection (SD) status */
+#define STM32_GCCFG_SDET_Msk (0x1UL << STM32_GCCFG_SDET_Pos) // 0x00000004
+#define STM32_GCCFG_SDET STM32_GCCFG_SDET_Msk // Secondary detection (SD) status
+
#define STM32_GCCFG_PS2DET_Pos (3U)
-#define STM32_GCCFG_PS2DET_Msk (0x1UL << STM32_GCCFG_PS2DET_Pos) // 0x00000008 */
-#define STM32_GCCFG_PS2DET STM32_GCCFG_PS2DET_Msk // DM pull-up detection status */
+#define STM32_GCCFG_PS2DET_Msk (0x1UL << STM32_GCCFG_PS2DET_Pos) // 0x00000008
+#define STM32_GCCFG_PS2DET STM32_GCCFG_PS2DET_Msk // DM pull-up detection status
+
#define STM32_GCCFG_PWRDWN_Pos (16U)
-#define STM32_GCCFG_PWRDWN_Msk (0x1UL << STM32_GCCFG_PWRDWN_Pos) // 0x00010000 */
-#define STM32_GCCFG_PWRDWN STM32_GCCFG_PWRDWN_Msk // Power down */
+#define STM32_GCCFG_PWRDWN_Msk (0x1UL << STM32_GCCFG_PWRDWN_Pos) // 0x00010000
+#define STM32_GCCFG_PWRDWN STM32_GCCFG_PWRDWN_Msk // Power down
+
#define STM32_GCCFG_BCDEN_Pos (17U)
-#define STM32_GCCFG_BCDEN_Msk (0x1UL << STM32_GCCFG_BCDEN_Pos) // 0x00020000 */
-#define STM32_GCCFG_BCDEN STM32_GCCFG_BCDEN_Msk // Battery charging detector (BCD) enable */
+#define STM32_GCCFG_BCDEN_Msk (0x1UL << STM32_GCCFG_BCDEN_Pos) // 0x00020000
+#define STM32_GCCFG_BCDEN STM32_GCCFG_BCDEN_Msk // Battery charging detector (BCD) enable
+
#define STM32_GCCFG_DCDEN_Pos (18U)
-#define STM32_GCCFG_DCDEN_Msk (0x1UL << STM32_GCCFG_DCDEN_Pos) // 0x00040000 */
+#define STM32_GCCFG_DCDEN_Msk (0x1UL << STM32_GCCFG_DCDEN_Pos) // 0x00040000
#define STM32_GCCFG_DCDEN STM32_GCCFG_DCDEN_Msk // Data contact detection (DCD) mode enable*/
+
#define STM32_GCCFG_PDEN_Pos (19U)
-#define STM32_GCCFG_PDEN_Msk (0x1UL << STM32_GCCFG_PDEN_Pos) // 0x00080000 */
+#define STM32_GCCFG_PDEN_Msk (0x1UL << STM32_GCCFG_PDEN_Pos) // 0x00080000
#define STM32_GCCFG_PDEN STM32_GCCFG_PDEN_Msk // Primary detection (PD) mode enable*/
+
#define STM32_GCCFG_SDEN_Pos (20U)
-#define STM32_GCCFG_SDEN_Msk (0x1UL << STM32_GCCFG_SDEN_Pos) // 0x00100000 */
-#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (SD) mode enable */
+#define STM32_GCCFG_SDEN_Msk (0x1UL << STM32_GCCFG_SDEN_Pos) // 0x00100000
+#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (SD) mode enable
+
#define STM32_GCCFG_VBDEN_Pos (21U)
-#define STM32_GCCFG_VBDEN_Msk (0x1UL << STM32_GCCFG_VBDEN_Pos) // 0x00200000 */
-#define STM32_GCCFG_VBDEN STM32_GCCFG_VBDEN_Msk // VBUS mode enable */
+#define STM32_GCCFG_VBDEN_Msk (0x1UL << STM32_GCCFG_VBDEN_Pos) // 0x00200000
+#define STM32_GCCFG_VBDEN STM32_GCCFG_VBDEN_Msk // VBUS mode enable
+
#define STM32_GCCFG_OTGIDEN_Pos (22U)
-#define STM32_GCCFG_OTGIDEN_Msk (0x1UL << STM32_GCCFG_OTGIDEN_Pos) // 0x00400000 */
-#define STM32_GCCFG_OTGIDEN STM32_GCCFG_OTGIDEN_Msk // OTG Id enable */
+#define STM32_GCCFG_OTGIDEN_Msk (0x1UL << STM32_GCCFG_OTGIDEN_Pos) // 0x00400000
+#define STM32_GCCFG_OTGIDEN STM32_GCCFG_OTGIDEN_Msk // OTG Id enable
+
#define STM32_GCCFG_PHYHSEN_Pos (23U)
-#define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000 */
-#define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable */
+#define STM32_GCCFG_PHYHSEN_Msk (0x1UL << STM32_GCCFG_PHYHSEN_Pos) // 0x00800000
+#define STM32_GCCFG_PHYHSEN STM32_GCCFG_PHYHSEN_Msk // HS PHY enable
+
+// TODO stm32u5a5 SDEN is 22nd bit, conflict with 20th bit above
+//#define STM32_GCCFG_SDEN_Pos (22U)
+//#define STM32_GCCFG_SDEN_Msk (0x1U << STM32_GCCFG_SDEN_Pos) // 0x00400000
+//#define STM32_GCCFG_SDEN STM32_GCCFG_SDEN_Msk // Secondary detection (PD) mode enable
+
+// TODO stm32u5a5 VBVALOVA is 23rd bit, conflict with PHYHSEN bit above
+#define STM32_GCCFG_VBVALOVAL_Pos (23U)
+#define STM32_GCCFG_VBVALOVAL_Msk (0x1U << STM32_GCCFG_VBVALOVAL_Pos) // 0x00800000
+#define STM32_GCCFG_VBVALOVAL STM32_GCCFG_VBVALOVAL_Msk // Value of VBUSVLDEXT0 femtoPHY input
+
+#define STM32_GCCFG_VBVALEXTOEN_Pos (24U)
+#define STM32_GCCFG_VBVALEXTOEN_Msk (0x1U << STM32_GCCFG_VBVALEXTOEN_Pos) // 0x01000000
+#define STM32_GCCFG_VBVALEXTOEN STM32_GCCFG_VBVALEXTOEN_Msk // Enables of VBUSVLDEXT0 femtoPHY input override
+
+#define STM32_GCCFG_PULLDOWNEN_Pos (25U)
+#define STM32_GCCFG_PULLDOWNEN_Msk (0x1U << STM32_GCCFG_PULLDOWNEN_Pos) // 0x02000000
+#define STM32_GCCFG_PULLDOWNEN STM32_GCCFG_PULLDOWNEN_Msk // Enables of femtoPHY pulldown resistors, used when ID PAD is disabled
+
/******************** Bit definition for DEACHINTMSK register ********************/
#define DEACHINTMSK_IEP1INTM_Pos (1U)
-#define DEACHINTMSK_IEP1INTM_Msk (0x1UL << DEACHINTMSK_IEP1INTM_Pos) // 0x00000002 */
-#define DEACHINTMSK_IEP1INTM DEACHINTMSK_IEP1INTM_Msk // IN Endpoint 1 interrupt mask bit */
+#define DEACHINTMSK_IEP1INTM_Msk (0x1UL << DEACHINTMSK_IEP1INTM_Pos) // 0x00000002
+#define DEACHINTMSK_IEP1INTM DEACHINTMSK_IEP1INTM_Msk // IN Endpoint 1 interrupt mask bit
#define DEACHINTMSK_OEP1INTM_Pos (17U)
-#define DEACHINTMSK_OEP1INTM_Msk (0x1UL << DEACHINTMSK_OEP1INTM_Pos) // 0x00020000 */
-#define DEACHINTMSK_OEP1INTM DEACHINTMSK_OEP1INTM_Msk // OUT Endpoint 1 interrupt mask bit */
+#define DEACHINTMSK_OEP1INTM_Msk (0x1UL << DEACHINTMSK_OEP1INTM_Pos) // 0x00020000
+#define DEACHINTMSK_OEP1INTM DEACHINTMSK_OEP1INTM_Msk // OUT Endpoint 1 interrupt mask bit
/******************** Bit definition for CID register ********************/
#define CID_PRODUCT_ID_Pos (0U)
-#define CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << CID_PRODUCT_ID_Pos) // 0xFFFFFFFF */
-#define CID_PRODUCT_ID CID_PRODUCT_ID_Msk // Product ID field */
+#define CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << CID_PRODUCT_ID_Pos) // 0xFFFFFFFF
+#define CID_PRODUCT_ID CID_PRODUCT_ID_Msk // Product ID field
/******************** Bit definition for GLPMCFG register ********************/
#define GLPMCFG_LPMEN_Pos (0U)
-#define GLPMCFG_LPMEN_Msk (0x1UL << GLPMCFG_LPMEN_Pos) // 0x00000001 */
-#define GLPMCFG_LPMEN GLPMCFG_LPMEN_Msk // LPM support enable */
+#define GLPMCFG_LPMEN_Msk (0x1UL << GLPMCFG_LPMEN_Pos) // 0x00000001
+#define GLPMCFG_LPMEN GLPMCFG_LPMEN_Msk // LPM support enable
#define GLPMCFG_LPMACK_Pos (1U)
-#define GLPMCFG_LPMACK_Msk (0x1UL << GLPMCFG_LPMACK_Pos) // 0x00000002 */
-#define GLPMCFG_LPMACK GLPMCFG_LPMACK_Msk // LPM Token acknowledge enable */
+#define GLPMCFG_LPMACK_Msk (0x1UL << GLPMCFG_LPMACK_Pos) // 0x00000002
+#define GLPMCFG_LPMACK GLPMCFG_LPMACK_Msk // LPM Token acknowledge enable
#define GLPMCFG_BESL_Pos (2U)
-#define GLPMCFG_BESL_Msk (0xFUL << GLPMCFG_BESL_Pos) // 0x0000003C */
-#define GLPMCFG_BESL GLPMCFG_BESL_Msk // BESL value received with last ACKed LPM Token */
+#define GLPMCFG_BESL_Msk (0xFUL << GLPMCFG_BESL_Pos) // 0x0000003C
+#define GLPMCFG_BESL GLPMCFG_BESL_Msk // BESL value received with last ACKed LPM Token
#define GLPMCFG_REMWAKE_Pos (6U)
-#define GLPMCFG_REMWAKE_Msk (0x1UL << GLPMCFG_REMWAKE_Pos) // 0x00000040 */
-#define GLPMCFG_REMWAKE GLPMCFG_REMWAKE_Msk // bRemoteWake value received with last ACKed LPM Token */
+#define GLPMCFG_REMWAKE_Msk (0x1UL << GLPMCFG_REMWAKE_Pos) // 0x00000040
+#define GLPMCFG_REMWAKE GLPMCFG_REMWAKE_Msk // bRemoteWake value received with last ACKed LPM Token
#define GLPMCFG_L1SSEN_Pos (7U)
-#define GLPMCFG_L1SSEN_Msk (0x1UL << GLPMCFG_L1SSEN_Pos) // 0x00000080 */
-#define GLPMCFG_L1SSEN GLPMCFG_L1SSEN_Msk // L1 shallow sleep enable */
+#define GLPMCFG_L1SSEN_Msk (0x1UL << GLPMCFG_L1SSEN_Pos) // 0x00000080
+#define GLPMCFG_L1SSEN GLPMCFG_L1SSEN_Msk // L1 shallow sleep enable
#define GLPMCFG_BESLTHRS_Pos (8U)
-#define GLPMCFG_BESLTHRS_Msk (0xFUL << GLPMCFG_BESLTHRS_Pos) // 0x00000F00 */
-#define GLPMCFG_BESLTHRS GLPMCFG_BESLTHRS_Msk // BESL threshold */
+#define GLPMCFG_BESLTHRS_Msk (0xFUL << GLPMCFG_BESLTHRS_Pos) // 0x00000F00
+#define GLPMCFG_BESLTHRS GLPMCFG_BESLTHRS_Msk // BESL threshold
#define GLPMCFG_L1DSEN_Pos (12U)
-#define GLPMCFG_L1DSEN_Msk (0x1UL << GLPMCFG_L1DSEN_Pos) // 0x00001000 */
-#define GLPMCFG_L1DSEN GLPMCFG_L1DSEN_Msk // L1 deep sleep enable */
+#define GLPMCFG_L1DSEN_Msk (0x1UL << GLPMCFG_L1DSEN_Pos) // 0x00001000
+#define GLPMCFG_L1DSEN GLPMCFG_L1DSEN_Msk // L1 deep sleep enable
#define GLPMCFG_LPMRSP_Pos (13U)
-#define GLPMCFG_LPMRSP_Msk (0x3UL << GLPMCFG_LPMRSP_Pos) // 0x00006000 */
-#define GLPMCFG_LPMRSP GLPMCFG_LPMRSP_Msk // LPM response */
+#define GLPMCFG_LPMRSP_Msk (0x3UL << GLPMCFG_LPMRSP_Pos) // 0x00006000
+#define GLPMCFG_LPMRSP GLPMCFG_LPMRSP_Msk // LPM response
#define GLPMCFG_SLPSTS_Pos (15U)
-#define GLPMCFG_SLPSTS_Msk (0x1UL << GLPMCFG_SLPSTS_Pos) // 0x00008000 */
-#define GLPMCFG_SLPSTS GLPMCFG_SLPSTS_Msk // Port sleep status */
+#define GLPMCFG_SLPSTS_Msk (0x1UL << GLPMCFG_SLPSTS_Pos) // 0x00008000
+#define GLPMCFG_SLPSTS GLPMCFG_SLPSTS_Msk // Port sleep status
#define GLPMCFG_L1RSMOK_Pos (16U)
-#define GLPMCFG_L1RSMOK_Msk (0x1UL << GLPMCFG_L1RSMOK_Pos) // 0x00010000 */
-#define GLPMCFG_L1RSMOK GLPMCFG_L1RSMOK_Msk // Sleep State Resume OK */
+#define GLPMCFG_L1RSMOK_Msk (0x1UL << GLPMCFG_L1RSMOK_Pos) // 0x00010000
+#define GLPMCFG_L1RSMOK GLPMCFG_L1RSMOK_Msk // Sleep State Resume OK
#define GLPMCFG_LPMCHIDX_Pos (17U)
-#define GLPMCFG_LPMCHIDX_Msk (0xFUL << GLPMCFG_LPMCHIDX_Pos) // 0x001E0000 */
-#define GLPMCFG_LPMCHIDX GLPMCFG_LPMCHIDX_Msk // LPM Channel Index */
+#define GLPMCFG_LPMCHIDX_Msk (0xFUL << GLPMCFG_LPMCHIDX_Pos) // 0x001E0000
+#define GLPMCFG_LPMCHIDX GLPMCFG_LPMCHIDX_Msk // LPM Channel Index
#define GLPMCFG_LPMRCNT_Pos (21U)
-#define GLPMCFG_LPMRCNT_Msk (0x7UL << GLPMCFG_LPMRCNT_Pos) // 0x00E00000 */
-#define GLPMCFG_LPMRCNT GLPMCFG_LPMRCNT_Msk // LPM retry count */
+#define GLPMCFG_LPMRCNT_Msk (0x7UL << GLPMCFG_LPMRCNT_Pos) // 0x00E00000
+#define GLPMCFG_LPMRCNT GLPMCFG_LPMRCNT_Msk // LPM retry count
#define GLPMCFG_SNDLPM_Pos (24U)
-#define GLPMCFG_SNDLPM_Msk (0x1UL << GLPMCFG_SNDLPM_Pos) // 0x01000000 */
-#define GLPMCFG_SNDLPM GLPMCFG_SNDLPM_Msk // Send LPM transaction */
+#define GLPMCFG_SNDLPM_Msk (0x1UL << GLPMCFG_SNDLPM_Pos) // 0x01000000
+#define GLPMCFG_SNDLPM GLPMCFG_SNDLPM_Msk // Send LPM transaction
#define GLPMCFG_LPMRCNTSTS_Pos (25U)
-#define GLPMCFG_LPMRCNTSTS_Msk (0x7UL << GLPMCFG_LPMRCNTSTS_Pos) // 0x0E000000 */
-#define GLPMCFG_LPMRCNTSTS GLPMCFG_LPMRCNTSTS_Msk // LPM retry count status */
+#define GLPMCFG_LPMRCNTSTS_Msk (0x7UL << GLPMCFG_LPMRCNTSTS_Pos) // 0x0E000000
+#define GLPMCFG_LPMRCNTSTS GLPMCFG_LPMRCNTSTS_Msk // LPM retry count status
#define GLPMCFG_ENBESL_Pos (28U)
-#define GLPMCFG_ENBESL_Msk (0x1UL << GLPMCFG_ENBESL_Pos) // 0x10000000 */
-#define GLPMCFG_ENBESL GLPMCFG_ENBESL_Msk // Enable best effort service latency */
+#define GLPMCFG_ENBESL_Msk (0x1UL << GLPMCFG_ENBESL_Pos) // 0x10000000
+#define GLPMCFG_ENBESL GLPMCFG_ENBESL_Msk // Enable best effort service latency
/******************** Bit definition for DIEPEACHMSK1 register ********************/
#define DIEPEACHMSK1_XFRCM_Pos (0U)
-#define DIEPEACHMSK1_XFRCM_Msk (0x1UL << DIEPEACHMSK1_XFRCM_Pos) // 0x00000001 */
-#define DIEPEACHMSK1_XFRCM DIEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask */
+#define DIEPEACHMSK1_XFRCM_Msk (0x1UL << DIEPEACHMSK1_XFRCM_Pos) // 0x00000001
+#define DIEPEACHMSK1_XFRCM DIEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask
#define DIEPEACHMSK1_EPDM_Pos (1U)
-#define DIEPEACHMSK1_EPDM_Msk (0x1UL << DIEPEACHMSK1_EPDM_Pos) // 0x00000002 */
-#define DIEPEACHMSK1_EPDM DIEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask */
+#define DIEPEACHMSK1_EPDM_Msk (0x1UL << DIEPEACHMSK1_EPDM_Pos) // 0x00000002
+#define DIEPEACHMSK1_EPDM DIEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask
#define DIEPEACHMSK1_TOM_Pos (3U)
-#define DIEPEACHMSK1_TOM_Msk (0x1UL << DIEPEACHMSK1_TOM_Pos) // 0x00000008 */
-#define DIEPEACHMSK1_TOM DIEPEACHMSK1_TOM_Msk // Timeout condition mask (nonisochronous endpoints) */
+#define DIEPEACHMSK1_TOM_Msk (0x1UL << DIEPEACHMSK1_TOM_Pos) // 0x00000008
+#define DIEPEACHMSK1_TOM DIEPEACHMSK1_TOM_Msk // Timeout condition mask (nonisochronous endpoints)
#define DIEPEACHMSK1_ITTXFEMSK_Pos (4U)
-#define DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DIEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 */
-#define DIEPEACHMSK1_ITTXFEMSK DIEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */
+#define DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DIEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010
+#define DIEPEACHMSK1_ITTXFEMSK DIEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask
#define DIEPEACHMSK1_INEPNMM_Pos (5U)
-#define DIEPEACHMSK1_INEPNMM_Msk (0x1UL << DIEPEACHMSK1_INEPNMM_Pos) // 0x00000020 */
-#define DIEPEACHMSK1_INEPNMM DIEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask */
+#define DIEPEACHMSK1_INEPNMM_Msk (0x1UL << DIEPEACHMSK1_INEPNMM_Pos) // 0x00000020
+#define DIEPEACHMSK1_INEPNMM DIEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask
#define DIEPEACHMSK1_INEPNEM_Pos (6U)
-#define DIEPEACHMSK1_INEPNEM_Msk (0x1UL << DIEPEACHMSK1_INEPNEM_Pos) // 0x00000040 */
-#define DIEPEACHMSK1_INEPNEM DIEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask */
+#define DIEPEACHMSK1_INEPNEM_Msk (0x1UL << DIEPEACHMSK1_INEPNEM_Pos) // 0x00000040
+#define DIEPEACHMSK1_INEPNEM DIEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask
#define DIEPEACHMSK1_TXFURM_Pos (8U)
-#define DIEPEACHMSK1_TXFURM_Msk (0x1UL << DIEPEACHMSK1_TXFURM_Pos) // 0x00000100 */
-#define DIEPEACHMSK1_TXFURM DIEPEACHMSK1_TXFURM_Msk // FIFO underrun mask */
+#define DIEPEACHMSK1_TXFURM_Msk (0x1UL << DIEPEACHMSK1_TXFURM_Pos) // 0x00000100
+#define DIEPEACHMSK1_TXFURM DIEPEACHMSK1_TXFURM_Msk // FIFO underrun mask
#define DIEPEACHMSK1_BIM_Pos (9U)
-#define DIEPEACHMSK1_BIM_Msk (0x1UL << DIEPEACHMSK1_BIM_Pos) // 0x00000200 */
-#define DIEPEACHMSK1_BIM DIEPEACHMSK1_BIM_Msk // BNA interrupt mask */
+#define DIEPEACHMSK1_BIM_Msk (0x1UL << DIEPEACHMSK1_BIM_Pos) // 0x00000200
+#define DIEPEACHMSK1_BIM DIEPEACHMSK1_BIM_Msk // BNA interrupt mask
#define DIEPEACHMSK1_NAKM_Pos (13U)
-#define DIEPEACHMSK1_NAKM_Msk (0x1UL << DIEPEACHMSK1_NAKM_Pos) // 0x00002000 */
-#define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask */
+#define DIEPEACHMSK1_NAKM_Msk (0x1UL << DIEPEACHMSK1_NAKM_Pos) // 0x00002000
+#define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask
/******************** Bit definition for HPRT register ********************/
#define HPRT_PCSTS_Pos (0U)
-#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001 */
-#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status */
+#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001
+#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status
#define HPRT_PCDET_Pos (1U)
-#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002 */
-#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected */
+#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002
+#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected
#define HPRT_PENA_Pos (2U)
-#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004 */
-#define HPRT_PENA HPRT_PENA_Msk // Port enable */
+#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004
+#define HPRT_PENA HPRT_PENA_Msk // Port enable
#define HPRT_PENCHNG_Pos (3U)
-#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008 */
-#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change */
+#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008
+#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change
#define HPRT_POCA_Pos (4U)
-#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010 */
-#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active */
+#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010
+#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active
#define HPRT_POCCHNG_Pos (5U)
-#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020 */
-#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change */
+#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020
+#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change
#define HPRT_PRES_Pos (6U)
-#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040 */
-#define HPRT_PRES HPRT_PRES_Msk // Port resume */
+#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040
+#define HPRT_PRES HPRT_PRES_Msk // Port resume
#define HPRT_PSUSP_Pos (7U)
-#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080 */
-#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend */
+#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080
+#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend
#define HPRT_PRST_Pos (8U)
-#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100 */
-#define HPRT_PRST HPRT_PRST_Msk // Port reset */
+#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100
+#define HPRT_PRST HPRT_PRST_Msk // Port reset
#define HPRT_PLSTS_Pos (10U)
-#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00 */
-#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status */
-#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400 */
-#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800 */
+#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00
+#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status
+#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400
+#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800
#define HPRT_PPWR_Pos (12U)
-#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000 */
-#define HPRT_PPWR HPRT_PPWR_Msk // Port power */
+#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000
+#define HPRT_PPWR HPRT_PPWR_Msk // Port power
#define HPRT_PTCTL_Pos (13U)
-#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000 */
-#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control */
-#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000 */
-#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000 */
-#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000 */
-#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000 */
+#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000
+#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control
+#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000
+#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000
+#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000
+#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000
#define HPRT_PSPD_Pos (17U)
-#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000 */
-#define HPRT_PSPD HPRT_PSPD_Msk // Port speed */
-#define HPRT_PSPD_0 (0x1UL << HPRT_PSPD_Pos) // 0x00020000 */
-#define HPRT_PSPD_1 (0x2UL << HPRT_PSPD_Pos) // 0x00040000 */
+#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000
+#define HPRT_PSPD HPRT_PSPD_Msk // Port speed
+#define HPRT_PSPD_0 (0x1UL << HPRT_PSPD_Pos) // 0x00020000
+#define HPRT_PSPD_1 (0x2UL << HPRT_PSPD_Pos) // 0x00040000
/******************** Bit definition for DOEPEACHMSK1 register ********************/
#define DOEPEACHMSK1_XFRCM_Pos (0U)
-#define DOEPEACHMSK1_XFRCM_Msk (0x1UL << DOEPEACHMSK1_XFRCM_Pos) // 0x00000001 */
-#define DOEPEACHMSK1_XFRCM DOEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask */
+#define DOEPEACHMSK1_XFRCM_Msk (0x1UL << DOEPEACHMSK1_XFRCM_Pos) // 0x00000001
+#define DOEPEACHMSK1_XFRCM DOEPEACHMSK1_XFRCM_Msk // Transfer completed interrupt mask
#define DOEPEACHMSK1_EPDM_Pos (1U)
-#define DOEPEACHMSK1_EPDM_Msk (0x1UL << DOEPEACHMSK1_EPDM_Pos) // 0x00000002 */
-#define DOEPEACHMSK1_EPDM DOEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask */
+#define DOEPEACHMSK1_EPDM_Msk (0x1UL << DOEPEACHMSK1_EPDM_Pos) // 0x00000002
+#define DOEPEACHMSK1_EPDM DOEPEACHMSK1_EPDM_Msk // Endpoint disabled interrupt mask
#define DOEPEACHMSK1_TOM_Pos (3U)
-#define DOEPEACHMSK1_TOM_Msk (0x1UL << DOEPEACHMSK1_TOM_Pos) // 0x00000008 */
-#define DOEPEACHMSK1_TOM DOEPEACHMSK1_TOM_Msk // Timeout condition mask */
+#define DOEPEACHMSK1_TOM_Msk (0x1UL << DOEPEACHMSK1_TOM_Pos) // 0x00000008
+#define DOEPEACHMSK1_TOM DOEPEACHMSK1_TOM_Msk // Timeout condition mask
#define DOEPEACHMSK1_ITTXFEMSK_Pos (4U)
-#define DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DOEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010 */
-#define DOEPEACHMSK1_ITTXFEMSK DOEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask */
+#define DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << DOEPEACHMSK1_ITTXFEMSK_Pos) // 0x00000010
+#define DOEPEACHMSK1_ITTXFEMSK DOEPEACHMSK1_ITTXFEMSK_Msk // IN token received when TxFIFO empty mask
#define DOEPEACHMSK1_INEPNMM_Pos (5U)
-#define DOEPEACHMSK1_INEPNMM_Msk (0x1UL << DOEPEACHMSK1_INEPNMM_Pos) // 0x00000020 */
-#define DOEPEACHMSK1_INEPNMM DOEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask */
+#define DOEPEACHMSK1_INEPNMM_Msk (0x1UL << DOEPEACHMSK1_INEPNMM_Pos) // 0x00000020
+#define DOEPEACHMSK1_INEPNMM DOEPEACHMSK1_INEPNMM_Msk // IN token received with EP mismatch mask
#define DOEPEACHMSK1_INEPNEM_Pos (6U)
-#define DOEPEACHMSK1_INEPNEM_Msk (0x1UL << DOEPEACHMSK1_INEPNEM_Pos) // 0x00000040 */
-#define DOEPEACHMSK1_INEPNEM DOEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask */
+#define DOEPEACHMSK1_INEPNEM_Msk (0x1UL << DOEPEACHMSK1_INEPNEM_Pos) // 0x00000040
+#define DOEPEACHMSK1_INEPNEM DOEPEACHMSK1_INEPNEM_Msk // IN endpoint NAK effective mask
#define DOEPEACHMSK1_TXFURM_Pos (8U)
-#define DOEPEACHMSK1_TXFURM_Msk (0x1UL << DOEPEACHMSK1_TXFURM_Pos) // 0x00000100 */
-#define DOEPEACHMSK1_TXFURM DOEPEACHMSK1_TXFURM_Msk // OUT packet error mask */
+#define DOEPEACHMSK1_TXFURM_Msk (0x1UL << DOEPEACHMSK1_TXFURM_Pos) // 0x00000100
+#define DOEPEACHMSK1_TXFURM DOEPEACHMSK1_TXFURM_Msk // OUT packet error mask
#define DOEPEACHMSK1_BIM_Pos (9U)
-#define DOEPEACHMSK1_BIM_Msk (0x1UL << DOEPEACHMSK1_BIM_Pos) // 0x00000200 */
-#define DOEPEACHMSK1_BIM DOEPEACHMSK1_BIM_Msk // BNA interrupt mask */
+#define DOEPEACHMSK1_BIM_Msk (0x1UL << DOEPEACHMSK1_BIM_Pos) // 0x00000200
+#define DOEPEACHMSK1_BIM DOEPEACHMSK1_BIM_Msk // BNA interrupt mask
#define DOEPEACHMSK1_BERRM_Pos (12U)
-#define DOEPEACHMSK1_BERRM_Msk (0x1UL << DOEPEACHMSK1_BERRM_Pos) // 0x00001000 */
-#define DOEPEACHMSK1_BERRM DOEPEACHMSK1_BERRM_Msk // Bubble error interrupt mask */
+#define DOEPEACHMSK1_BERRM_Msk (0x1UL << DOEPEACHMSK1_BERRM_Pos) // 0x00001000
+#define DOEPEACHMSK1_BERRM DOEPEACHMSK1_BERRM_Msk // Bubble error interrupt mask
#define DOEPEACHMSK1_NAKM_Pos (13U)
-#define DOEPEACHMSK1_NAKM_Msk (0x1UL << DOEPEACHMSK1_NAKM_Pos) // 0x00002000 */
-#define DOEPEACHMSK1_NAKM DOEPEACHMSK1_NAKM_Msk // NAK interrupt mask */
+#define DOEPEACHMSK1_NAKM_Msk (0x1UL << DOEPEACHMSK1_NAKM_Pos) // 0x00002000
+#define DOEPEACHMSK1_NAKM DOEPEACHMSK1_NAKM_Msk // NAK interrupt mask
#define DOEPEACHMSK1_NYETM_Pos (14U)
-#define DOEPEACHMSK1_NYETM_Msk (0x1UL << DOEPEACHMSK1_NYETM_Pos) // 0x00004000 */
-#define DOEPEACHMSK1_NYETM DOEPEACHMSK1_NYETM_Msk // NYET interrupt mask */
+#define DOEPEACHMSK1_NYETM_Msk (0x1UL << DOEPEACHMSK1_NYETM_Pos) // 0x00004000
+#define DOEPEACHMSK1_NYETM DOEPEACHMSK1_NYETM_Msk // NYET interrupt mask
/******************** Bit definition for HPTXFSIZ register ********************/
#define HPTXFSIZ_PTXSA_Pos (0U)
-#define HPTXFSIZ_PTXSA_Msk (0xFFFFUL << HPTXFSIZ_PTXSA_Pos) // 0x0000FFFF */
-#define HPTXFSIZ_PTXSA HPTXFSIZ_PTXSA_Msk // Host periodic TxFIFO start address */
+#define HPTXFSIZ_PTXSA_Msk (0xFFFFUL << HPTXFSIZ_PTXSA_Pos) // 0x0000FFFF
+#define HPTXFSIZ_PTXSA HPTXFSIZ_PTXSA_Msk // Host periodic TxFIFO start address
#define HPTXFSIZ_PTXFD_Pos (16U)
-#define HPTXFSIZ_PTXFD_Msk (0xFFFFUL << HPTXFSIZ_PTXFD_Pos) // 0xFFFF0000 */
-#define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth */
+#define HPTXFSIZ_PTXFD_Msk (0xFFFFUL << HPTXFSIZ_PTXFD_Pos) // 0xFFFF0000
+#define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth
/******************** Bit definition for DIEPCTL register ********************/
#define DIEPCTL_MPSIZ_Pos (0U)
-#define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF */
-#define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size */
+#define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF
+#define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size
#define DIEPCTL_USBAEP_Pos (15U)
-#define DIEPCTL_USBAEP_Msk (0x1UL << DIEPCTL_USBAEP_Pos) // 0x00008000 */
-#define DIEPCTL_USBAEP DIEPCTL_USBAEP_Msk // USB active endpoint */
+#define DIEPCTL_USBAEP_Msk (0x1UL << DIEPCTL_USBAEP_Pos) // 0x00008000
+#define DIEPCTL_USBAEP DIEPCTL_USBAEP_Msk // USB active endpoint
#define DIEPCTL_EONUM_DPID_Pos (16U)
-#define DIEPCTL_EONUM_DPID_Msk (0x1UL << DIEPCTL_EONUM_DPID_Pos) // 0x00010000 */
-#define DIEPCTL_EONUM_DPID DIEPCTL_EONUM_DPID_Msk // Even/odd frame */
+#define DIEPCTL_EONUM_DPID_Msk (0x1UL << DIEPCTL_EONUM_DPID_Pos) // 0x00010000
+#define DIEPCTL_EONUM_DPID DIEPCTL_EONUM_DPID_Msk // Even/odd frame
#define DIEPCTL_NAKSTS_Pos (17U)
-#define DIEPCTL_NAKSTS_Msk (0x1UL << DIEPCTL_NAKSTS_Pos) // 0x00020000 */
-#define DIEPCTL_NAKSTS DIEPCTL_NAKSTS_Msk // NAK status */
+#define DIEPCTL_NAKSTS_Msk (0x1UL << DIEPCTL_NAKSTS_Pos) // 0x00020000
+#define DIEPCTL_NAKSTS DIEPCTL_NAKSTS_Msk // NAK status
#define DIEPCTL_EPTYP_Pos (18U)
-#define DIEPCTL_EPTYP_Msk (0x3UL << DIEPCTL_EPTYP_Pos) // 0x000C0000 */
-#define DIEPCTL_EPTYP DIEPCTL_EPTYP_Msk // Endpoint type */
-#define DIEPCTL_EPTYP_0 (0x1UL << DIEPCTL_EPTYP_Pos) // 0x00040000 */
-#define DIEPCTL_EPTYP_1 (0x2UL << DIEPCTL_EPTYP_Pos) // 0x00080000 */
+#define DIEPCTL_EPTYP_Msk (0x3UL << DIEPCTL_EPTYP_Pos) // 0x000C0000
+#define DIEPCTL_EPTYP DIEPCTL_EPTYP_Msk // Endpoint type
+#define DIEPCTL_EPTYP_0 (0x1UL << DIEPCTL_EPTYP_Pos) // 0x00040000
+#define DIEPCTL_EPTYP_1 (0x2UL << DIEPCTL_EPTYP_Pos) // 0x00080000
#define DIEPCTL_STALL_Pos (21U)
-#define DIEPCTL_STALL_Msk (0x1UL << DIEPCTL_STALL_Pos) // 0x00200000 */
-#define DIEPCTL_STALL DIEPCTL_STALL_Msk // STALL handshake */
+#define DIEPCTL_STALL_Msk (0x1UL << DIEPCTL_STALL_Pos) // 0x00200000
+#define DIEPCTL_STALL DIEPCTL_STALL_Msk // STALL handshake
#define DIEPCTL_TXFNUM_Pos (22U)
-#define DIEPCTL_TXFNUM_Msk (0xFUL << DIEPCTL_TXFNUM_Pos) // 0x03C00000 */
-#define DIEPCTL_TXFNUM DIEPCTL_TXFNUM_Msk // TxFIFO number */
-#define DIEPCTL_TXFNUM_0 (0x1UL << DIEPCTL_TXFNUM_Pos) // 0x00400000 */
-#define DIEPCTL_TXFNUM_1 (0x2UL << DIEPCTL_TXFNUM_Pos) // 0x00800000 */
-#define DIEPCTL_TXFNUM_2 (0x4UL << DIEPCTL_TXFNUM_Pos) // 0x01000000 */
-#define DIEPCTL_TXFNUM_3 (0x8UL << DIEPCTL_TXFNUM_Pos) // 0x02000000 */
+#define DIEPCTL_TXFNUM_Msk (0xFUL << DIEPCTL_TXFNUM_Pos) // 0x03C00000
+#define DIEPCTL_TXFNUM DIEPCTL_TXFNUM_Msk // TxFIFO number
+#define DIEPCTL_TXFNUM_0 (0x1UL << DIEPCTL_TXFNUM_Pos) // 0x00400000
+#define DIEPCTL_TXFNUM_1 (0x2UL << DIEPCTL_TXFNUM_Pos) // 0x00800000
+#define DIEPCTL_TXFNUM_2 (0x4UL << DIEPCTL_TXFNUM_Pos) // 0x01000000
+#define DIEPCTL_TXFNUM_3 (0x8UL << DIEPCTL_TXFNUM_Pos) // 0x02000000
#define DIEPCTL_CNAK_Pos (26U)
-#define DIEPCTL_CNAK_Msk (0x1UL << DIEPCTL_CNAK_Pos) // 0x04000000 */
-#define DIEPCTL_CNAK DIEPCTL_CNAK_Msk // Clear NAK */
+#define DIEPCTL_CNAK_Msk (0x1UL << DIEPCTL_CNAK_Pos) // 0x04000000
+#define DIEPCTL_CNAK DIEPCTL_CNAK_Msk // Clear NAK
#define DIEPCTL_SNAK_Pos (27U)
-#define DIEPCTL_SNAK_Msk (0x1UL << DIEPCTL_SNAK_Pos) // 0x08000000 */
-#define DIEPCTL_SNAK DIEPCTL_SNAK_Msk // Set NAK */
+#define DIEPCTL_SNAK_Msk (0x1UL << DIEPCTL_SNAK_Pos) // 0x08000000
+#define DIEPCTL_SNAK DIEPCTL_SNAK_Msk // Set NAK
#define DIEPCTL_SD0PID_SEVNFRM_Pos (28U)
-#define DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DIEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 */
-#define DIEPCTL_SD0PID_SEVNFRM DIEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID */
+#define DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DIEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000
+#define DIEPCTL_SD0PID_SEVNFRM DIEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID
#define DIEPCTL_SODDFRM_Pos (29U)
-#define DIEPCTL_SODDFRM_Msk (0x1UL << DIEPCTL_SODDFRM_Pos) // 0x20000000 */
-#define DIEPCTL_SODDFRM DIEPCTL_SODDFRM_Msk // Set odd frame */
+#define DIEPCTL_SODDFRM_Msk (0x1UL << DIEPCTL_SODDFRM_Pos) // 0x20000000
+#define DIEPCTL_SODDFRM DIEPCTL_SODDFRM_Msk // Set odd frame
#define DIEPCTL_EPDIS_Pos (30U)
-#define DIEPCTL_EPDIS_Msk (0x1UL << DIEPCTL_EPDIS_Pos) // 0x40000000 */
-#define DIEPCTL_EPDIS DIEPCTL_EPDIS_Msk // Endpoint disable */
+#define DIEPCTL_EPDIS_Msk (0x1UL << DIEPCTL_EPDIS_Pos) // 0x40000000
+#define DIEPCTL_EPDIS DIEPCTL_EPDIS_Msk // Endpoint disable
#define DIEPCTL_EPENA_Pos (31U)
-#define DIEPCTL_EPENA_Msk (0x1UL << DIEPCTL_EPENA_Pos) // 0x80000000 */
-#define DIEPCTL_EPENA DIEPCTL_EPENA_Msk // Endpoint enable */
+#define DIEPCTL_EPENA_Msk (0x1UL << DIEPCTL_EPENA_Pos) // 0x80000000
+#define DIEPCTL_EPENA DIEPCTL_EPENA_Msk // Endpoint enable
/******************** Bit definition for HCCHAR register ********************/
#define HCCHAR_MPSIZ_Pos (0U)
-#define HCCHAR_MPSIZ_Msk (0x7FFUL << HCCHAR_MPSIZ_Pos) // 0x000007FF */
-#define HCCHAR_MPSIZ HCCHAR_MPSIZ_Msk // Maximum packet size */
+#define HCCHAR_MPSIZ_Msk (0x7FFUL << HCCHAR_MPSIZ_Pos) // 0x000007FF
+#define HCCHAR_MPSIZ HCCHAR_MPSIZ_Msk // Maximum packet size
#define HCCHAR_EPNUM_Pos (11U)
-#define HCCHAR_EPNUM_Msk (0xFUL << HCCHAR_EPNUM_Pos) // 0x00007800 */
-#define HCCHAR_EPNUM HCCHAR_EPNUM_Msk // Endpoint number */
-#define HCCHAR_EPNUM_0 (0x1UL << HCCHAR_EPNUM_Pos) // 0x00000800 */
-#define HCCHAR_EPNUM_1 (0x2UL << HCCHAR_EPNUM_Pos) // 0x00001000 */
-#define HCCHAR_EPNUM_2 (0x4UL << HCCHAR_EPNUM_Pos) // 0x00002000 */
-#define HCCHAR_EPNUM_3 (0x8UL << HCCHAR_EPNUM_Pos) // 0x00004000 */
+#define HCCHAR_EPNUM_Msk (0xFUL << HCCHAR_EPNUM_Pos) // 0x00007800
+#define HCCHAR_EPNUM HCCHAR_EPNUM_Msk // Endpoint number
+#define HCCHAR_EPNUM_0 (0x1UL << HCCHAR_EPNUM_Pos) // 0x00000800
+#define HCCHAR_EPNUM_1 (0x2UL << HCCHAR_EPNUM_Pos) // 0x00001000
+#define HCCHAR_EPNUM_2 (0x4UL << HCCHAR_EPNUM_Pos) // 0x00002000
+#define HCCHAR_EPNUM_3 (0x8UL << HCCHAR_EPNUM_Pos) // 0x00004000
#define HCCHAR_EPDIR_Pos (15U)
-#define HCCHAR_EPDIR_Msk (0x1UL << HCCHAR_EPDIR_Pos) // 0x00008000 */
-#define HCCHAR_EPDIR HCCHAR_EPDIR_Msk // Endpoint direction */
+#define HCCHAR_EPDIR_Msk (0x1UL << HCCHAR_EPDIR_Pos) // 0x00008000
+#define HCCHAR_EPDIR HCCHAR_EPDIR_Msk // Endpoint direction
#define HCCHAR_LSDEV_Pos (17U)
-#define HCCHAR_LSDEV_Msk (0x1UL << HCCHAR_LSDEV_Pos) // 0x00020000 */
-#define HCCHAR_LSDEV HCCHAR_LSDEV_Msk // Low-speed device */
+#define HCCHAR_LSDEV_Msk (0x1UL << HCCHAR_LSDEV_Pos) // 0x00020000
+#define HCCHAR_LSDEV HCCHAR_LSDEV_Msk // Low-speed device
#define HCCHAR_EPTYP_Pos (18U)
-#define HCCHAR_EPTYP_Msk (0x3UL << HCCHAR_EPTYP_Pos) // 0x000C0000 */
-#define HCCHAR_EPTYP HCCHAR_EPTYP_Msk // Endpoint type */
-#define HCCHAR_EPTYP_0 (0x1UL << HCCHAR_EPTYP_Pos) // 0x00040000 */
-#define HCCHAR_EPTYP_1 (0x2UL << HCCHAR_EPTYP_Pos) // 0x00080000 */
+#define HCCHAR_EPTYP_Msk (0x3UL << HCCHAR_EPTYP_Pos) // 0x000C0000
+#define HCCHAR_EPTYP HCCHAR_EPTYP_Msk // Endpoint type
+#define HCCHAR_EPTYP_0 (0x1UL << HCCHAR_EPTYP_Pos) // 0x00040000
+#define HCCHAR_EPTYP_1 (0x2UL << HCCHAR_EPTYP_Pos) // 0x00080000
#define HCCHAR_MC_Pos (20U)
-#define HCCHAR_MC_Msk (0x3UL << HCCHAR_MC_Pos) // 0x00300000 */
-#define HCCHAR_MC HCCHAR_MC_Msk // Multi Count (MC) / Error Count (EC) */
-#define HCCHAR_MC_0 (0x1UL << HCCHAR_MC_Pos) // 0x00100000 */
-#define HCCHAR_MC_1 (0x2UL << HCCHAR_MC_Pos) // 0x00200000 */
+#define HCCHAR_MC_Msk (0x3UL << HCCHAR_MC_Pos) // 0x00300000
+#define HCCHAR_MC HCCHAR_MC_Msk // Multi Count (MC) / Error Count (EC)
+#define HCCHAR_MC_0 (0x1UL << HCCHAR_MC_Pos) // 0x00100000
+#define HCCHAR_MC_1 (0x2UL << HCCHAR_MC_Pos) // 0x00200000
#define HCCHAR_DAD_Pos (22U)
-#define HCCHAR_DAD_Msk (0x7FUL << HCCHAR_DAD_Pos) // 0x1FC00000 */
-#define HCCHAR_DAD HCCHAR_DAD_Msk // Device address */
-#define HCCHAR_DAD_0 (0x01UL << HCCHAR_DAD_Pos) // 0x00400000 */
-#define HCCHAR_DAD_1 (0x02UL << HCCHAR_DAD_Pos) // 0x00800000 */
-#define HCCHAR_DAD_2 (0x04UL << HCCHAR_DAD_Pos) // 0x01000000 */
-#define HCCHAR_DAD_3 (0x08UL << HCCHAR_DAD_Pos) // 0x02000000 */
-#define HCCHAR_DAD_4 (0x10UL << HCCHAR_DAD_Pos) // 0x04000000 */
-#define HCCHAR_DAD_5 (0x20UL << HCCHAR_DAD_Pos) // 0x08000000 */
-#define HCCHAR_DAD_6 (0x40UL << HCCHAR_DAD_Pos) // 0x10000000 */
+#define HCCHAR_DAD_Msk (0x7FUL << HCCHAR_DAD_Pos) // 0x1FC00000
+#define HCCHAR_DAD HCCHAR_DAD_Msk // Device address
+#define HCCHAR_DAD_0 (0x01UL << HCCHAR_DAD_Pos) // 0x00400000
+#define HCCHAR_DAD_1 (0x02UL << HCCHAR_DAD_Pos) // 0x00800000
+#define HCCHAR_DAD_2 (0x04UL << HCCHAR_DAD_Pos) // 0x01000000
+#define HCCHAR_DAD_3 (0x08UL << HCCHAR_DAD_Pos) // 0x02000000
+#define HCCHAR_DAD_4 (0x10UL << HCCHAR_DAD_Pos) // 0x04000000
+#define HCCHAR_DAD_5 (0x20UL << HCCHAR_DAD_Pos) // 0x08000000
+#define HCCHAR_DAD_6 (0x40UL << HCCHAR_DAD_Pos) // 0x10000000
#define HCCHAR_ODDFRM_Pos (29U)
-#define HCCHAR_ODDFRM_Msk (0x1UL << HCCHAR_ODDFRM_Pos) // 0x20000000 */
-#define HCCHAR_ODDFRM HCCHAR_ODDFRM_Msk // Odd frame */
+#define HCCHAR_ODDFRM_Msk (0x1UL << HCCHAR_ODDFRM_Pos) // 0x20000000
+#define HCCHAR_ODDFRM HCCHAR_ODDFRM_Msk // Odd frame
#define HCCHAR_CHDIS_Pos (30U)
-#define HCCHAR_CHDIS_Msk (0x1UL << HCCHAR_CHDIS_Pos) // 0x40000000 */
-#define HCCHAR_CHDIS HCCHAR_CHDIS_Msk // Channel disable */
+#define HCCHAR_CHDIS_Msk (0x1UL << HCCHAR_CHDIS_Pos) // 0x40000000
+#define HCCHAR_CHDIS HCCHAR_CHDIS_Msk // Channel disable
#define HCCHAR_CHENA_Pos (31U)
-#define HCCHAR_CHENA_Msk (0x1UL << HCCHAR_CHENA_Pos) // 0x80000000 */
-#define HCCHAR_CHENA HCCHAR_CHENA_Msk // Channel enable */
+#define HCCHAR_CHENA_Msk (0x1UL << HCCHAR_CHENA_Pos) // 0x80000000
+#define HCCHAR_CHENA HCCHAR_CHENA_Msk // Channel enable
/******************** Bit definition for HCSPLT register ********************/
#define HCSPLT_PRTADDR_Pos (0U)
-#define HCSPLT_PRTADDR_Msk (0x7FUL << HCSPLT_PRTADDR_Pos) // 0x0000007F */
-#define HCSPLT_PRTADDR HCSPLT_PRTADDR_Msk // Port address */
-#define HCSPLT_PRTADDR_0 (0x01UL << HCSPLT_PRTADDR_Pos) // 0x00000001 */
-#define HCSPLT_PRTADDR_1 (0x02UL << HCSPLT_PRTADDR_Pos) // 0x00000002 */
-#define HCSPLT_PRTADDR_2 (0x04UL << HCSPLT_PRTADDR_Pos) // 0x00000004 */
-#define HCSPLT_PRTADDR_3 (0x08UL << HCSPLT_PRTADDR_Pos) // 0x00000008 */
-#define HCSPLT_PRTADDR_4 (0x10UL << HCSPLT_PRTADDR_Pos) // 0x00000010 */
-#define HCSPLT_PRTADDR_5 (0x20UL << HCSPLT_PRTADDR_Pos) // 0x00000020 */
-#define HCSPLT_PRTADDR_6 (0x40UL << HCSPLT_PRTADDR_Pos) // 0x00000040 */
+#define HCSPLT_PRTADDR_Msk (0x7FUL << HCSPLT_PRTADDR_Pos) // 0x0000007F
+#define HCSPLT_PRTADDR HCSPLT_PRTADDR_Msk // Port address
+#define HCSPLT_PRTADDR_0 (0x01UL << HCSPLT_PRTADDR_Pos) // 0x00000001
+#define HCSPLT_PRTADDR_1 (0x02UL << HCSPLT_PRTADDR_Pos) // 0x00000002
+#define HCSPLT_PRTADDR_2 (0x04UL << HCSPLT_PRTADDR_Pos) // 0x00000004
+#define HCSPLT_PRTADDR_3 (0x08UL << HCSPLT_PRTADDR_Pos) // 0x00000008
+#define HCSPLT_PRTADDR_4 (0x10UL << HCSPLT_PRTADDR_Pos) // 0x00000010
+#define HCSPLT_PRTADDR_5 (0x20UL << HCSPLT_PRTADDR_Pos) // 0x00000020
+#define HCSPLT_PRTADDR_6 (0x40UL << HCSPLT_PRTADDR_Pos) // 0x00000040
#define HCSPLT_HUBADDR_Pos (7U)
-#define HCSPLT_HUBADDR_Msk (0x7FUL << HCSPLT_HUBADDR_Pos) // 0x00003F80 */
-#define HCSPLT_HUBADDR HCSPLT_HUBADDR_Msk // Hub address */
-#define HCSPLT_HUBADDR_0 (0x01UL << HCSPLT_HUBADDR_Pos) // 0x00000080 */
-#define HCSPLT_HUBADDR_1 (0x02UL << HCSPLT_HUBADDR_Pos) // 0x00000100 */
-#define HCSPLT_HUBADDR_2 (0x04UL << HCSPLT_HUBADDR_Pos) // 0x00000200 */
-#define HCSPLT_HUBADDR_3 (0x08UL << HCSPLT_HUBADDR_Pos) // 0x00000400 */
-#define HCSPLT_HUBADDR_4 (0x10UL << HCSPLT_HUBADDR_Pos) // 0x00000800 */
-#define HCSPLT_HUBADDR_5 (0x20UL << HCSPLT_HUBADDR_Pos) // 0x00001000 */
-#define HCSPLT_HUBADDR_6 (0x40UL << HCSPLT_HUBADDR_Pos) // 0x00002000 */
+#define HCSPLT_HUBADDR_Msk (0x7FUL << HCSPLT_HUBADDR_Pos) // 0x00003F80
+#define HCSPLT_HUBADDR HCSPLT_HUBADDR_Msk // Hub address
+#define HCSPLT_HUBADDR_0 (0x01UL << HCSPLT_HUBADDR_Pos) // 0x00000080
+#define HCSPLT_HUBADDR_1 (0x02UL << HCSPLT_HUBADDR_Pos) // 0x00000100
+#define HCSPLT_HUBADDR_2 (0x04UL << HCSPLT_HUBADDR_Pos) // 0x00000200
+#define HCSPLT_HUBADDR_3 (0x08UL << HCSPLT_HUBADDR_Pos) // 0x00000400
+#define HCSPLT_HUBADDR_4 (0x10UL << HCSPLT_HUBADDR_Pos) // 0x00000800
+#define HCSPLT_HUBADDR_5 (0x20UL << HCSPLT_HUBADDR_Pos) // 0x00001000
+#define HCSPLT_HUBADDR_6 (0x40UL << HCSPLT_HUBADDR_Pos) // 0x00002000
#define HCSPLT_XACTPOS_Pos (14U)
-#define HCSPLT_XACTPOS_Msk (0x3UL << HCSPLT_XACTPOS_Pos) // 0x0000C000 */
-#define HCSPLT_XACTPOS HCSPLT_XACTPOS_Msk // XACTPOS */
-#define HCSPLT_XACTPOS_0 (0x1UL << HCSPLT_XACTPOS_Pos) // 0x00004000 */
-#define HCSPLT_XACTPOS_1 (0x2UL << HCSPLT_XACTPOS_Pos) // 0x00008000 */
+#define HCSPLT_XACTPOS_Msk (0x3UL << HCSPLT_XACTPOS_Pos) // 0x0000C000
+#define HCSPLT_XACTPOS HCSPLT_XACTPOS_Msk // XACTPOS
+#define HCSPLT_XACTPOS_0 (0x1UL << HCSPLT_XACTPOS_Pos) // 0x00004000
+#define HCSPLT_XACTPOS_1 (0x2UL << HCSPLT_XACTPOS_Pos) // 0x00008000
#define HCSPLT_COMPLSPLT_Pos (16U)
-#define HCSPLT_COMPLSPLT_Msk (0x1UL << HCSPLT_COMPLSPLT_Pos) // 0x00010000 */
-#define HCSPLT_COMPLSPLT HCSPLT_COMPLSPLT_Msk // Do complete split */
+#define HCSPLT_COMPLSPLT_Msk (0x1UL << HCSPLT_COMPLSPLT_Pos) // 0x00010000
+#define HCSPLT_COMPLSPLT HCSPLT_COMPLSPLT_Msk // Do complete split
#define HCSPLT_SPLITEN_Pos (31U)
-#define HCSPLT_SPLITEN_Msk (0x1UL << HCSPLT_SPLITEN_Pos) // 0x80000000 */
-#define HCSPLT_SPLITEN HCSPLT_SPLITEN_Msk // Split enable */
+#define HCSPLT_SPLITEN_Msk (0x1UL << HCSPLT_SPLITEN_Pos) // 0x80000000
+#define HCSPLT_SPLITEN HCSPLT_SPLITEN_Msk // Split enable
/******************** Bit definition for HCINT register ********************/
#define HCINT_XFRC_Pos (0U)
-#define HCINT_XFRC_Msk (0x1UL << HCINT_XFRC_Pos) // 0x00000001 */
-#define HCINT_XFRC HCINT_XFRC_Msk // Transfer completed */
+#define HCINT_XFRC_Msk (0x1UL << HCINT_XFRC_Pos) // 0x00000001
+#define HCINT_XFRC HCINT_XFRC_Msk // Transfer completed
#define HCINT_CHH_Pos (1U)
-#define HCINT_CHH_Msk (0x1UL << HCINT_CHH_Pos) // 0x00000002 */
-#define HCINT_CHH HCINT_CHH_Msk // Channel halted */
+#define HCINT_CHH_Msk (0x1UL << HCINT_CHH_Pos) // 0x00000002
+#define HCINT_CHH HCINT_CHH_Msk // Channel halted
#define HCINT_AHBERR_Pos (2U)
-#define HCINT_AHBERR_Msk (0x1UL << HCINT_AHBERR_Pos) // 0x00000004 */
-#define HCINT_AHBERR HCINT_AHBERR_Msk // AHB error */
+#define HCINT_AHBERR_Msk (0x1UL << HCINT_AHBERR_Pos) // 0x00000004
+#define HCINT_AHBERR HCINT_AHBERR_Msk // AHB error
#define HCINT_STALL_Pos (3U)
-#define HCINT_STALL_Msk (0x1UL << HCINT_STALL_Pos) // 0x00000008 */
-#define HCINT_STALL HCINT_STALL_Msk // STALL response received interrupt */
+#define HCINT_STALL_Msk (0x1UL << HCINT_STALL_Pos) // 0x00000008
+#define HCINT_STALL HCINT_STALL_Msk // STALL response received interrupt
#define HCINT_NAK_Pos (4U)
-#define HCINT_NAK_Msk (0x1UL << HCINT_NAK_Pos) // 0x00000010 */
-#define HCINT_NAK HCINT_NAK_Msk // NAK response received interrupt */
+#define HCINT_NAK_Msk (0x1UL << HCINT_NAK_Pos) // 0x00000010
+#define HCINT_NAK HCINT_NAK_Msk // NAK response received interrupt
#define HCINT_ACK_Pos (5U)
-#define HCINT_ACK_Msk (0x1UL << HCINT_ACK_Pos) // 0x00000020 */
-#define HCINT_ACK HCINT_ACK_Msk // ACK response received/transmitted interrupt */
+#define HCINT_ACK_Msk (0x1UL << HCINT_ACK_Pos) // 0x00000020
+#define HCINT_ACK HCINT_ACK_Msk // ACK response received/transmitted interrupt
#define HCINT_NYET_Pos (6U)
-#define HCINT_NYET_Msk (0x1UL << HCINT_NYET_Pos) // 0x00000040 */
-#define HCINT_NYET HCINT_NYET_Msk // Response received interrupt */
+#define HCINT_NYET_Msk (0x1UL << HCINT_NYET_Pos) // 0x00000040
+#define HCINT_NYET HCINT_NYET_Msk // Response received interrupt
#define HCINT_TXERR_Pos (7U)
-#define HCINT_TXERR_Msk (0x1UL << HCINT_TXERR_Pos) // 0x00000080 */
-#define HCINT_TXERR HCINT_TXERR_Msk // Transaction error */
+#define HCINT_TXERR_Msk (0x1UL << HCINT_TXERR_Pos) // 0x00000080
+#define HCINT_TXERR HCINT_TXERR_Msk // Transaction error
#define HCINT_BBERR_Pos (8U)
-#define HCINT_BBERR_Msk (0x1UL << HCINT_BBERR_Pos) // 0x00000100 */
-#define HCINT_BBERR HCINT_BBERR_Msk // Babble error */
+#define HCINT_BBERR_Msk (0x1UL << HCINT_BBERR_Pos) // 0x00000100
+#define HCINT_BBERR HCINT_BBERR_Msk // Babble error
#define HCINT_FRMOR_Pos (9U)
-#define HCINT_FRMOR_Msk (0x1UL << HCINT_FRMOR_Pos) // 0x00000200 */
-#define HCINT_FRMOR HCINT_FRMOR_Msk // Frame overrun */
+#define HCINT_FRMOR_Msk (0x1UL << HCINT_FRMOR_Pos) // 0x00000200
+#define HCINT_FRMOR HCINT_FRMOR_Msk // Frame overrun
#define HCINT_DTERR_Pos (10U)
-#define HCINT_DTERR_Msk (0x1UL << HCINT_DTERR_Pos) // 0x00000400 */
-#define HCINT_DTERR HCINT_DTERR_Msk // Data toggle error */
+#define HCINT_DTERR_Msk (0x1UL << HCINT_DTERR_Pos) // 0x00000400
+#define HCINT_DTERR HCINT_DTERR_Msk // Data toggle error
/******************** Bit definition for DIEPINT register ********************/
#define DIEPINT_XFRC_Pos (0U)
-#define DIEPINT_XFRC_Msk (0x1UL << DIEPINT_XFRC_Pos) // 0x00000001 */
-#define DIEPINT_XFRC DIEPINT_XFRC_Msk // Transfer completed interrupt */
+#define DIEPINT_XFRC_Msk (0x1UL << DIEPINT_XFRC_Pos) // 0x00000001
+#define DIEPINT_XFRC DIEPINT_XFRC_Msk // Transfer completed interrupt
#define DIEPINT_EPDISD_Pos (1U)
-#define DIEPINT_EPDISD_Msk (0x1UL << DIEPINT_EPDISD_Pos) // 0x00000002 */
-#define DIEPINT_EPDISD DIEPINT_EPDISD_Msk // Endpoint disabled interrupt */
+#define DIEPINT_EPDISD_Msk (0x1UL << DIEPINT_EPDISD_Pos) // 0x00000002
+#define DIEPINT_EPDISD DIEPINT_EPDISD_Msk // Endpoint disabled interrupt
#define DIEPINT_AHBERR_Pos (2U)
-#define DIEPINT_AHBERR_Msk (0x1UL << DIEPINT_AHBERR_Pos) // 0x00000004 */
-#define DIEPINT_AHBERR DIEPINT_AHBERR_Msk // AHB Error (AHBErr) during an IN transaction */
+#define DIEPINT_AHBERR_Msk (0x1UL << DIEPINT_AHBERR_Pos) // 0x00000004
+#define DIEPINT_AHBERR DIEPINT_AHBERR_Msk // AHB Error (AHBErr) during an IN transaction
#define DIEPINT_TOC_Pos (3U)
-#define DIEPINT_TOC_Msk (0x1UL << DIEPINT_TOC_Pos) // 0x00000008 */
-#define DIEPINT_TOC DIEPINT_TOC_Msk // Timeout condition */
+#define DIEPINT_TOC_Msk (0x1UL << DIEPINT_TOC_Pos) // 0x00000008
+#define DIEPINT_TOC DIEPINT_TOC_Msk // Timeout condition
#define DIEPINT_ITTXFE_Pos (4U)
-#define DIEPINT_ITTXFE_Msk (0x1UL << DIEPINT_ITTXFE_Pos) // 0x00000010 */
-#define DIEPINT_ITTXFE DIEPINT_ITTXFE_Msk // IN token received when TxFIFO is empty */
+#define DIEPINT_ITTXFE_Msk (0x1UL << DIEPINT_ITTXFE_Pos) // 0x00000010
+#define DIEPINT_ITTXFE DIEPINT_ITTXFE_Msk // IN token received when TxFIFO is empty
#define DIEPINT_INEPNM_Pos (5U)
-#define DIEPINT_INEPNM_Msk (0x1UL << DIEPINT_INEPNM_Pos) // 0x00000020 */
-#define DIEPINT_INEPNM DIEPINT_INEPNM_Msk // IN token received with EP mismatch */
+#define DIEPINT_INEPNM_Msk (0x1UL << DIEPINT_INEPNM_Pos) // 0x00000020
+#define DIEPINT_INEPNM DIEPINT_INEPNM_Msk // IN token received with EP mismatch
#define DIEPINT_INEPNE_Pos (6U)
-#define DIEPINT_INEPNE_Msk (0x1UL << DIEPINT_INEPNE_Pos) // 0x00000040 */
-#define DIEPINT_INEPNE DIEPINT_INEPNE_Msk // IN endpoint NAK effective */
+#define DIEPINT_INEPNE_Msk (0x1UL << DIEPINT_INEPNE_Pos) // 0x00000040
+#define DIEPINT_INEPNE DIEPINT_INEPNE_Msk // IN endpoint NAK effective
#define DIEPINT_TXFE_Pos (7U)
-#define DIEPINT_TXFE_Msk (0x1UL << DIEPINT_TXFE_Pos) // 0x00000080 */
-#define DIEPINT_TXFE DIEPINT_TXFE_Msk // Transmit FIFO empty */
+#define DIEPINT_TXFE_Msk (0x1UL << DIEPINT_TXFE_Pos) // 0x00000080
+#define DIEPINT_TXFE DIEPINT_TXFE_Msk // Transmit FIFO empty
#define DIEPINT_TXFIFOUDRN_Pos (8U)
-#define DIEPINT_TXFIFOUDRN_Msk (0x1UL << DIEPINT_TXFIFOUDRN_Pos) // 0x00000100 */
-#define DIEPINT_TXFIFOUDRN DIEPINT_TXFIFOUDRN_Msk // Transmit Fifo Underrun */
+#define DIEPINT_TXFIFOUDRN_Msk (0x1UL << DIEPINT_TXFIFOUDRN_Pos) // 0x00000100
+#define DIEPINT_TXFIFOUDRN DIEPINT_TXFIFOUDRN_Msk // Transmit Fifo Underrun
#define DIEPINT_BNA_Pos (9U)
-#define DIEPINT_BNA_Msk (0x1UL << DIEPINT_BNA_Pos) // 0x00000200 */
-#define DIEPINT_BNA DIEPINT_BNA_Msk // Buffer not available interrupt */
+#define DIEPINT_BNA_Msk (0x1UL << DIEPINT_BNA_Pos) // 0x00000200
+#define DIEPINT_BNA DIEPINT_BNA_Msk // Buffer not available interrupt
#define DIEPINT_PKTDRPSTS_Pos (11U)
-#define DIEPINT_PKTDRPSTS_Msk (0x1UL << DIEPINT_PKTDRPSTS_Pos) // 0x00000800 */
-#define DIEPINT_PKTDRPSTS DIEPINT_PKTDRPSTS_Msk // Packet dropped status */
+#define DIEPINT_PKTDRPSTS_Msk (0x1UL << DIEPINT_PKTDRPSTS_Pos) // 0x00000800
+#define DIEPINT_PKTDRPSTS DIEPINT_PKTDRPSTS_Msk // Packet dropped status
#define DIEPINT_BERR_Pos (12U)
-#define DIEPINT_BERR_Msk (0x1UL << DIEPINT_BERR_Pos) // 0x00001000 */
-#define DIEPINT_BERR DIEPINT_BERR_Msk // Babble error interrupt */
+#define DIEPINT_BERR_Msk (0x1UL << DIEPINT_BERR_Pos) // 0x00001000
+#define DIEPINT_BERR DIEPINT_BERR_Msk // Babble error interrupt
#define DIEPINT_NAK_Pos (13U)
-#define DIEPINT_NAK_Msk (0x1UL << DIEPINT_NAK_Pos) // 0x00002000 */
-#define DIEPINT_NAK DIEPINT_NAK_Msk // NAK interrupt */
+#define DIEPINT_NAK_Msk (0x1UL << DIEPINT_NAK_Pos) // 0x00002000
+#define DIEPINT_NAK DIEPINT_NAK_Msk // NAK interrupt
/******************** Bit definition for HCINTMSK register ********************/
#define HCINTMSK_XFRCM_Pos (0U)
-#define HCINTMSK_XFRCM_Msk (0x1UL << HCINTMSK_XFRCM_Pos) // 0x00000001 */
-#define HCINTMSK_XFRCM HCINTMSK_XFRCM_Msk // Transfer completed mask */
+#define HCINTMSK_XFRCM_Msk (0x1UL << HCINTMSK_XFRCM_Pos) // 0x00000001
+#define HCINTMSK_XFRCM HCINTMSK_XFRCM_Msk // Transfer completed mask
#define HCINTMSK_CHHM_Pos (1U)
-#define HCINTMSK_CHHM_Msk (0x1UL << HCINTMSK_CHHM_Pos) // 0x00000002 */
-#define HCINTMSK_CHHM HCINTMSK_CHHM_Msk // Channel halted mask */
+#define HCINTMSK_CHHM_Msk (0x1UL << HCINTMSK_CHHM_Pos) // 0x00000002
+#define HCINTMSK_CHHM HCINTMSK_CHHM_Msk // Channel halted mask
#define HCINTMSK_AHBERR_Pos (2U)
-#define HCINTMSK_AHBERR_Msk (0x1UL << HCINTMSK_AHBERR_Pos) // 0x00000004 */
-#define HCINTMSK_AHBERR HCINTMSK_AHBERR_Msk // AHB error */
+#define HCINTMSK_AHBERR_Msk (0x1UL << HCINTMSK_AHBERR_Pos) // 0x00000004
+#define HCINTMSK_AHBERR HCINTMSK_AHBERR_Msk // AHB error
#define HCINTMSK_STALLM_Pos (3U)
-#define HCINTMSK_STALLM_Msk (0x1UL << HCINTMSK_STALLM_Pos) // 0x00000008 */
-#define HCINTMSK_STALLM HCINTMSK_STALLM_Msk // STALL response received interrupt mask */
+#define HCINTMSK_STALLM_Msk (0x1UL << HCINTMSK_STALLM_Pos) // 0x00000008
+#define HCINTMSK_STALLM HCINTMSK_STALLM_Msk // STALL response received interrupt mask
#define HCINTMSK_NAKM_Pos (4U)
-#define HCINTMSK_NAKM_Msk (0x1UL << HCINTMSK_NAKM_Pos) // 0x00000010 */
-#define HCINTMSK_NAKM HCINTMSK_NAKM_Msk // NAK response received interrupt mask */
+#define HCINTMSK_NAKM_Msk (0x1UL << HCINTMSK_NAKM_Pos) // 0x00000010
+#define HCINTMSK_NAKM HCINTMSK_NAKM_Msk // NAK response received interrupt mask
#define HCINTMSK_ACKM_Pos (5U)
-#define HCINTMSK_ACKM_Msk (0x1UL << HCINTMSK_ACKM_Pos) // 0x00000020 */
-#define HCINTMSK_ACKM HCINTMSK_ACKM_Msk // ACK response received/transmitted interrupt mask */
+#define HCINTMSK_ACKM_Msk (0x1UL << HCINTMSK_ACKM_Pos) // 0x00000020
+#define HCINTMSK_ACKM HCINTMSK_ACKM_Msk // ACK response received/transmitted interrupt mask
#define HCINTMSK_NYET_Pos (6U)
-#define HCINTMSK_NYET_Msk (0x1UL << HCINTMSK_NYET_Pos) // 0x00000040 */
-#define HCINTMSK_NYET HCINTMSK_NYET_Msk // response received interrupt mask */
+#define HCINTMSK_NYET_Msk (0x1UL << HCINTMSK_NYET_Pos) // 0x00000040
+#define HCINTMSK_NYET HCINTMSK_NYET_Msk // response received interrupt mask
#define HCINTMSK_TXERRM_Pos (7U)
-#define HCINTMSK_TXERRM_Msk (0x1UL << HCINTMSK_TXERRM_Pos) // 0x00000080 */
-#define HCINTMSK_TXERRM HCINTMSK_TXERRM_Msk // Transaction error mask */
+#define HCINTMSK_TXERRM_Msk (0x1UL << HCINTMSK_TXERRM_Pos) // 0x00000080
+#define HCINTMSK_TXERRM HCINTMSK_TXERRM_Msk // Transaction error mask
#define HCINTMSK_BBERRM_Pos (8U)
-#define HCINTMSK_BBERRM_Msk (0x1UL << HCINTMSK_BBERRM_Pos) // 0x00000100 */
-#define HCINTMSK_BBERRM HCINTMSK_BBERRM_Msk // Babble error mask */
+#define HCINTMSK_BBERRM_Msk (0x1UL << HCINTMSK_BBERRM_Pos) // 0x00000100
+#define HCINTMSK_BBERRM HCINTMSK_BBERRM_Msk // Babble error mask
#define HCINTMSK_FRMORM_Pos (9U)
-#define HCINTMSK_FRMORM_Msk (0x1UL << HCINTMSK_FRMORM_Pos) // 0x00000200 */
-#define HCINTMSK_FRMORM HCINTMSK_FRMORM_Msk // Frame overrun mask */
+#define HCINTMSK_FRMORM_Msk (0x1UL << HCINTMSK_FRMORM_Pos) // 0x00000200
+#define HCINTMSK_FRMORM HCINTMSK_FRMORM_Msk // Frame overrun mask
#define HCINTMSK_DTERRM_Pos (10U)
-#define HCINTMSK_DTERRM_Msk (0x1UL << HCINTMSK_DTERRM_Pos) // 0x00000400 */
-#define HCINTMSK_DTERRM HCINTMSK_DTERRM_Msk // Data toggle error mask */
+#define HCINTMSK_DTERRM_Msk (0x1UL << HCINTMSK_DTERRM_Pos) // 0x00000400
+#define HCINTMSK_DTERRM HCINTMSK_DTERRM_Msk // Data toggle error mask
/******************** Bit definition for DIEPTSIZ register ********************/
#define DIEPTSIZ_XFRSIZ_Pos (0U)
-#define DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DIEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF */
-#define DIEPTSIZ_XFRSIZ DIEPTSIZ_XFRSIZ_Msk // Transfer size */
+#define DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DIEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF
+#define DIEPTSIZ_XFRSIZ DIEPTSIZ_XFRSIZ_Msk // Transfer size
#define DIEPTSIZ_PKTCNT_Pos (19U)
-#define DIEPTSIZ_PKTCNT_Msk (0x3FFUL << DIEPTSIZ_PKTCNT_Pos) // 0x1FF80000 */
-#define DIEPTSIZ_PKTCNT DIEPTSIZ_PKTCNT_Msk // Packet count */
+#define DIEPTSIZ_PKTCNT_Msk (0x3FFUL << DIEPTSIZ_PKTCNT_Pos) // 0x1FF80000
+#define DIEPTSIZ_PKTCNT DIEPTSIZ_PKTCNT_Msk // Packet count
#define DIEPTSIZ_MULCNT_Pos (29U)
-#define DIEPTSIZ_MULCNT_Msk (0x3UL << DIEPTSIZ_MULCNT_Pos) // 0x60000000 */
-#define DIEPTSIZ_MULCNT DIEPTSIZ_MULCNT_Msk // Packet count */
+#define DIEPTSIZ_MULCNT_Msk (0x3UL << DIEPTSIZ_MULCNT_Pos) // 0x60000000
+#define DIEPTSIZ_MULCNT DIEPTSIZ_MULCNT_Msk // Packet count
/******************** Bit definition for HCTSIZ register ********************/
#define HCTSIZ_XFRSIZ_Pos (0U)
-#define HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << HCTSIZ_XFRSIZ_Pos) // 0x0007FFFF */
-#define HCTSIZ_XFRSIZ HCTSIZ_XFRSIZ_Msk // Transfer size */
+#define HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << HCTSIZ_XFRSIZ_Pos) // 0x0007FFFF
+#define HCTSIZ_XFRSIZ HCTSIZ_XFRSIZ_Msk // Transfer size
#define HCTSIZ_PKTCNT_Pos (19U)
-#define HCTSIZ_PKTCNT_Msk (0x3FFUL << HCTSIZ_PKTCNT_Pos) // 0x1FF80000 */
-#define HCTSIZ_PKTCNT HCTSIZ_PKTCNT_Msk // Packet count */
+#define HCTSIZ_PKTCNT_Msk (0x3FFUL << HCTSIZ_PKTCNT_Pos) // 0x1FF80000
+#define HCTSIZ_PKTCNT HCTSIZ_PKTCNT_Msk // Packet count
#define HCTSIZ_DOPING_Pos (31U)
-#define HCTSIZ_DOPING_Msk (0x1UL << HCTSIZ_DOPING_Pos) // 0x80000000 */
-#define HCTSIZ_DOPING HCTSIZ_DOPING_Msk // Do PING */
+#define HCTSIZ_DOPING_Msk (0x1UL << HCTSIZ_DOPING_Pos) // 0x80000000
+#define HCTSIZ_DOPING HCTSIZ_DOPING_Msk // Do PING
#define HCTSIZ_DPID_Pos (29U)
-#define HCTSIZ_DPID_Msk (0x3UL << HCTSIZ_DPID_Pos) // 0x60000000 */
-#define HCTSIZ_DPID HCTSIZ_DPID_Msk // Data PID */
-#define HCTSIZ_DPID_0 (0x1UL << HCTSIZ_DPID_Pos) // 0x20000000 */
-#define HCTSIZ_DPID_1 (0x2UL << HCTSIZ_DPID_Pos) // 0x40000000 */
+#define HCTSIZ_DPID_Msk (0x3UL << HCTSIZ_DPID_Pos) // 0x60000000
+#define HCTSIZ_DPID HCTSIZ_DPID_Msk // Data PID
+#define HCTSIZ_DPID_0 (0x1UL << HCTSIZ_DPID_Pos) // 0x20000000
+#define HCTSIZ_DPID_1 (0x2UL << HCTSIZ_DPID_Pos) // 0x40000000
/******************** Bit definition for DIEPDMA register ********************/
#define DIEPDMA_DMAADDR_Pos (0U)
-#define DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << DIEPDMA_DMAADDR_Pos) // 0xFFFFFFFF */
-#define DIEPDMA_DMAADDR DIEPDMA_DMAADDR_Msk // DMA address */
+#define DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << DIEPDMA_DMAADDR_Pos) // 0xFFFFFFFF
+#define DIEPDMA_DMAADDR DIEPDMA_DMAADDR_Msk // DMA address
/******************** Bit definition for HCDMA register ********************/
#define HCDMA_DMAADDR_Pos (0U)
-#define HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << HCDMA_DMAADDR_Pos) // 0xFFFFFFFF */
-#define HCDMA_DMAADDR HCDMA_DMAADDR_Msk // DMA address */
+#define HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << HCDMA_DMAADDR_Pos) // 0xFFFFFFFF
+#define HCDMA_DMAADDR HCDMA_DMAADDR_Msk // DMA address
/******************** Bit definition for DTXFSTS register ********************/
#define DTXFSTS_INEPTFSAV_Pos (0U)
-#define DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << DTXFSTS_INEPTFSAV_Pos) // 0x0000FFFF */
-#define DTXFSTS_INEPTFSAV DTXFSTS_INEPTFSAV_Msk // IN endpoint TxFIFO space available */
+#define DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << DTXFSTS_INEPTFSAV_Pos) // 0x0000FFFF
+#define DTXFSTS_INEPTFSAV DTXFSTS_INEPTFSAV_Msk // IN endpoint TxFIFO space available
/******************** Bit definition for DIEPTXF register ********************/
#define DIEPTXF_INEPTXSA_Pos (0U)
-#define DIEPTXF_INEPTXSA_Msk (0xFFFFUL << DIEPTXF_INEPTXSA_Pos) // 0x0000FFFF */
-#define DIEPTXF_INEPTXSA DIEPTXF_INEPTXSA_Msk // IN endpoint FIFOx transmit RAM start address */
+#define DIEPTXF_INEPTXSA_Msk (0xFFFFUL << DIEPTXF_INEPTXSA_Pos) // 0x0000FFFF
+#define DIEPTXF_INEPTXSA DIEPTXF_INEPTXSA_Msk // IN endpoint FIFOx transmit RAM start address
#define DIEPTXF_INEPTXFD_Pos (16U)
-#define DIEPTXF_INEPTXFD_Msk (0xFFFFUL << DIEPTXF_INEPTXFD_Pos) // 0xFFFF0000 */
-#define DIEPTXF_INEPTXFD DIEPTXF_INEPTXFD_Msk // IN endpoint TxFIFO depth */
+#define DIEPTXF_INEPTXFD_Msk (0xFFFFUL << DIEPTXF_INEPTXFD_Pos) // 0xFFFF0000
+#define DIEPTXF_INEPTXFD DIEPTXF_INEPTXFD_Msk // IN endpoint TxFIFO depth
/******************** Bit definition for DOEPCTL register ********************/
#define DOEPCTL_MPSIZ_Pos (0U)
-#define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF */
-#define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size */ //Bit 1 */
+#define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF
+#define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size //Bit 1
#define DOEPCTL_USBAEP_Pos (15U)
-#define DOEPCTL_USBAEP_Msk (0x1UL << DOEPCTL_USBAEP_Pos) // 0x00008000 */
-#define DOEPCTL_USBAEP DOEPCTL_USBAEP_Msk // USB active endpoint */
+#define DOEPCTL_USBAEP_Msk (0x1UL << DOEPCTL_USBAEP_Pos) // 0x00008000
+#define DOEPCTL_USBAEP DOEPCTL_USBAEP_Msk // USB active endpoint
#define DOEPCTL_NAKSTS_Pos (17U)
-#define DOEPCTL_NAKSTS_Msk (0x1UL << DOEPCTL_NAKSTS_Pos) // 0x00020000 */
-#define DOEPCTL_NAKSTS DOEPCTL_NAKSTS_Msk // NAK status */
+#define DOEPCTL_NAKSTS_Msk (0x1UL << DOEPCTL_NAKSTS_Pos) // 0x00020000
+#define DOEPCTL_NAKSTS DOEPCTL_NAKSTS_Msk // NAK status
#define DOEPCTL_SD0PID_SEVNFRM_Pos (28U)
-#define DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DOEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000 */
-#define DOEPCTL_SD0PID_SEVNFRM DOEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID */
+#define DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << DOEPCTL_SD0PID_SEVNFRM_Pos) // 0x10000000
+#define DOEPCTL_SD0PID_SEVNFRM DOEPCTL_SD0PID_SEVNFRM_Msk // Set DATA0 PID
#define DOEPCTL_SODDFRM_Pos (29U)
-#define DOEPCTL_SODDFRM_Msk (0x1UL << DOEPCTL_SODDFRM_Pos) // 0x20000000 */
-#define DOEPCTL_SODDFRM DOEPCTL_SODDFRM_Msk // Set odd frame */
+#define DOEPCTL_SODDFRM_Msk (0x1UL << DOEPCTL_SODDFRM_Pos) // 0x20000000
+#define DOEPCTL_SODDFRM DOEPCTL_SODDFRM_Msk // Set odd frame
#define DOEPCTL_EPTYP_Pos (18U)
-#define DOEPCTL_EPTYP_Msk (0x3UL << DOEPCTL_EPTYP_Pos) // 0x000C0000 */
-#define DOEPCTL_EPTYP DOEPCTL_EPTYP_Msk // Endpoint type */
-#define DOEPCTL_EPTYP_0 (0x1UL << DOEPCTL_EPTYP_Pos) // 0x00040000 */
-#define DOEPCTL_EPTYP_1 (0x2UL << DOEPCTL_EPTYP_Pos) // 0x00080000 */
+#define DOEPCTL_EPTYP_Msk (0x3UL << DOEPCTL_EPTYP_Pos) // 0x000C0000
+#define DOEPCTL_EPTYP DOEPCTL_EPTYP_Msk // Endpoint type
+#define DOEPCTL_EPTYP_0 (0x1UL << DOEPCTL_EPTYP_Pos) // 0x00040000
+#define DOEPCTL_EPTYP_1 (0x2UL << DOEPCTL_EPTYP_Pos) // 0x00080000
#define DOEPCTL_SNPM_Pos (20U)
-#define DOEPCTL_SNPM_Msk (0x1UL << DOEPCTL_SNPM_Pos) // 0x00100000 */
-#define DOEPCTL_SNPM DOEPCTL_SNPM_Msk // Snoop mode */
+#define DOEPCTL_SNPM_Msk (0x1UL << DOEPCTL_SNPM_Pos) // 0x00100000
+#define DOEPCTL_SNPM DOEPCTL_SNPM_Msk // Snoop mode
#define DOEPCTL_STALL_Pos (21U)
-#define DOEPCTL_STALL_Msk (0x1UL << DOEPCTL_STALL_Pos) // 0x00200000 */
-#define DOEPCTL_STALL DOEPCTL_STALL_Msk // STALL handshake */
+#define DOEPCTL_STALL_Msk (0x1UL << DOEPCTL_STALL_Pos) // 0x00200000
+#define DOEPCTL_STALL DOEPCTL_STALL_Msk // STALL handshake
#define DOEPCTL_CNAK_Pos (26U)
-#define DOEPCTL_CNAK_Msk (0x1UL << DOEPCTL_CNAK_Pos) // 0x04000000 */
-#define DOEPCTL_CNAK DOEPCTL_CNAK_Msk // Clear NAK */
+#define DOEPCTL_CNAK_Msk (0x1UL << DOEPCTL_CNAK_Pos) // 0x04000000
+#define DOEPCTL_CNAK DOEPCTL_CNAK_Msk // Clear NAK
#define DOEPCTL_SNAK_Pos (27U)
-#define DOEPCTL_SNAK_Msk (0x1UL << DOEPCTL_SNAK_Pos) // 0x08000000 */
-#define DOEPCTL_SNAK DOEPCTL_SNAK_Msk // Set NAK */
+#define DOEPCTL_SNAK_Msk (0x1UL << DOEPCTL_SNAK_Pos) // 0x08000000
+#define DOEPCTL_SNAK DOEPCTL_SNAK_Msk // Set NAK
#define DOEPCTL_EPDIS_Pos (30U)
-#define DOEPCTL_EPDIS_Msk (0x1UL << DOEPCTL_EPDIS_Pos) // 0x40000000 */
-#define DOEPCTL_EPDIS DOEPCTL_EPDIS_Msk // Endpoint disable */
+#define DOEPCTL_EPDIS_Msk (0x1UL << DOEPCTL_EPDIS_Pos) // 0x40000000
+#define DOEPCTL_EPDIS DOEPCTL_EPDIS_Msk // Endpoint disable
#define DOEPCTL_EPENA_Pos (31U)
-#define DOEPCTL_EPENA_Msk (0x1UL << DOEPCTL_EPENA_Pos) // 0x80000000 */
-#define DOEPCTL_EPENA DOEPCTL_EPENA_Msk // Endpoint enable */
+#define DOEPCTL_EPENA_Msk (0x1UL << DOEPCTL_EPENA_Pos) // 0x80000000
+#define DOEPCTL_EPENA DOEPCTL_EPENA_Msk // Endpoint enable
/******************** Bit definition for DOEPINT register ********************/
#define DOEPINT_XFRC_Pos (0U)
-#define DOEPINT_XFRC_Msk (0x1UL << DOEPINT_XFRC_Pos) // 0x00000001 */
-#define DOEPINT_XFRC DOEPINT_XFRC_Msk // Transfer completed interrupt */
+#define DOEPINT_XFRC_Msk (0x1UL << DOEPINT_XFRC_Pos) // 0x00000001
+#define DOEPINT_XFRC DOEPINT_XFRC_Msk // Transfer completed interrupt
#define DOEPINT_EPDISD_Pos (1U)
-#define DOEPINT_EPDISD_Msk (0x1UL << DOEPINT_EPDISD_Pos) // 0x00000002 */
-#define DOEPINT_EPDISD DOEPINT_EPDISD_Msk // Endpoint disabled interrupt */
+#define DOEPINT_EPDISD_Msk (0x1UL << DOEPINT_EPDISD_Pos) // 0x00000002
+#define DOEPINT_EPDISD DOEPINT_EPDISD_Msk // Endpoint disabled interrupt
#define DOEPINT_AHBERR_Pos (2U)
-#define DOEPINT_AHBERR_Msk (0x1UL << DOEPINT_AHBERR_Pos) // 0x00000004 */
-#define DOEPINT_AHBERR DOEPINT_AHBERR_Msk // AHB Error (AHBErr) during an OUT transaction */
+#define DOEPINT_AHBERR_Msk (0x1UL << DOEPINT_AHBERR_Pos) // 0x00000004
+#define DOEPINT_AHBERR DOEPINT_AHBERR_Msk // AHB Error (AHBErr) during an OUT transaction
#define DOEPINT_STUP_Pos (3U)
-#define DOEPINT_STUP_Msk (0x1UL << DOEPINT_STUP_Pos) // 0x00000008 */
-#define DOEPINT_STUP DOEPINT_STUP_Msk // SETUP phase done */
+#define DOEPINT_STUP_Msk (0x1UL << DOEPINT_STUP_Pos) // 0x00000008
+#define DOEPINT_STUP DOEPINT_STUP_Msk // SETUP phase done
#define DOEPINT_OTEPDIS_Pos (4U)
-#define DOEPINT_OTEPDIS_Msk (0x1UL << DOEPINT_OTEPDIS_Pos) // 0x00000010 */
-#define DOEPINT_OTEPDIS DOEPINT_OTEPDIS_Msk // OUT token received when endpoint disabled */
+#define DOEPINT_OTEPDIS_Msk (0x1UL << DOEPINT_OTEPDIS_Pos) // 0x00000010
+#define DOEPINT_OTEPDIS DOEPINT_OTEPDIS_Msk // OUT token received when endpoint disabled
#define DOEPINT_OTEPSPR_Pos (5U)
-#define DOEPINT_OTEPSPR_Msk (0x1UL << DOEPINT_OTEPSPR_Pos) // 0x00000020 */
-#define DOEPINT_OTEPSPR DOEPINT_OTEPSPR_Msk // Status Phase Received For Control Write */
+#define DOEPINT_OTEPSPR_Msk (0x1UL << DOEPINT_OTEPSPR_Pos) // 0x00000020
+#define DOEPINT_OTEPSPR DOEPINT_OTEPSPR_Msk // Status Phase Received For Control Write
#define DOEPINT_B2BSTUP_Pos (6U)
-#define DOEPINT_B2BSTUP_Msk (0x1UL << DOEPINT_B2BSTUP_Pos) // 0x00000040 */
-#define DOEPINT_B2BSTUP DOEPINT_B2BSTUP_Msk // Back-to-back SETUP packets received */
+#define DOEPINT_B2BSTUP_Msk (0x1UL << DOEPINT_B2BSTUP_Pos) // 0x00000040
+#define DOEPINT_B2BSTUP DOEPINT_B2BSTUP_Msk // Back-to-back SETUP packets received
#define DOEPINT_OUTPKTERR_Pos (8U)
-#define DOEPINT_OUTPKTERR_Msk (0x1UL << DOEPINT_OUTPKTERR_Pos) // 0x00000100 */
-#define DOEPINT_OUTPKTERR DOEPINT_OUTPKTERR_Msk // OUT packet error */
+#define DOEPINT_OUTPKTERR_Msk (0x1UL << DOEPINT_OUTPKTERR_Pos) // 0x00000100
+#define DOEPINT_OUTPKTERR DOEPINT_OUTPKTERR_Msk // OUT packet error
#define DOEPINT_NAK_Pos (13U)
-#define DOEPINT_NAK_Msk (0x1UL << DOEPINT_NAK_Pos) // 0x00002000 */
-#define DOEPINT_NAK DOEPINT_NAK_Msk // NAK Packet is transmitted by the device */
+#define DOEPINT_NAK_Msk (0x1UL << DOEPINT_NAK_Pos) // 0x00002000
+#define DOEPINT_NAK DOEPINT_NAK_Msk // NAK Packet is transmitted by the device
#define DOEPINT_NYET_Pos (14U)
-#define DOEPINT_NYET_Msk (0x1UL << DOEPINT_NYET_Pos) // 0x00004000 */
-#define DOEPINT_NYET DOEPINT_NYET_Msk // NYET interrupt */
+#define DOEPINT_NYET_Msk (0x1UL << DOEPINT_NYET_Pos) // 0x00004000
+#define DOEPINT_NYET DOEPINT_NYET_Msk // NYET interrupt
#define DOEPINT_STPKTRX_Pos (15U)
-#define DOEPINT_STPKTRX_Msk (0x1UL << DOEPINT_STPKTRX_Pos) // 0x00008000 */
-#define DOEPINT_STPKTRX DOEPINT_STPKTRX_Msk // Setup Packet Received */
+#define DOEPINT_STPKTRX_Msk (0x1UL << DOEPINT_STPKTRX_Pos) // 0x00008000
+#define DOEPINT_STPKTRX DOEPINT_STPKTRX_Msk // Setup Packet Received
/******************** Bit definition for DOEPTSIZ register ********************/
#define DOEPTSIZ_XFRSIZ_Pos (0U)
-#define DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DOEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF */
-#define DOEPTSIZ_XFRSIZ DOEPTSIZ_XFRSIZ_Msk // Transfer size */
+#define DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << DOEPTSIZ_XFRSIZ_Pos) // 0x0007FFFF
+#define DOEPTSIZ_XFRSIZ DOEPTSIZ_XFRSIZ_Msk // Transfer size
#define DOEPTSIZ_PKTCNT_Pos (19U)
-#define DOEPTSIZ_PKTCNT_Msk (0x3FFUL << DOEPTSIZ_PKTCNT_Pos) // 0x1FF80000 */
-#define DOEPTSIZ_PKTCNT DOEPTSIZ_PKTCNT_Msk // Packet count */
+#define DOEPTSIZ_PKTCNT_Msk (0x3FFUL << DOEPTSIZ_PKTCNT_Pos) // 0x1FF80000
+#define DOEPTSIZ_PKTCNT DOEPTSIZ_PKTCNT_Msk // Packet count
#define DOEPTSIZ_STUPCNT_Pos (29U)
-#define DOEPTSIZ_STUPCNT_Msk (0x3UL << DOEPTSIZ_STUPCNT_Pos) // 0x60000000 */
-#define DOEPTSIZ_STUPCNT DOEPTSIZ_STUPCNT_Msk // SETUP packet count */
-#define DOEPTSIZ_STUPCNT_0 (0x1UL << DOEPTSIZ_STUPCNT_Pos) // 0x20000000 */
-#define DOEPTSIZ_STUPCNT_1 (0x2UL << DOEPTSIZ_STUPCNT_Pos) // 0x40000000 */
+#define DOEPTSIZ_STUPCNT_Msk (0x3UL << DOEPTSIZ_STUPCNT_Pos) // 0x60000000
+#define DOEPTSIZ_STUPCNT DOEPTSIZ_STUPCNT_Msk // SETUP packet count
+#define DOEPTSIZ_STUPCNT_0 (0x1UL << DOEPTSIZ_STUPCNT_Pos) // 0x20000000
+#define DOEPTSIZ_STUPCNT_1 (0x2UL << DOEPTSIZ_STUPCNT_Pos) // 0x40000000
/******************** Bit definition for PCGCTL register ********************/
#define PCGCTL_IF_DEV_MODE TU_BIT(31)
diff --git a/src/portable/synopsys/dwc2/hwcfg_list.md b/src/portable/synopsys/dwc2/hwcfg_list.md
deleted file mode 100644
index b5590da00..000000000
--- a/src/portable/synopsys/dwc2/hwcfg_list.md
+++ /dev/null
@@ -1,777 +0,0 @@
-# DWC2 Hardware Configuration Registers
-
-## Broadcom BCM2711 (Pi4)
-
-dwc2->guid = 2708A000
-dwc2->gsnpsid = 4F54280A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 228DDD50
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 2
-hw_cfg2->point2point = 0
-hw_cfg2->hs_phy_type = 1
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 7
-hw_cfg2->num_host_ch = 7
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 0
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = FF000E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 0
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 0
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 0
-hw_cfg3->lpm_mode = 0
-hw_cfg3->total_fifo_size = 4080
-
-dwc2->ghwcfg4 = 1FF00020
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 0
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 0
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 15
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## EFM32GG FS
-
-dwc2->guid = 0
-dwc2->gsnpsid = 4F54330A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 228F5910
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 2
-hw_cfg2->point2point = 0
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 6
-hw_cfg2->num_host_ch = 13
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 0
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 1F204E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 0
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 1
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 0
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 0
-hw_cfg3->lpm_mode = 0
-hw_cfg3->total_fifo_size = 498
-
-dwc2->ghwcfg4 = 1BF08030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 2
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 13
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## ESP32-S2 Fullspeed
-
-dwc2->guid = 0
-dwc2->gsnpsid = 4F54400A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 224DD930
-hw_cfg2->op_mode = 2
-hw_cfg2->arch = 3
-hw_cfg2->point2point = 0
-hw_cfg2->hs_phy_type = 1
-hw_cfg2->fs_phy_type = 2
-hw_cfg2->num_dev_ep = 6
-hw_cfg2->num_host_ch = 9
-hw_cfg2->period_channel_support = 0
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 1
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 22
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = C804B5
-hw_cfg3->xfer_size_width = 10
-hw_cfg3->packet_size_width = 5
-hw_cfg3->otg_enable = 0
-hw_cfg3->i2c_enable = 0
-hw_cfg3->vendor_ctrl_itf = 1
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 1
-hw_cfg3->otg_adp_support = 1
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 1
-hw_cfg3->lpm_mode = 0
-hw_cfg3->total_fifo_size = 23130
-
-dwc2->ghwcfg4 = D3F0A030
-hw_cfg4->num_dev_period_in_ep = 10
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 0
-hw_cfg4->hibernation = 1
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 1
-hw_cfg4->acg_enable = 1
-hw_cfg4->utmi_phy_data_width = 1
-hw_cfg4->dev_ctrl_ep_num = 10
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 0
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 0
-hw_cfg4->dedicated_fifos = 0
-hw_cfg4->num_dev_in_eps = 13
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 1
-
-## STM32F407 and STM32F207
-
-STM32F407 and STM32F207 are exactly the same
-
-### STM32F407 Fullspeed
-
-dwc2->guid = 1200
-dwc2->gsnpsid = 4F54281A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229DCD20
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 0
-hw_cfg2->point2point = 1
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 3
-hw_cfg2->num_host_ch = 7
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 20001E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 1
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 0
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 0
-hw_cfg3->lpm_mode = 0
-hw_cfg3->total_fifo_size = 512
-
-dwc2->ghwcfg4 = FF08030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 2
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 7
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-### STM32F407 Highspeed
-
-dwc2->guid = 1100
-dwc2->gsnpsid = 4F54281A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229ED590
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 2
-hw_cfg2->point2point = 0
-hw_cfg2->hs_phy_type = 2
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 5
-hw_cfg2->num_host_ch = 11
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 3F403E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 1
-hw_cfg3->vendor_ctrl_itf = 1
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 0
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 0
-hw_cfg3->lpm_mode = 0
-hw_cfg3->total_fifo_size = 1012
-
-dwc2->ghwcfg4 = 17F00030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 0
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 11
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## STM32F411 Fullspeed
-
-dwc2->guid = 1200
-dwc2->gsnpsid = 4F54281A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229DCD20
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 0
-hw_cfg2->point2point = 1
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 3
-hw_cfg2->num_host_ch = 7
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 20001E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 1
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 0
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 0
-hw_cfg3->lpm_mode = 0
-hw_cfg3->total_fifo_size = 512
-
-dwc2->ghwcfg4 = FF08030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 2
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 7
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## STM32F412 FS
-
-dwc2->guid = 2000
-dwc2->gsnpsid = 4F54320A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229ED520
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 0
-hw_cfg2->point2point = 1
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 5
-hw_cfg2->num_host_ch = 11
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 200D1E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 1
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 1
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 1
-hw_cfg3->lpm_mode = 1
-hw_cfg3->total_fifo_size = 512
-
-dwc2->ghwcfg4 = 17F08030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 2
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 11
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## STM32F723
-
-### STM32F723 HighSpeed
-
-dwc2->guid = 3100
-dwc2->gsnpsid = 4F54330A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229FE1D0
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 2
-hw_cfg2->point2point = 0
-hw_cfg2->hs_phy_type = 3
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 8
-hw_cfg2->num_host_ch = 15
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 3EED2E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 0
-hw_cfg3->vendor_ctrl_itf = 1
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 1
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 1
-hw_cfg3->lpm_mode = 1
-hw_cfg3->total_fifo_size = 1006
-
-dwc2->ghwcfg4 = 23F00030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 0
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 1
-hw_cfg4->dma_desc_enable = 1
-hw_cfg4->dma_dynamic = 0
-
-### STM32F723 Fullspeed
-
-dwc2->guid = 3000
-dwc2->gsnpsid = 4F54330A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229ED520
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 0
-hw_cfg2->point2point = 1
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 5
-hw_cfg2->num_host_ch = 11
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 200D1E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 1
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 1
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 1
-hw_cfg3->lpm_mode = 1
-hw_cfg3->total_fifo_size = 512
-
-dwc2->ghwcfg4 = 17F08030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 2
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 11
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## STM32F767 FS
-
-dwc2->guid = 2000
-dwc2->gsnpsid = 4F54320A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229ED520
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 0
-hw_cfg2->point2point = 1
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 5
-hw_cfg2->num_host_ch = 11
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 200D1E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 1
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 1
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 1
-hw_cfg3->lpm_mode = 1
-hw_cfg3->total_fifo_size = 512
-
-dwc2->ghwcfg4 = 17F08030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 2
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 11
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## STM32H743 (both cores HS)
-
-dwc2->guid = 2300
-dwc2->gsnpsid = 4F54330A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229FE190
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 2
-hw_cfg2->point2point = 0
-hw_cfg2->hs_phy_type = 2
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 8
-hw_cfg2->num_host_ch = 15
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 3B8D2E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 0
-hw_cfg3->vendor_ctrl_itf = 1
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 1
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 1
-hw_cfg3->lpm_mode = 1
-hw_cfg3->total_fifo_size = 952
-
-dwc2->ghwcfg4 = E3F00030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 0
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 1
-hw_cfg4->dma_desc_enable = 1
-hw_cfg4->dma_dynamic = 1
-
-## STM32L476 FS
-
-dwc2->guid = 2000
-dwc2->gsnpsid = 4F54310A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 229ED520
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 0
-hw_cfg2->point2point = 1
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 5
-hw_cfg2->num_host_ch = 11
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 1
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 200D1E8
-hw_cfg3->xfer_size_width = 8
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 1
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 1
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 1
-hw_cfg3->lpm_mode = 1
-hw_cfg3->total_fifo_size = 512
-
-dwc2->ghwcfg4 = 17F08030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 2
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 11
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## GD32VF103 Fullspeed
-
-dwc2->guid = 1000
-dwc2->gsnpsid = 0
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 0
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 0
-hw_cfg2->point2point = 0
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 0
-hw_cfg2->num_dev_ep = 0
-hw_cfg2->num_host_ch = 0
-hw_cfg2->period_channel_support = 0
-hw_cfg2->enable_dynamic_fifo = 0
-hw_cfg2->mul_cpu_int = 0
-hw_cfg2->nperiod_tx_q_depth = 0
-hw_cfg2->host_period_tx_q_depth = 0
-hw_cfg2->dev_token_q_depth = 0
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 0
-hw_cfg3->xfer_size_width = 0
-hw_cfg3->packet_size_width = 0
-hw_cfg3->otg_enable = 0
-hw_cfg3->i2c_enable = 0
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 0
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 0
-hw_cfg3->lpm_mode = 0
-hw_cfg3->total_fifo_size = 0
-
-dwc2->ghwcfg4 = 0
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 0
-hw_cfg4->ahb_freq_min = 0
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 0
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 0
-hw_cfg4->vbus_valid_filter_enabled = 0
-hw_cfg4->a_valid_filter_enabled = 0
-hw_cfg4->b_valid_filter_enabled = 0
-hw_cfg4->dedicated_fifos = 0
-hw_cfg4->num_dev_in_eps = 0
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 0
-
-## XMC4500
-
-dwc2->guid = AEC000
-dwc2->gsnpsid = 4F54292A
-dwc2->ghwcfg1 = 0
-
-dwc2->ghwcfg2 = 228F5930
-hw_cfg2->op_mode = 0
-hw_cfg2->arch = 2
-hw_cfg2->point2point = 1
-hw_cfg2->hs_phy_type = 0
-hw_cfg2->fs_phy_type = 1
-hw_cfg2->num_dev_ep = 6
-hw_cfg2->num_host_ch = 13
-hw_cfg2->period_channel_support = 1
-hw_cfg2->enable_dynamic_fifo = 1
-hw_cfg2->mul_cpu_int = 0
-hw_cfg2->nperiod_tx_q_depth = 2
-hw_cfg2->host_period_tx_q_depth = 2
-hw_cfg2->dev_token_q_depth = 8
-hw_cfg2->otg_enable_ic_usb = 0
-
-dwc2->ghwcfg3 = 27A01E5
-hw_cfg3->xfer_size_width = 5
-hw_cfg3->packet_size_width = 6
-hw_cfg3->otg_enable = 1
-hw_cfg3->i2c_enable = 1
-hw_cfg3->vendor_ctrl_itf = 0
-hw_cfg3->optional_feature_removed = 0
-hw_cfg3->synch_reset = 0
-hw_cfg3->otg_adp_support = 0
-hw_cfg3->otg_enable_hsic = 0
-hw_cfg3->battery_charger_support = 0
-hw_cfg3->lpm_mode = 0
-hw_cfg3->total_fifo_size = 634
-
-dwc2->ghwcfg4 = DBF08030
-hw_cfg4->num_dev_period_in_ep = 0
-hw_cfg4->power_optimized = 1
-hw_cfg4->ahb_freq_min = 1
-hw_cfg4->hibernation = 0
-hw_cfg4->service_interval_mode = 0
-hw_cfg4->ipg_isoc_en = 0
-hw_cfg4->acg_enable = 0
-hw_cfg4->utmi_phy_data_width = 2
-hw_cfg4->dev_ctrl_ep_num = 0
-hw_cfg4->iddg_filter_enabled = 1
-hw_cfg4->vbus_valid_filter_enabled = 1
-hw_cfg4->a_valid_filter_enabled = 1
-hw_cfg4->b_valid_filter_enabled = 1
-hw_cfg4->dedicated_fifos = 1
-hw_cfg4->num_dev_in_eps = 13
-hw_cfg4->dma_desc_enable = 0
-hw_cfg4->dma_dynamic = 1
diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c
index 590dd9fcf..12d610bd6 100644
--- a/src/portable/template/dcd_template.c
+++ b/src/portable/template/dcd_template.c
@@ -26,7 +26,7 @@
#include "tusb_option.h"
-#if CFG_TUSB_MCU == OPT_MCU_NONE
+#if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_NONE
#include "device/dcd.h"
@@ -141,4 +141,6 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
(void) ep_addr;
}
+
+
#endif
diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c
new file mode 100644
index 000000000..b073d6057
--- /dev/null
+++ b/src/portable/template/hcd_template.c
@@ -0,0 +1,163 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+#if CFG_TUH_ENABLED && CFG_TUSB_MCU == OPT_MCU_NONE
+
+#include "host/hcd.h"
+
+//--------------------------------------------------------------------+
+// Controller API
+//--------------------------------------------------------------------+
+
+// optional hcd configuration, called by tuh_configure()
+bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
+ (void) rhport;
+ (void) cfg_id;
+ (void) cfg_param;
+
+ return false;
+}
+
+// Initialize controller to host mode
+bool hcd_init(uint8_t rhport) {
+ (void) rhport;
+
+ return false;
+}
+
+// Interrupt Handler
+void hcd_int_handler(uint8_t rhport, bool in_isr) {
+ (void) rhport;
+ (void) in_isr;
+}
+
+// Enable USB interrupt
+void hcd_int_enable (uint8_t rhport) {
+ (void) rhport;
+}
+
+// Disable USB interrupt
+void hcd_int_disable(uint8_t rhport) {
+ (void) rhport;
+}
+
+// Get frame number (1ms)
+uint32_t hcd_frame_number(uint8_t rhport) {
+ (void) rhport;
+
+ return 0;
+}
+
+//--------------------------------------------------------------------+
+// Port API
+//--------------------------------------------------------------------+
+
+// Get the current connect status of roothub port
+bool hcd_port_connect_status(uint8_t rhport) {
+ (void) rhport;
+
+ return false;
+}
+
+// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete.
+// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence.
+void hcd_port_reset(uint8_t rhport) {
+ (void) rhport;
+}
+
+// Complete bus reset sequence, may be required by some controllers
+void hcd_port_reset_end(uint8_t rhport) {
+ (void) rhport;
+}
+
+// Get port link speed
+tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
+ (void) rhport;
+
+ return TUSB_SPEED_FULL;
+}
+
+// HCD closes all opened endpoints belong to this device
+void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
+ (void) rhport;
+ (void) dev_addr;
+}
+
+//--------------------------------------------------------------------+
+// Endpoints API
+//--------------------------------------------------------------------+
+
+// Open an endpoint
+bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_desc;
+
+ return false;
+}
+
+// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+ (void) buffer;
+ (void) buflen;
+
+ return false;
+}
+
+// Abort a queued transfer. Note: it can only abort transfer that has not been started
+// Return true if a queued transfer is aborted, false if there is no transfer to abort
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+
+ return false;
+}
+
+// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked
+bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) setup_packet;
+
+ return false;
+}
+
+// clear stall, data toggle is also reset to DATA0
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+ (void) dev_addr;
+ (void) ep_addr;
+
+ return false;
+}
+
+#endif
diff --git a/src/portable/wch/ch32v307/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h
index 5a2c1fbc9..9b956231f 100644
--- a/src/portable/wch/ch32v307/ch32_usbhs_reg.h
+++ b/src/portable/wch/ch32_usbhs_reg.h
@@ -1,7 +1,11 @@
#ifndef _USB_CH32_USBHS_REG_H
#define _USB_CH32_USBHS_REG_H
+#if (CFG_TUSB_MCU == OPT_MCU_CH32V307)
#include <ch32v30x.h>
+#elif (CFG_TUSB_MCU == OPT_MCU_CH32F20X)
+#include <ch32f20x.h>
+#endif
/******************* GLOBAL ******************/
diff --git a/src/portable/wch/ch32v307/dcd_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c
index 3ad011cff..1f1c0b876 100644
--- a/src/portable/wch/ch32v307/dcd_usbhs.c
+++ b/src/portable/wch/dcd_ch32_usbhs.c
@@ -26,11 +26,11 @@
#include "tusb_option.h"
-#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V307)
+#if CFG_TUD_ENABLED && ((CFG_TUSB_MCU == OPT_MCU_CH32V307) || (CFG_TUSB_MCU == OPT_MCU_CH32F20X))
#include "device/dcd.h"
#include "ch32_usbhs_reg.h"
-#include "core_riscv.h"
+
// Max number of bi-directional endpoints including EP0
#define EP_MAX 16
@@ -73,7 +73,7 @@ void dcd_init(uint8_t rhport) {
#if TUD_OPT_HIGH_SPEED
USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED;
#else
- #error OPT_MODE_FULL_SPEED not currently supported on CH32V307
+ #error OPT_MODE_FULL_SPEED not currently supported on CH32
USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_FULL_SPEED;
#endif
diff --git a/src/tinyusb.mk b/src/tinyusb.mk
new file mode 100644
index 000000000..89ea0212c
--- /dev/null
+++ b/src/tinyusb.mk
@@ -0,0 +1,26 @@
+# C source files
+TINYUSB_SRC_C += \
+ src/tusb.c \
+ src/common/tusb_fifo.c \
+ src/device/usbd.c \
+ src/device/usbd_control.c \
+ src/typec/usbc.c \
+ src/class/audio/audio_device.c \
+ src/class/cdc/cdc_device.c \
+ src/class/dfu/dfu_device.c \
+ src/class/dfu/dfu_rt_device.c \
+ src/class/hid/hid_device.c \
+ src/class/midi/midi_device.c \
+ src/class/msc/msc_device.c \
+ src/class/net/ecm_rndis_device.c \
+ src/class/net/ncm_device.c \
+ src/class/usbtmc/usbtmc_device.c \
+ src/class/video/video_device.c \
+ src/class/vendor/vendor_device.c \
+ src/host/usbh.c \
+ src/host/hub.c \
+ src/class/cdc/cdc_host.c \
+ src/class/hid/hid_host.c \
+ src/class/msc/msc_host.c \
+ src/class/vendor/vendor_host.c \
+ src/typec/usbc.c \
diff --git a/src/tusb.c b/src/tusb.c
index 85fe5a3cc..0092267a1 100644
--- a/src/tusb.c
+++ b/src/tusb.c
@@ -36,39 +36,37 @@
#endif
#if CFG_TUH_ENABLED
-#include "host/usbh_classdriver.h"
+#include "host/usbh_pvt.h"
#endif
//--------------------------------------------------------------------+
// Public API
//--------------------------------------------------------------------+
-bool tusb_init(void)
-{
-#if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT)
+bool tusb_init(void) {
+ #if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT)
// init device stack CFG_TUSB_RHPORTx_MODE must be defined
TU_ASSERT ( tud_init(TUD_OPT_RHPORT) );
-#endif
+ #endif
-#if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT)
+ #if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT)
// init host stack CFG_TUSB_RHPORTx_MODE must be defined
TU_ASSERT( tuh_init(TUH_OPT_RHPORT) );
-#endif
+ #endif
return true;
}
-bool tusb_inited(void)
-{
+bool tusb_inited(void) {
bool ret = false;
-#if CFG_TUD_ENABLED
+ #if CFG_TUD_ENABLED
ret = ret || tud_inited();
-#endif
+ #endif
-#if CFG_TUH_ENABLED
+ #if CFG_TUH_ENABLED
ret = ret || tuh_inited();
-#endif
+ #endif
return ret;
}
@@ -77,43 +75,35 @@ bool tusb_inited(void)
// Descriptor helper
//--------------------------------------------------------------------+
-uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1)
-{
- while(desc+1 < end)
- {
- if ( desc[1] == byte1 ) return desc;
+uint8_t const* tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1) {
+ while (desc + 1 < end) {
+ if (desc[1] == byte1) return desc;
desc += desc[DESC_OFFSET_LEN];
}
return NULL;
}
-uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2)
-{
- while(desc+2 < end)
- {
- if ( desc[1] == byte1 && desc[2] == byte2) return desc;
+uint8_t const* tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2) {
+ while (desc + 2 < end) {
+ if (desc[1] == byte1 && desc[2] == byte2) return desc;
desc += desc[DESC_OFFSET_LEN];
}
return NULL;
}
-uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3)
-{
- while(desc+3 < end)
- {
+uint8_t const* tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3) {
+ while (desc + 3 < end) {
if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) return desc;
desc += desc[DESC_OFFSET_LEN];
}
return NULL;
}
-
//--------------------------------------------------------------------+
// Endpoint Helper for both Host and Device stack
//--------------------------------------------------------------------+
-bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex)
-{
+bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) {
(void) mutex;
// pre-check to help reducing mutex lock
@@ -122,111 +112,93 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex)
// can only claim the endpoint if it is not busy and not claimed yet.
bool const available = (ep_state->busy == 0) && (ep_state->claimed == 0);
- if (available)
- {
+ if (available) {
ep_state->claimed = 1;
}
(void) osal_mutex_unlock(mutex);
-
return available;
}
-bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex)
-{
+bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) {
(void) mutex;
-
(void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER);
// can only release the endpoint if it is claimed and not busy
bool const ret = (ep_state->claimed == 1) && (ep_state->busy == 0);
- if (ret)
- {
+ if (ret) {
ep_state->claimed = 0;
}
(void) osal_mutex_unlock(mutex);
-
return ret;
}
-bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed)
-{
+bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed) {
uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep);
TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size);
- switch (desc_ep->bmAttributes.xfer)
- {
- case TUSB_XFER_ISOCHRONOUS:
- {
+ switch (desc_ep->bmAttributes.xfer) {
+ case TUSB_XFER_ISOCHRONOUS: {
uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023);
TU_ASSERT(max_packet_size <= spec_size);
+ break;
}
- break;
case TUSB_XFER_BULK:
- if (speed == TUSB_SPEED_HIGH)
- {
+ if (speed == TUSB_SPEED_HIGH) {
// Bulk highspeed must be EXACTLY 512
TU_ASSERT(max_packet_size == 512);
- }else
- {
+ } else {
// TODO Bulk fullspeed can only be 8, 16, 32, 64
TU_ASSERT(max_packet_size <= 64);
}
- break;
+ break;
- case TUSB_XFER_INTERRUPT:
- {
+ case TUSB_XFER_INTERRUPT: {
uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64);
TU_ASSERT(max_packet_size <= spec_size);
+ break;
}
- break;
- default: return false;
+ default:
+ return false;
}
return true;
}
-void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id)
-{
+void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len,
+ uint8_t driver_id) {
uint8_t const* p_desc = (uint8_t const*) desc_itf;
uint8_t const* desc_end = p_desc + desc_len;
- while( p_desc < desc_end )
- {
- if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
- {
+ while (p_desc < desc_end) {
+ if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) {
uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress;
-
TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id);
ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id;
}
-
p_desc = tu_desc_next(p_desc);
}
}
-uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len)
-{
+uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) {
uint8_t const* p_desc = (uint8_t const*) desc_itf;
uint16_t len = 0;
- while (itf_count--)
- {
+ while (itf_count--) {
// Next on interface desc
len += tu_desc_len(desc_itf);
p_desc = tu_desc_next(p_desc);
- while (len < max_len)
- {
+ while (len < max_len) {
// return on IAD regardless of itf count
- if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len;
-
- if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
- ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 )
- {
+ if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) {
+ return len;
+ }
+ if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
+ ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0) {
break;
}
@@ -243,9 +215,8 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf,
//--------------------------------------------------------------------+
bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable,
- void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize)
-{
- osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutex);
+ void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) {
+ osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutexdef);
(void) new_mutex;
(void) is_tx;
@@ -259,92 +230,82 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove
return true;
}
+bool tu_edpt_stream_deinit(tu_edpt_stream_t* s) {
+ (void) s;
+ #if OSAL_MUTEX_REQUIRED
+ if (s->ff.mutex_wr) osal_mutex_delete(s->ff.mutex_wr);
+ if (s->ff.mutex_rd) osal_mutex_delete(s->ff.mutex_rd);
+ #endif
+ return true;
+}
+
TU_ATTR_ALWAYS_INLINE static inline
-bool stream_claim(tu_edpt_stream_t* s)
-{
- if (s->is_host)
- {
+bool stream_claim(tu_edpt_stream_t* s) {
+ if (s->is_host) {
#if CFG_TUH_ENABLED
return usbh_edpt_claim(s->daddr, s->ep_addr);
#endif
- }else
- {
+ } else {
#if CFG_TUD_ENABLED
return usbd_edpt_claim(s->rhport, s->ep_addr);
#endif
}
-
return false;
}
TU_ATTR_ALWAYS_INLINE static inline
-bool stream_xfer(tu_edpt_stream_t* s, uint16_t count)
-{
- if (s->is_host)
- {
+bool stream_xfer(tu_edpt_stream_t* s, uint16_t count) {
+ if (s->is_host) {
#if CFG_TUH_ENABLED
return usbh_edpt_xfer(s->daddr, s->ep_addr, count ? s->ep_buf : NULL, count);
#endif
- }else
- {
+ } else {
#if CFG_TUD_ENABLED
return usbd_edpt_xfer(s->rhport, s->ep_addr, count ? s->ep_buf : NULL, count);
#endif
}
-
return false;
}
TU_ATTR_ALWAYS_INLINE static inline
-bool stream_release(tu_edpt_stream_t* s)
-{
- if (s->is_host)
- {
+bool stream_release(tu_edpt_stream_t* s) {
+ if (s->is_host) {
#if CFG_TUH_ENABLED
return usbh_edpt_release(s->daddr, s->ep_addr);
#endif
- }else
- {
+ } else {
#if CFG_TUD_ENABLED
return usbd_edpt_release(s->rhport, s->ep_addr);
#endif
}
-
return false;
}
//--------------------------------------------------------------------+
// Stream Write
//--------------------------------------------------------------------+
-
-bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes)
-{
+bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes) {
// ZLP condition: no pending data, last transferred bytes is multiple of packet size
- TU_VERIFY( !tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (s->ep_packetsize-1))) );
-
- TU_VERIFY( stream_claim(s) );
- TU_ASSERT( stream_xfer(s, 0) );
-
+ TU_VERIFY(!tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (s->ep_packetsize - 1))));
+ TU_VERIFY(stream_claim(s));
+ TU_ASSERT(stream_xfer(s, 0));
return true;
}
-uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s)
-{
+uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) {
// skip if no data
- TU_VERIFY( tu_fifo_count(&s->ff), 0 );
+ TU_VERIFY(tu_fifo_count(&s->ff), 0);
// Claim the endpoint
- TU_VERIFY( stream_claim(s), 0 );
+ TU_VERIFY(stream_claim(s), 0);
// Pull data from FIFO -> EP buf
uint16_t const count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize);
- if ( count )
- {
- TU_ASSERT( stream_xfer(s, count), 0 );
+ if (count) {
+ TU_ASSERT(stream_xfer(s, count), 0);
return count;
- }else
- {
+ } else {
// Release endpoint since we don't make any transfer
// Note: data is dropped if terminal is not connected
stream_release(s);
@@ -352,16 +313,13 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s)
}
}
-uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize)
-{
+uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const* buffer, uint32_t bufsize) {
TU_VERIFY(bufsize); // TODO support ZLP
-
uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize);
// flush if fifo has more than packet size or
// in rare case: fifo depth is configured too small (which never reach packet size)
- if ( (tu_fifo_count(&s->ff) >= s->ep_packetsize) || (tu_fifo_depth(&s->ff) < s->ep_packetsize) )
- {
+ if ((tu_fifo_count(&s->ff) >= s->ep_packetsize) || (tu_fifo_depth(&s->ff) < s->ep_packetsize)) {
tu_edpt_stream_write_xfer(s);
}
@@ -371,9 +329,7 @@ uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const *buffer, uint32_t
//--------------------------------------------------------------------+
// Stream Read
//--------------------------------------------------------------------+
-
-uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s)
-{
+uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) {
uint16_t available = tu_fifo_remaining(&s->ff);
// Prepare for incoming data but only allow what we can store in the ring buffer.
@@ -388,25 +344,21 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s)
// get available again since fifo can be changed before endpoint is claimed
available = tu_fifo_remaining(&s->ff);
- if ( available >= s->ep_packetsize )
- {
+ if (available >= s->ep_packetsize) {
// multiple of packet size limit by ep bufsize
- uint16_t count = (uint16_t) (available & ~(s->ep_packetsize -1));
+ uint16_t count = (uint16_t) (available & ~(s->ep_packetsize - 1));
count = tu_min16(count, s->ep_bufsize);
- TU_ASSERT( stream_xfer(s, count), 0 );
-
+ TU_ASSERT(stream_xfer(s, count), 0);
return count;
- }else
- {
+ } else {
// Release endpoint since we don't make any transfer
stream_release(s);
return 0;
}
}
-uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize)
-{
+uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) {
uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t) bufsize);
tu_edpt_stream_read_xfer(s);
return num_read;
@@ -419,39 +371,36 @@ uint32_t tu_edpt_stream_read(tu_edpt_stream_t* s, void* buffer, uint32_t bufsize
#if CFG_TUSB_DEBUG
#include <ctype.h>
-#if CFG_TUSB_DEBUG >= 2
-
-char const* const tu_str_speed[] = { "Full", "Low", "High" };
-char const* const tu_str_std_request[] =
-{
- "Get Status" ,
- "Clear Feature" ,
- "Reserved" ,
- "Set Feature" ,
- "Reserved" ,
- "Set Address" ,
- "Get Descriptor" ,
- "Set Descriptor" ,
- "Get Configuration" ,
- "Set Configuration" ,
- "Get Interface" ,
- "Set Interface" ,
- "Synch Frame"
+#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL || CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
+char const* const tu_str_speed[] = {"Full", "Low", "High"};
+char const* const tu_str_std_request[] = {
+ "Get Status",
+ "Clear Feature",
+ "Reserved",
+ "Set Feature",
+ "Reserved",
+ "Set Address",
+ "Get Descriptor",
+ "Set Descriptor",
+ "Get Configuration",
+ "Set Configuration",
+ "Get Interface",
+ "Set Interface",
+ "Synch Frame"
};
+char const* const tu_str_xfer_result[] = {
+ "OK", "FAILED", "STALLED", "TIMEOUT"
+};
#endif
-static void dump_str_line(uint8_t const* buf, uint16_t count)
-{
+static void dump_str_line(uint8_t const* buf, uint16_t count) {
tu_printf(" |");
-
// each line is 16 bytes
- for(uint16_t i=0; i<count; i++)
- {
+ for (uint16_t i = 0; i < count; i++) {
const char ch = buf[i];
tu_printf("%c", isprint(ch) ? ch : '.');
}
-
tu_printf("|\r\n");
}
@@ -460,39 +409,27 @@ static void dump_str_line(uint8_t const* buf, uint16_t count)
* - count : number of item
* - indent: prefix spaces on every line
*/
-void tu_print_mem(void const *buf, uint32_t count, uint8_t indent)
-{
+void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) {
uint8_t const size = 1; // fixed 1 byte for now
-
- if ( !buf || !count )
- {
+ if (!buf || !count) {
tu_printf("NULL\r\n");
return;
}
- uint8_t const *buf8 = (uint8_t const *) buf;
-
+ uint8_t const* buf8 = (uint8_t const*) buf;
char format[] = "%00X";
- format[2] += 2*size;
-
- const uint8_t item_per_line = 16 / size;
+ format[2] += (uint8_t) (2 * size); // 1 byte = 2 hex digits
+ const uint8_t item_per_line = 16 / size;
- for(unsigned int i=0; i<count; i++)
- {
- unsigned int value=0;
+ for (unsigned int i = 0; i < count; i++) {
+ unsigned int value = 0;
- if ( i%item_per_line == 0 )
- {
+ if (i % item_per_line == 0) {
// Print Ascii
- if ( i != 0 )
- {
- dump_str_line(buf8-16, 16);
- }
-
- for(uint8_t s=0; s < indent; s++) tu_printf(" ");
-
+ if (i != 0) dump_str_line(buf8 - 16, 16);
+ for (uint8_t s = 0; s < indent; s++) tu_printf(" ");
// print offset or absolute address
- tu_printf("%04X: ", 16*i/item_per_line);
+ tu_printf("%04X: ", 16 * i / item_per_line);
}
tu_memcpy_s(&value, sizeof(value), buf8, size);
@@ -503,19 +440,16 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent)
}
// fill up last row to 16 for printing ascii
- const uint32_t remain = count%16;
- uint8_t nback = (uint8_t)(remain ? remain : 16);
-
- if ( remain )
- {
- for(uint32_t i=0; i< 16-remain; i++)
- {
+ const uint32_t remain = count % 16;
+ uint8_t nback = (uint8_t) (remain ? remain : 16);
+ if (remain) {
+ for (uint32_t i = 0; i < 16 - remain; i++) {
tu_printf(" ");
- for(int j=0; j<2*size; j++) tu_printf(" ");
+ for (int j = 0; j < 2 * size; j++) tu_printf(" ");
}
}
- dump_str_line(buf8-nback, nback);
+ dump_str_line(buf8 - nback, nback);
}
#endif
diff --git a/src/tusb.h b/src/tusb.h
index b776d7d01..c9d56d3c3 100644
--- a/src/tusb.h
+++ b/src/tusb.h
@@ -40,6 +40,11 @@
#include "class/hid/hid.h"
+//------------- TypeC -------------//
+#if CFG_TUC_ENABLED
+ #include "typec/usbc.h"
+#endif
+
//------------- HOST -------------//
#if CFG_TUH_ENABLED
#include "host/usbh.h"
@@ -59,7 +64,10 @@
#if CFG_TUH_VENDOR
#include "class/vendor/vendor_host.h"
#endif
-
+#else
+ #ifndef tuh_int_handler
+ #define tuh_int_handler(...)
+ #endif
#endif
//------------- DEVICE -------------//
@@ -113,6 +121,10 @@
#if CFG_TUD_BTH
#include "class/bth/bth_device.h"
#endif
+#else
+ #ifndef tud_int_handler
+ #define tud_int_handler(...)
+ #endif
#endif
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 4f3f3a985..cbcb69edd 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -29,9 +29,14 @@
#include "common/tusb_compiler.h"
+// Version is release as major.minor.revision eg 1.0.0. though there could be notable APIs before a new release.
+// For notable API changes within a release, we increase the build number.
#define TUSB_VERSION_MAJOR 0
-#define TUSB_VERSION_MINOR 15
+#define TUSB_VERSION_MINOR 16
#define TUSB_VERSION_REVISION 0
+#define TUSB_VERSION_BUILD 3
+
+#define TUSB_VERSION_NUMBER (TUSB_VERSION_MAJOR << 24 | TUSB_VERSION_MINOR << 16 | TUSB_VERSION_REVISION << 8 | TUSB_VERSION_BUILD)
#define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION)
//--------------------------------------------------------------------+
@@ -51,8 +56,11 @@
#define OPT_MCU_LPC40XX 7 ///< NXP LPC40xx
#define OPT_MCU_LPC43XX 8 ///< NXP LPC43xx
#define OPT_MCU_LPC51UXX 9 ///< NXP LPC51U6x
-#define OPT_MCU_LPC54XXX 10 ///< NXP LPC54xxx
-#define OPT_MCU_LPC55XX 11 ///< NXP LPC55xx
+#define OPT_MCU_LPC54 10 ///< NXP LPC54
+#define OPT_MCU_LPC55 11 ///< NXP LPC55
+// legacy naming
+#define OPT_MCU_LPC54XXX OPT_MCU_LPC54
+#define OPT_MCU_LPC55XX OPT_MCU_LPC55
// NRF
#define OPT_MCU_NRF5X 100 ///< Nordic nRF5x series
@@ -83,6 +91,7 @@
#define OPT_MCU_STM32WB 312 ///< ST WB
#define OPT_MCU_STM32U5 313 ///< ST U5
#define OPT_MCU_STM32L5 314 ///< ST L5
+#define OPT_MCU_STM32H5 315 ///< ST H5
// Sony
#define OPT_MCU_CXD56 400 ///< SONY CXD56
@@ -97,9 +106,9 @@
#define OPT_MCU_VALENTYUSB_EPTRI 600 ///< Fomu eptri config
// NXP iMX RT
-#define OPT_MCU_MIMXRT 700 ///< NXP iMX RT Series
-#define OPT_MCU_MIMXRT10XX OPT_MCU_MIMXRT ///< RT10xx
-#define OPT_MCU_MIMXRT11XX OPT_MCU_MIMXRT ///< RT11xx
+#define OPT_MCU_MIMXRT1XXX 700 ///< NXP iMX RT1xxx Series
+#define OPT_MCU_MIMXRT10XX OPT_MCU_MIMXRT1XXX ///< RT10xx
+#define OPT_MCU_MIMXRT11XX OPT_MCU_MIMXRT1XXX ///< RT11xx
// Nuvoton
#define OPT_MCU_NUC121 800
@@ -119,7 +128,9 @@
// NXP Kinetis
#define OPT_MCU_KINETIS_KL 1200 ///< NXP KL series
-#define OPT_MCU_KINETIS_K32 1201 ///< NXP K32 series
+#define OPT_MCU_KINETIS_K32L 1201 ///< NXP K32L series
+#define OPT_MCU_KINETIS_K32 1201 ///< Alias to K32L
+#define OPT_MCU_KINETIS_K 1202 ///< NXP K series
#define OPT_MCU_MKL25ZXX 1200 ///< Alias to KL (obsolete)
#define OPT_MCU_K32L2BXX 1201 ///< Alias to K32 (obsolete)
@@ -133,7 +144,6 @@
#define OPT_MCU_RX72N 1402 ///< Renesas RX72N
#define OPT_MCU_RAXXX 1403 ///< Renesas RAxxx families
-
// Mind Motion
#define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327
@@ -165,11 +175,17 @@
// WCH
#define OPT_MCU_CH32V307 2200 ///< WCH CH32V307
+#define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x
+
-// Helper to check if configured MCU is one of listed
+// NXP LPC MCX
+#define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series
+#define OPT_MCU_MCXA15 2301 ///< NXP MCX A15 Series
+
+// Check if configured MCU is one of listed
// Apply _TU_CHECK_MCU with || as separator to list of input
-#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m)
-#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__))
+#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m)
+#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__))
//--------------------------------------------------------------------+
// Supported OS
@@ -274,7 +290,7 @@
// In case TUP_MCU_STRICT_ALIGN = 1 and TUP_ARCH_STRICT_ALIGN =0, we will not reply on compiler
// to generate unaligned access code.
// LPC_IP3511 Highspeed cannot access unaligned memory on USB_RAM
-#if TUD_OPT_HIGH_SPEED && (CFG_TUSB_MCU == OPT_MCU_LPC54XXX || CFG_TUSB_MCU == OPT_MCU_LPC55XX)
+#if TUD_OPT_HIGH_SPEED && TU_CHECK_MCU(OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX)
#define TUP_MCU_STRICT_ALIGN 1
#else
#define TUP_MCU_STRICT_ALIGN 0
@@ -290,15 +306,24 @@
#define CFG_TUSB_DEBUG 0
#endif
-// TODO MEM_SECTION can be different for host and device controller
-// should use CFG_TUD_MEM_SECTION, CFG_TUH_MEM_SECTION
+// Level where CFG_TUSB_DEBUG must be at least for USBH is logged
+#ifndef CFG_TUH_LOG_LEVEL
+ #define CFG_TUH_LOG_LEVEL 2
+#endif
+
+// Level where CFG_TUSB_DEBUG must be at least for USBD is logged
+#ifndef CFG_TUD_LOG_LEVEL
+ #define CFG_TUD_LOG_LEVEL 2
+#endif
+
+// Memory section for placing buffer used for usb transferring. If MEM_SECTION is different for
+// host and device use: CFG_TUD_MEM_SECTION, CFG_TUH_MEM_SECTION instead
#ifndef CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_SECTION
#endif
-// alignment requirement of buffer used for endpoint transferring
-// TODO MEM_ALIGN can be different for host and device controller
-// should use CFG_TUD_MEM_ALIGN, CFG_TUH_MEM_ALIGN
+// Alignment requirement of buffer used for usb transferring. if MEM_ALIGN is different for
+// host and device controller use: CFG_TUD_MEM_ALIGN, CFG_TUH_MEM_ALIGN instead
#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4)
#endif
@@ -316,24 +341,14 @@
// Device Options (Default)
//--------------------------------------------------------------------
-// Attribute to place data in accessible RAM for device controller
-// default to CFG_TUSB_MEM_SECTION for backward-compatible
+// Attribute to place data in accessible RAM for device controller (default: CFG_TUSB_MEM_SECTION)
#ifndef CFG_TUD_MEM_SECTION
- #ifdef CFG_TUSB_MEM_SECTION
- #define CFG_TUD_MEM_SECTION CFG_TUSB_MEM_SECTION
- #else
- #define CFG_TUD_MEM_SECTION
- #endif
+ #define CFG_TUD_MEM_SECTION CFG_TUSB_MEM_SECTION
#endif
-// Attribute to align memory for device controller
-// default to CFG_TUSB_MEM_ALIGN for backward-compatible
+// Attribute to align memory for device controller (default: CFG_TUSB_MEM_ALIGN)
#ifndef CFG_TUD_MEM_ALIGN
- #ifdef CFG_TUSB_MEM_ALIGN
- #define CFG_TUD_MEM_ALIGN CFG_TUSB_MEM_ALIGN
- #else
- #define CFG_TUD_MEM_ALIGN TU_ATTR_ALIGNED(4)
- #endif
+ #define CFG_TUD_MEM_ALIGN CFG_TUSB_MEM_ALIGN
#endif
#ifndef CFG_TUD_ENDPOINT0_SIZE
@@ -344,6 +359,15 @@
#define CFG_TUD_INTERFACE_MAX 16
#endif
+//------------- Device Class Driver -------------//
+#ifndef CFG_TUD_BTH
+ #define CFG_TUD_BTH 0
+#endif
+
+#if CFG_TUD_BTH && !defined(CFG_TUD_BTH_ISO_ALT_COUNT)
+#error CFG_TUD_BTH_ISO_ALT_COUNT must be defined to tell Bluetooth driver the number of ISO endpoints to use
+#endif
+
#ifndef CFG_TUD_CDC
#define CFG_TUD_CDC 0
#endif
@@ -384,10 +408,6 @@
#define CFG_TUD_DFU 0
#endif
-#ifndef CFG_TUD_BTH
- #define CFG_TUD_BTH 0
-#endif
-
#ifndef CFG_TUD_ECM_RNDIS
#ifdef CFG_TUD_NET
#warning "CFG_TUD_NET is renamed to CFG_TUD_ECM_RNDIS"
@@ -414,29 +434,24 @@
#endif
#endif // CFG_TUH_ENABLED
-// Attribute to place data in accessible RAM for host controller
-// default to CFG_TUSB_MEM_SECTION for backward-compatible
+// Attribute to place data in accessible RAM for host controller (default: CFG_TUSB_MEM_SECTION)
#ifndef CFG_TUH_MEM_SECTION
- #ifdef CFG_TUSB_MEM_SECTION
- #define CFG_TUH_MEM_SECTION CFG_TUSB_MEM_SECTION
- #else
- #define CFG_TUH_MEM_SECTION
- #endif
+ #define CFG_TUH_MEM_SECTION CFG_TUSB_MEM_SECTION
#endif
// Attribute to align memory for host controller
#ifndef CFG_TUH_MEM_ALIGN
- #define CFG_TUH_MEM_ALIGN TU_ATTR_ALIGNED(4)
+ #define CFG_TUH_MEM_ALIGN CFG_TUSB_MEM_ALIGN
#endif
//------------- CLASS -------------//
#ifndef CFG_TUH_HUB
-#define CFG_TUH_HUB 0
+ #define CFG_TUH_HUB 0
#endif
#ifndef CFG_TUH_CDC
-#define CFG_TUH_CDC 0
+ #define CFG_TUH_CDC 0
#endif
#ifndef CFG_TUH_CDC_FTDI
@@ -444,40 +459,85 @@
#define CFG_TUH_CDC_FTDI 0
#endif
+#ifndef CFG_TUH_CDC_FTDI_VID_PID_LIST
+ // List of product IDs that can use the FTDI CDC driver. 0x0403 is FTDI's VID
+ #define CFG_TUH_CDC_FTDI_VID_PID_LIST \
+ {0x0403, 0x6001}, {0x0403, 0x6006}, {0x0403, 0x6010}, {0x0403, 0x6011}, \
+ {0x0403, 0x6014}, {0x0403, 0x6015}, {0x0403, 0x8372}, {0x0403, 0xFBFA}, \
+ {0x0403, 0xCD18}
+#endif
+
#ifndef CFG_TUH_CDC_CP210X
// CP210X is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_CP210X 0
#endif
+#ifndef CFG_TUH_CDC_CP210X_VID_PID_LIST
+ // List of product IDs that can use the CP210X CDC driver. 0x10C4 is Silicon Labs' VID
+ #define CFG_TUH_CDC_CP210X_VID_PID_LIST \
+ {0x10C4, 0xEA60}, {0x10C4, 0xEA70}
+#endif
+
+#ifndef CFG_TUH_CDC_CH34X
+ // CH34X is not part of CDC class, only to re-use CDC driver API
+ #define CFG_TUH_CDC_CH34X 0
+#endif
+
+#ifndef CFG_TUH_CDC_CH34X_VID_PID_LIST
+ // List of product IDs that can use the CH34X CDC driver
+ #define CFG_TUH_CDC_CH34X_VID_PID_LIST \
+ { 0x1a86, 0x5523 }, /* ch341 chip */ \
+ { 0x1a86, 0x7522 }, /* ch340k chip */ \
+ { 0x1a86, 0x7523 }, /* ch340 chip */ \
+ { 0x1a86, 0xe523 }, /* ch330 chip */ \
+ { 0x4348, 0x5523 }, /* ch340 custom chip */ \
+ { 0x2184, 0x0057 }, /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ \
+ { 0x9986, 0x7523 } /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */
+#endif
+
#ifndef CFG_TUH_HID
-#define CFG_TUH_HID 0
+ #define CFG_TUH_HID 0
#endif
#ifndef CFG_TUH_MIDI
-#define CFG_TUH_MIDI 0
+ #define CFG_TUH_MIDI 0
#endif
#ifndef CFG_TUH_MSC
-#define CFG_TUH_MSC 0
+ #define CFG_TUH_MSC 0
#endif
#ifndef CFG_TUH_VENDOR
-#define CFG_TUH_VENDOR 0
+ #define CFG_TUH_VENDOR 0
#endif
#ifndef CFG_TUH_API_EDPT_XFER
-#define CFG_TUH_API_EDPT_XFER 0
+ #define CFG_TUH_API_EDPT_XFER 0
#endif
// Enable PIO-USB software host controller
#ifndef CFG_TUH_RPI_PIO_USB
-#define CFG_TUH_RPI_PIO_USB 0
+ #define CFG_TUH_RPI_PIO_USB 0
#endif
#ifndef CFG_TUD_RPI_PIO_USB
-#define CFG_TUD_RPI_PIO_USB 0
+ #define CFG_TUD_RPI_PIO_USB 0
#endif
+// MAX3421 Host controller option
+#ifndef CFG_TUH_MAX3421
+ #define CFG_TUH_MAX3421 0
+#endif
+
+//--------------------------------------------------------------------+
+// TypeC Options (Default)
+//--------------------------------------------------------------------+
+
+#ifndef CFG_TUC_ENABLED
+#define CFG_TUC_ENABLED 0
+
+#define tuc_int_handler(_p)
+#endif
//------------------------------------------------------------------
// Configuration Validation
diff --git a/src/typec/pd_types.h b/src/typec/pd_types.h
new file mode 100644
index 000000000..1b2968f65
--- /dev/null
+++ b/src/typec/pd_types.h
@@ -0,0 +1,237 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _TUSB_PD_TYPES_H_
+#define _TUSB_PD_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "common/tusb_compiler.h"
+
+// Start of all packed definitions for compiler without per-type packed
+TU_ATTR_PACKED_BEGIN
+TU_ATTR_BIT_FIELD_ORDER_BEGIN
+
+//--------------------------------------------------------------------+
+// TYPE-C
+//--------------------------------------------------------------------+
+
+typedef enum {
+ TUSB_TYPEC_PORT_SRC,
+ TUSB_TYPEC_PORT_SNK,
+ TUSB_TYPEC_PORT_DRP
+} tusb_typec_port_type_t;
+
+enum {
+ PD_CTRL_RESERVED = 0, // 0b00000: 0
+ PD_CTRL_GOOD_CRC, // 0b00001: 1
+ PD_CTRL_GO_TO_MIN, // 0b00010: 2
+ PD_CTRL_ACCEPT, // 0b00011: 3
+ PD_CTRL_REJECT, // 0b00100: 4
+ PD_CTRL_PING, // 0b00101: 5
+ PD_CTRL_PS_READY, // 0b00110: 6
+ PD_CTRL_GET_SOURCE_CAP, // 0b00111: 7
+ PD_CTRL_GET_SINK_CAP, // 0b01000: 8
+ PD_CTRL_DR_SWAP, // 0b01001: 9
+ PD_CTRL_PR_SWAP, // 0b01010: 10
+ PD_CTRL_VCONN_SWAP, // 0b01011: 11
+ PD_CTRL_WAIT, // 0b01100: 12
+ PD_CTRL_SOFT_RESET, // 0b01101: 13
+ PD_CTRL_DATA_RESET, // 0b01110: 14
+ PD_CTRL_DATA_RESET_COMPLETE, // 0b01111: 15
+ PD_CTRL_NOT_SUPPORTED, // 0b10000: 16
+ PD_CTRL_GET_SOURCE_CAP_EXTENDED, // 0b10001: 17
+ PD_CTRL_GET_STATUS, // 0b10010: 18
+ PD_CTRL_FR_SWAP, // 0b10011: 19
+ PD_CTRL_GET_PPS_STATUS, // 0b10100: 20
+ PD_CTRL_GET_COUNTRY_CODES, // 0b10101: 21
+ PD_CTRL_GET_SINK_CAP_EXTENDED, // 0b10110: 22
+ PD_CTRL_GET_SOURCE_INFO, // 0b10111: 23
+ PD_CTRL_REVISION, // 0b11000: 24
+};
+
+enum {
+ PD_DATA_RESERVED = 0, // 0b00000: 0
+ PD_DATA_SOURCE_CAP, // 0b00001: 1
+ PD_DATA_REQUEST, // 0b00010: 2
+ PD_DATA_BIST, // 0b00011: 3
+ PD_DATA_SINK_CAP, // 0b00100: 4
+ PD_DATA_BATTERY_STATUS, // 0b00101: 5
+ PD_DATA_ALERT, // 0b00110: 6
+ PD_DATA_GET_COUNTRY_INFO, // 0b00111: 7
+ PD_DATA_ENTER_USB, // 0b01000: 8
+ PD_DATA_EPR_REQUEST, // 0b01001: 9
+ PD_DATA_EPR_MODE, // 0b01010: 10
+ PD_DATA_SRC_INFO, // 0b01011: 11
+ PD_DATA_REVISION, // 0b01100: 12
+ PD_DATA_RESERVED_13, // 0b01101: 13
+ PD_DATA_RESERVED_14, // 0b01110: 14
+ PD_DATA_VENDOR_DEFINED, // 0b01111: 15
+};
+
+enum {
+ PD_REV_10 = 0x0,
+ PD_REV_20 = 0x1,
+ PD_REV_30 = 0x2,
+};
+
+enum {
+ PD_DATA_ROLE_UFP = 0x0,
+ PD_DATA_ROLE_DFP = 0x1,
+};
+
+enum {
+ PD_POWER_ROLE_SINK = 0x0,
+ PD_POWER_ROLE_SOURCE = 0x1,
+};
+
+typedef struct TU_ATTR_PACKED {
+ uint16_t msg_type : 5; // [0:4]
+ uint16_t data_role : 1; // [5] SOP only: 0 UFP, 1 DFP
+ uint16_t specs_rev : 2; // [6:7]
+ uint16_t power_role : 1; // [8] SOP only: 0 Sink, 1 Source
+ uint16_t msg_id : 3; // [9:11]
+ uint16_t n_data_obj : 3; // [12:14]
+ uint16_t extended : 1; // [15]
+} pd_header_t;
+TU_VERIFY_STATIC(sizeof(pd_header_t) == 2, "size is not correct");
+
+typedef struct TU_ATTR_PACKED {
+ uint16_t data_size : 9; // [0:8]
+ uint16_t reserved : 1; // [9]
+ uint16_t request_chunk : 1; // [10]
+ uint16_t chunk_number : 4; // [11:14]
+ uint16_t chunked : 1; // [15]
+} pd_header_extended_t;
+TU_VERIFY_STATIC(sizeof(pd_header_extended_t) == 2, "size is not correct");
+
+//--------------------------------------------------------------------+
+// Source Capability
+//--------------------------------------------------------------------+
+
+// All table references are from USBPD Specification rev3.1 version 1.8
+enum {
+ PD_PDO_TYPE_FIXED = 0, // Vmin = Vmax
+ PD_PDO_TYPE_BATTERY,
+ PD_PDO_TYPE_VARIABLE, // non-battery
+ PD_PDO_TYPE_APDO, // Augmented Power Data Object
+};
+
+// Fixed Power Data Object (PDO) table 6-9
+typedef struct TU_ATTR_PACKED {
+ uint32_t current_max_10ma : 10; // [9..0] Max current in 10mA unit
+ uint32_t voltage_50mv : 10; // [19..10] Voltage in 50mV unit
+ uint32_t current_peak : 2; // [21..20] Peak current
+ uint32_t reserved : 1; // [22] Reserved
+ uint32_t epr_mode_capable : 1; // [23] epr_mode_capable
+ uint32_t unchunked_ext_msg_support : 1; // [24] UnChunked Extended Message Supported
+ uint32_t dual_role_data : 1; // [25] Dual Role Data
+ uint32_t usb_comm_capable : 1; // [26] USB Communications Capable
+ uint32_t unconstrained_power : 1; // [27] Unconstrained Power
+ uint32_t usb_suspend_supported : 1; // [28] USB Suspend Supported
+ uint32_t dual_role_power : 1; // [29] Dual Role Power
+ uint32_t type : 2; // [30] Fixed Supply type = PD_PDO_TYPE_FIXED
+} pd_pdo_fixed_t;
+TU_VERIFY_STATIC(sizeof(pd_pdo_fixed_t) == 4, "Invalid size");
+
+// Battery Power Data Object (PDO) table 6-12
+typedef struct TU_ATTR_PACKED {
+ uint32_t power_max_250mw : 10; // [9..0] Max allowable power in 250mW unit
+ uint32_t voltage_min_50mv : 10; // [19..10] Minimum voltage in 50mV unit
+ uint32_t voltage_max_50mv : 10; // [29..20] Maximum voltage in 50mV unit
+ uint32_t type : 2; // [31..30] Battery type = PD_PDO_TYPE_BATTERY
+} pd_pdo_battery_t;
+TU_VERIFY_STATIC(sizeof(pd_pdo_battery_t) == 4, "Invalid size");
+
+// Variable Power Data Object (PDO) table 6-11
+typedef struct TU_ATTR_PACKED {
+ uint32_t current_max_10ma : 10; // [9..0] Max current in 10mA unit
+ uint32_t voltage_min_50mv : 10; // [19..10] Minimum voltage in 50mV unit
+ uint32_t voltage_max_50mv : 10; // [29..20] Maximum voltage in 50mV unit
+ uint32_t type : 2; // [31..30] Variable Supply type = PD_PDO_TYPE_VARIABLE
+} pd_pdo_variable_t;
+TU_VERIFY_STATIC(sizeof(pd_pdo_variable_t) == 4, "Invalid size");
+
+// Augmented Power Data Object (PDO) table 6-13
+typedef struct TU_ATTR_PACKED {
+ uint32_t current_max_50ma : 7; // [6..0] Max current in 50mA unit
+ uint32_t reserved1 : 1; // [7] Reserved
+ uint32_t voltage_min_100mv : 8; // [15..8] Minimum Voltage in 100mV unit
+ uint32_t reserved2 : 1; // [16] Reserved
+ uint32_t voltage_max_100mv : 8; // [24..17] Maximum Voltage in 100mV unit
+ uint32_t reserved3 : 2; // [26..25] Reserved
+ uint32_t pps_power_limited : 1; // [27] PPS Power Limited
+ uint32_t spr_programmable : 2; // [29..28] SPR Programmable Power Supply
+ uint32_t type : 2; // [31..30] Augmented Power Data Object = PD_PDO_TYPE_APDO
+} pd_pdo_apdo_t;
+TU_VERIFY_STATIC(sizeof(pd_pdo_apdo_t) == 4, "Invalid size");
+
+//--------------------------------------------------------------------+
+// Request
+//--------------------------------------------------------------------+
+
+typedef struct TU_ATTR_PACKED {
+ uint32_t current_extremum_10ma : 10; // [9..0] Max (give back = 0) or Min (give back = 1) current in 10mA unit
+ uint32_t current_operate_10ma : 10; // [19..10] Operating current in 10mA unit
+ uint32_t reserved : 2; // [21..20] Reserved
+ uint32_t epr_mode_capable : 1; // [22] EPR mode capable
+ uint32_t unchunked_ext_msg_support : 1; // [23] UnChunked Extended Message Supported
+ uint32_t no_usb_suspend : 1; // [24] No USB Suspend
+ uint32_t usb_comm_capable : 1; // [25] USB Communications Capable
+ uint32_t capability_mismatch : 1; // [26] Capability Mismatch
+ uint32_t give_back_flag : 1; // [27] GiveBack Flag: 0 = Max, 1 = Min
+ uint32_t object_position : 4; // [31..28] Object Position
+} pd_rdo_fixed_variable_t;
+TU_VERIFY_STATIC(sizeof(pd_rdo_fixed_variable_t) == 4, "Invalid size");
+
+typedef struct TU_ATTR_PACKED {
+ uint32_t power_extremum_250mw : 10; // [9..0] Max (give back = 0) or Min (give back = 1) operating power in 250mW unit
+ uint32_t power_operate_250mw : 10; // [19..10] Operating power in 250mW unit
+ uint32_t reserved : 2; // [21..20] Reserved
+ uint32_t epr_mode_capable : 1; // [22] EPR mode capable
+ uint32_t unchunked_ext_msg_support : 1; // [23] UnChunked Extended Message Supported
+ uint32_t no_usb_suspend : 1; // [24] No USB Suspend
+ uint32_t usb_comm_capable : 1; // [25] USB Communications Capable
+ uint32_t capability_mismatch : 1; // [26] Capability Mismatch
+ uint32_t give_back_flag : 1; // [27] GiveBack Flag: 0 = Max, 1 = Min
+ uint32_t object_position : 4; // [31..28] Object Position
+} pd_rdo_battery_t;
+TU_VERIFY_STATIC(sizeof(pd_rdo_battery_t) == 4, "Invalid size");
+
+
+TU_ATTR_PACKED_END // End of all packed definitions
+TU_ATTR_BIT_FIELD_ORDER_END
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/typec/tcd.h b/src/typec/tcd.h
new file mode 100644
index 000000000..86499c951
--- /dev/null
+++ b/src/typec/tcd.h
@@ -0,0 +1,143 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach ([email protected]) for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _TUSB_TCD_H_
+#define _TUSB_TCD_H_
+
+#include "common/tusb_common.h"
+#include "pd_types.h"
+
+#include "osal/osal.h"
+#include "common/tusb_fifo.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+enum {
+ TCD_EVENT_INVALID = 0,
+ TCD_EVENT_CC_CHANGED,
+ TCD_EVENT_RX_COMPLETE,
+ TCD_EVENT_TX_COMPLETE,
+};
+
+typedef struct TU_ATTR_PACKED {
+ uint8_t rhport;
+ uint8_t event_id;
+
+ union {
+ struct {
+ uint8_t cc_state[2];
+ } cc_changed;
+
+ struct TU_ATTR_PACKED {
+ uint16_t result : 2;
+ uint16_t xferred_bytes : 14;
+ } xfer_complete;
+ };
+
+} tcd_event_t;;
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+// Initialize controller
+bool tcd_init(uint8_t rhport, uint32_t port_type);
+
+// Enable interrupt
+void tcd_int_enable (uint8_t rhport);
+
+// Disable interrupt
+void tcd_int_disable(uint8_t rhport);
+
+// Interrupt Handler
+void tcd_int_handler(uint8_t rhport);
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+bool tcd_msg_receive(uint8_t rhport, uint8_t* buffer, uint16_t total_bytes);
+bool tcd_msg_send(uint8_t rhport, uint8_t const* buffer, uint16_t total_bytes);
+
+//--------------------------------------------------------------------+
+// Event API (implemented by stack)
+// Called by TCD to notify stack
+//--------------------------------------------------------------------+
+
+extern void tcd_event_handler(tcd_event_t const * event, bool in_isr);
+
+TU_ATTR_ALWAYS_INLINE static inline
+void tcd_event_cc_changed(uint8_t rhport, uint8_t cc1, uint8_t cc2, bool in_isr) {
+ tcd_event_t event = {
+ .rhport = rhport,
+ .event_id = TCD_EVENT_CC_CHANGED,
+ .cc_changed = {
+ .cc_state = {cc1, cc2 }
+ }
+ };
+
+ tcd_event_handler(&event, in_isr);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline
+void tcd_event_rx_complete(uint8_t rhport, uint16_t xferred_bytes, uint8_t result, bool in_isr) {
+ tcd_event_t event = {
+ .rhport = rhport,
+ .event_id = TCD_EVENT_RX_COMPLETE,
+ .xfer_complete = {
+ .xferred_bytes = xferred_bytes,
+ .result = result
+ }
+ };
+
+ tcd_event_handler(&event, in_isr);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline
+void tcd_event_tx_complete(uint8_t rhport, uint16_t xferred_bytes, uint8_t result, bool in_isr) {
+ tcd_event_t event = {
+ .rhport = rhport,
+ .event_id = TCD_EVENT_TX_COMPLETE,
+ .xfer_complete = {
+ .xferred_bytes = xferred_bytes,
+ .result = result
+ }
+ };
+
+ tcd_event_handler(&event, in_isr);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/typec/usbc.c b/src/typec/usbc.c
new file mode 100644
index 000000000..fdf2a0cd6
--- /dev/null
+++ b/src/typec/usbc.c
@@ -0,0 +1,219 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach ([email protected])
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+#if CFG_TUC_ENABLED
+
+#include "tcd.h"
+#include "usbc.h"
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+// Debug level of USBD
+#define USBC_DEBUG 2
+#define TU_LOG_USBC(...) TU_LOG(USBC_DEBUG, __VA_ARGS__)
+
+// Event queue
+// usbc_int_set() is used as mutex in OS NONE config
+void usbc_int_set(bool enabled);
+OSAL_QUEUE_DEF(usbc_int_set, _usbc_qdef, CFG_TUC_TASK_QUEUE_SZ, tcd_event_t);
+tu_static osal_queue_t _usbc_q;
+
+// if stack is initialized
+static bool _usbc_inited = false;
+
+// if port is initialized
+static bool _port_inited[TUP_TYPEC_RHPORTS_NUM];
+
+// Max possible PD size is 262 bytes
+static uint8_t _rx_buf[64] TU_ATTR_ALIGNED(4);
+static uint8_t _tx_buf[64] TU_ATTR_ALIGNED(4);
+
+bool usbc_msg_send(uint8_t rhport, pd_header_t const* header, void const* data);
+bool parse_msg_data(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end);
+bool parse_msg_control(uint8_t rhport, pd_header_t const* header);
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+bool tuc_inited(uint8_t rhport) {
+ return _usbc_inited && _port_inited[rhport];
+}
+
+bool tuc_init(uint8_t rhport, uint32_t port_type) {
+ // Initialize stack
+ if (!_usbc_inited) {
+ tu_memclr(_port_inited, sizeof(_port_inited));
+
+ _usbc_q = osal_queue_create(&_usbc_qdef);
+ TU_ASSERT(_usbc_q != NULL);
+
+ _usbc_inited = true;
+ }
+
+ // skip if port already initialized
+ if ( _port_inited[rhport] ) {
+ return true;
+ }
+
+ TU_LOG_USBC("USBC init on port %u\r\n", rhport);
+ TU_LOG_INT(USBC_DEBUG, sizeof(tcd_event_t));
+
+ TU_ASSERT(tcd_init(rhport, port_type));
+ tcd_int_enable(rhport);
+
+ _port_inited[rhport] = true;
+ return true;
+}
+
+void tuc_task_ext(uint32_t timeout_ms, bool in_isr) {
+ (void) in_isr; // not implemented yet
+
+ // Skip if stack is not initialized
+ if (!_usbc_inited) return;
+
+ // Loop until there is no more events in the queue
+ while (1) {
+ tcd_event_t event;
+ if (!osal_queue_receive(_usbc_q, &event, timeout_ms)) return;
+
+ switch (event.event_id) {
+ case TCD_EVENT_CC_CHANGED:
+ break;
+
+ case TCD_EVENT_RX_COMPLETE:
+ // TODO process message here in ISR, move to thread later
+ if (event.xfer_complete.result == XFER_RESULT_SUCCESS) {
+ pd_header_t const* header = (pd_header_t const*) _rx_buf;
+
+ if (header->n_data_obj == 0) {
+ parse_msg_control(event.rhport, header);
+
+ }else {
+ uint8_t const* p_end = _rx_buf + event.xfer_complete.xferred_bytes;
+ uint8_t const * dobj = _rx_buf + sizeof(pd_header_t);
+
+ parse_msg_data(event.rhport, header, dobj, p_end);
+ }
+ }
+
+ // prepare for next message
+ tcd_msg_receive(event.rhport, _rx_buf, sizeof(_rx_buf));
+ break;
+
+ case TCD_EVENT_TX_COMPLETE:
+ break;
+
+ default: break;
+ }
+ }
+}
+
+bool parse_msg_data(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end) {
+ if (tuc_pd_data_received_cb) {
+ tuc_pd_data_received_cb(rhport, header, dobj, p_end);
+ }
+
+ return true;
+}
+
+bool parse_msg_control(uint8_t rhport, pd_header_t const* header) {
+ if (tuc_pd_control_received_cb) {
+ tuc_pd_control_received_cb(rhport, header);
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+bool usbc_msg_send(uint8_t rhport, pd_header_t const* header, void const* data) {
+ // copy header
+ memcpy(_tx_buf, header, sizeof(pd_header_t));
+
+ // copy data objcet if available
+ uint16_t const n_data_obj = header->n_data_obj;
+ if (n_data_obj > 0) {
+ memcpy(_tx_buf + sizeof(pd_header_t), data, n_data_obj * 4);
+ }
+
+ return tcd_msg_send(rhport, _tx_buf, sizeof(pd_header_t) + n_data_obj * 4);
+}
+
+bool tuc_msg_request(uint8_t rhport, void const* rdo) {
+ pd_header_t const header = {
+ .msg_type = PD_DATA_REQUEST,
+ .data_role = PD_DATA_ROLE_UFP,
+ .specs_rev = PD_REV_30,
+ .power_role = PD_POWER_ROLE_SINK,
+ .msg_id = 0,
+ .n_data_obj = 1,
+ .extended = 0,
+ };
+
+ return usbc_msg_send(rhport, &header, rdo);
+}
+
+void tcd_event_handler(tcd_event_t const * event, bool in_isr) {
+ (void) in_isr;
+ switch(event->event_id) {
+ case TCD_EVENT_CC_CHANGED:
+ if (event->cc_changed.cc_state[0] || event->cc_changed.cc_state[1]) {
+ // Attach, start receiving
+ tcd_msg_receive(event->rhport, _rx_buf, sizeof(_rx_buf));
+ }else {
+ // Detach
+ }
+ break;
+
+ default: break;
+ }
+
+ osal_queue_send(_usbc_q, event, in_isr);
+}
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+void usbc_int_set(bool enabled) {
+ // Disable all controllers since they shared the same event queue
+ for (uint8_t p = 0; p < TUP_TYPEC_RHPORTS_NUM; p++) {
+ if ( _port_inited[p] ) {
+ if (enabled) {
+ tcd_int_enable(p);
+ }else {
+ tcd_int_disable(p);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/src/typec/usbc.h b/src/typec/usbc.h
new file mode 100644
index 000000000..9fbff9bc6
--- /dev/null
+++ b/src/typec/usbc.h
@@ -0,0 +1,91 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _TUSB_UTCD_H_
+#define _TUSB_UTCD_H_
+
+#include "common/tusb_common.h"
+#include "pd_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// TypeC Configuration
+//--------------------------------------------------------------------+
+
+#ifndef CFG_TUC_TASK_QUEUE_SZ
+#define CFG_TUC_TASK_QUEUE_SZ 8
+#endif
+
+//--------------------------------------------------------------------+
+// Application API
+//--------------------------------------------------------------------+
+
+// Init typec stack on a port
+bool tuc_init(uint8_t rhport, uint32_t port_type);
+
+// Check if typec port is initialized
+bool tuc_inited(uint8_t rhport);
+
+// Task function should be called in main/rtos loop, extended version of tud_task()
+// - timeout_ms: millisecond to wait, zero = no wait, 0xFFFFFFFF = wait forever
+// - in_isr: if function is called in ISR
+void tuc_task_ext(uint32_t timeout_ms, bool in_isr);
+
+// Task function should be called in main/rtos loop
+TU_ATTR_ALWAYS_INLINE static inline
+void tuc_task (void) {
+ tuc_task_ext(UINT32_MAX, false);
+}
+
+#ifndef _TUSB_TCD_H_
+extern void tcd_int_handler(uint8_t rhport);
+#endif
+
+// Interrupt handler, name alias to TCD
+#define tuc_int_handler tcd_int_handler
+
+//--------------------------------------------------------------------+
+// Callbacks
+//--------------------------------------------------------------------+
+
+TU_ATTR_WEAK bool tuc_pd_data_received_cb(uint8_t rhport, pd_header_t const* header, uint8_t const* dobj, uint8_t const* p_end);
+TU_ATTR_WEAK bool tuc_pd_control_received_cb(uint8_t rhport, pd_header_t const* header);
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+bool tuc_msg_request(uint8_t rhport, void const* rdo);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif