summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2024-05-31 12:38:18 +0200
committerHiFiPhile <[email protected]>2024-05-31 12:38:18 +0200
commitb0f5422262a26fb1ab496e33bb8009efb6660788 (patch)
treedfd2570838592e9b822e701097f18b753f32bca6 /src
parent67456357c54ee81e8418a9e814df774b1a3dee85 (diff)
parentd10b65ada4be7d5754b3128e80a9b4db72bdb23f (diff)
Merge branch 'master' of https://github.com/hathach/tinyusb into rx_fb
Diffstat (limited to 'src')
-rw-r--r--src/common/tusb_compiler.h1
-rw-r--r--src/common/tusb_mcu.h60
-rw-r--r--src/device/dcd.h33
-rw-r--r--src/device/usbd.c91
-rw-r--r--src/device/usbd.h4
-rw-r--r--src/portable/analog/max3421/hcd_max3421.c80
-rw-r--r--src/portable/chipidea/ci_hs/dcd_ci_hs.c13
-rw-r--r--src/portable/espressif/esp32sx/dcd_esp32sx.c3
-rw-r--r--src/portable/microchip/samd/dcd_samd.c11
-rw-r--r--src/portable/nordic/nrf5x/dcd_nrf5x.c28
-rw-r--r--src/portable/renesas/rusb2/dcd_rusb2.c40
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c214
-rw-r--r--src/portable/st/stm32_fsdev/fsdev_ch32.h232
-rw-r--r--src/portable/st/stm32_fsdev/fsdev_common.h (renamed from src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h)248
-rw-r--r--src/portable/st/stm32_fsdev/fsdev_stm32.h292
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c21
-rw-r--r--src/portable/synopsys/dwc2/dwc2_type.h33
-rw-r--r--src/portable/wch/ch32_usbfs_reg.h111
-rw-r--r--src/portable/wch/ch32_usbhs_reg.h70
-rw-r--r--src/portable/wch/dcd_ch32_usbfs.c344
-rw-r--r--src/portable/wch/dcd_ch32_usbhs.c568
-rw-r--r--src/tusb_option.h72
22 files changed, 1738 insertions, 831 deletions
diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h
index 0d5570b1c..ce5566ffe 100644
--- a/src/common/tusb_compiler.h
+++ b/src/common/tusb_compiler.h
@@ -128,6 +128,7 @@
#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_WEAK_ALIAS(f) __attribute__ ((weak, alias(#f))
#ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug
#define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
#endif
diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h
index 4e3b89262..c66996c4f 100644
--- a/src/common/tusb_mcu.h
+++ b/src/common/tusb_mcu.h
@@ -195,6 +195,7 @@
#elif TU_CHECK_MCU(OPT_MCU_STM32F4)
#define TUP_USBIP_DWC2
#define TUP_USBIP_DWC2_STM32
+ #define TUP_USBIP_DWC2_TEST_MODE
// For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9
#define TUP_DCD_ENDPOINT_MAX 6
@@ -209,6 +210,7 @@
// MCU with on-chip HS Phy
#if defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F733xx)
#define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS
+ #define TUP_USBIP_DWC2_TEST_MODE
#endif
#elif TU_CHECK_MCU(OPT_MCU_STM32H7)
@@ -277,6 +279,7 @@
defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx)
#define TUP_DCD_ENDPOINT_MAX 9
#define TUP_RHPORT_HIGHSPEED 1
+ #define TUP_USBIP_DWC2_TEST_MODE
#else
#define TUP_DCD_ENDPOINT_MAX 6
#endif
@@ -329,7 +332,7 @@
#define TUP_USBIP_DWC2
#define TUP_DCD_ENDPOINT_MAX 6
-#elif TU_CHECK_MCU(OPT_MCU_ESP32) && (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421))
+#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C6, OPT_MCU_ESP32H2) && (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421))
#error "MCUs are only supported with CFG_TUH_MAX3421 enabled"
//--------------------------------------------------------------------+
@@ -399,16 +402,57 @@
#elif TU_CHECK_MCU(OPT_MCU_F1C100S)
#define TUP_DCD_ENDPOINT_MAX 4
-//------------- WCH -------------//
+//--------------------------------------------------------------------+
+// WCH
+//--------------------------------------------------------------------+
+#elif TU_CHECK_MCU(OPT_MCU_CH32F20X)
+ #define TUP_USBIP_WCH_USBHS
+ #define TUP_USBIP_WCH_USBFS
+
+ #if !defined(CFG_TUD_WCH_USBIP_USBFS)
+ #define CFG_TUD_WCH_USBIP_USBFS 0
+ #endif
+
+ #if !defined(CFG_TUD_WCH_USBIP_USBHS)
+ #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1)
+ #endif
+
+ #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS
+ #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8)
+
+#elif TU_CHECK_MCU(OPT_MCU_CH32V20X)
+ // v20x support both FSDEV (USBD) and USBFS, default to FSDEV
+ #define TUP_USBIP_WCH_USBFS
+ #define TUP_USBIP_FSDEV
+ #define TUP_USBIP_FSDEV_CH32
+
+ #if !defined(CFG_TUD_WCH_USBIP_USBFS)
+ #define CFG_TUD_WCH_USBIP_USBFS 0
+ #endif
+
+ #if !defined(CFG_TUD_WCH_USBIP_FSDEV)
+ #define CFG_TUD_WCH_USBIP_FSDEV (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1)
+ #endif
+
+ #define TUP_DCD_ENDPOINT_MAX 8
+
#elif TU_CHECK_MCU(OPT_MCU_CH32V307)
- #define TUP_DCD_ENDPOINT_MAX 16
- #define TUP_RHPORT_HIGHSPEED 1
+ // v307 support both FS and HS, default to HS
+ #define TUP_USBIP_WCH_USBHS
+ #define TUP_USBIP_WCH_USBFS
-#elif TU_CHECK_MCU(OPT_MCU_CH32F20X)
- #define TUP_DCD_ENDPOINT_MAX 16
- #define TUP_RHPORT_HIGHSPEED 1
-#endif
+ #if !defined(CFG_TUD_WCH_USBIP_USBFS)
+ #define CFG_TUD_WCH_USBIP_USBFS 0
+ #endif
+ #if !defined(CFG_TUD_WCH_USBIP_USBHS)
+ #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1)
+ #endif
+
+ #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS
+ #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8)
+
+#endif
//--------------------------------------------------------------------+
// External USB controller
diff --git a/src/device/dcd.h b/src/device/dcd.h
index d4f105aa3..f6735b077 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_DCD_H_
-#define _TUSB_DCD_H_
+#ifndef TUSB_DCD_H_
+#define TUSB_DCD_H_
#include "common/tusb_common.h"
#include "osal/osal.h"
@@ -36,14 +36,6 @@
#endif
//--------------------------------------------------------------------+
-// Configuration
-//--------------------------------------------------------------------+
-
-#ifndef CFG_TUD_ENDPPOINT_MAX
- #define CFG_TUD_ENDPPOINT_MAX TUP_DCD_ENDPOINT_MAX
-#endif
-
-//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
@@ -97,6 +89,14 @@ typedef struct TU_ATTR_ALIGNED(4) {
};
} dcd_event_t;
+typedef enum {
+ TEST_J = 1,
+ TEST_K,
+ TEST_SE0_NAK,
+ TEST_PACKET,
+ TEST_FORCE_ENABLE,
+} test_mode_t;
+
//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct");
//--------------------------------------------------------------------+
@@ -141,14 +141,21 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr);
void dcd_remote_wakeup(uint8_t rhport);
// Connect by enabling internal pull-up resistor on D+/D-
-void dcd_connect(uint8_t rhport) TU_ATTR_WEAK;
+void dcd_connect(uint8_t rhport);
// Disconnect by disabling internal pull-up resistor on D+/D-
-void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK;
+void dcd_disconnect(uint8_t rhport);
// Enable/Disable Start-of-frame interrupt. Default is disabled
void dcd_sof_enable(uint8_t rhport, bool en);
+#if CFG_TUD_TEST_MODE
+// Check if the test mode is supported, returns true is test mode selector is supported
+bool dcd_check_test_mode_support(test_mode_t test_selector) TU_ATTR_WEAK;
+
+// Put device into a test mode (needs power cycle to quit)
+void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) TU_ATTR_WEAK;
+#endif
//--------------------------------------------------------------------+
// Endpoint API
//--------------------------------------------------------------------+
@@ -239,4 +246,4 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_sof(uint8_t rhport, uint32_t
}
#endif
-#endif /* _TUSB_DCD_H_ */
+#endif
diff --git a/src/device/usbd.c b/src/device/usbd.c
index e33f39bcf..800d9c824 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -45,11 +45,6 @@
//--------------------------------------------------------------------+
// 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;
@@ -60,6 +55,19 @@ TU_ATTR_WEAK void tud_sof_cb(uint32_t frame_count) {
(void)frame_count;
}
+TU_ATTR_WEAK bool dcd_deinit(uint8_t rhport) {
+ (void) rhport;
+ return false;
+}
+
+TU_ATTR_WEAK void dcd_connect(uint8_t rhport) {
+ (void) rhport;
+}
+
+TU_ATTR_WEAK void dcd_disconnect(uint8_t rhport) {
+ (void) rhport;
+}
+
//--------------------------------------------------------------------+
// Device Data
//--------------------------------------------------------------------+
@@ -313,7 +321,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event,
static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request);
static bool process_set_config(uint8_t rhport, uint8_t cfg_num);
static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request);
-
+#if CFG_TUD_TEST_MODE
+static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
+#endif
// from usbd_control.c
void usbd_control_reset(void);
void usbd_control_set_request(tusb_control_request_t const *request);
@@ -377,21 +387,17 @@ bool tud_remote_wakeup(void) {
}
bool tud_disconnect(void) {
- TU_VERIFY(dcd_disconnect);
dcd_disconnect(_usbd_rhport);
return true;
}
bool tud_connect(void) {
- TU_VERIFY(dcd_connect);
dcd_connect(_usbd_rhport);
return true;
}
-bool tud_sof_cb_enable(bool en)
-{
+void tud_sof_cb_enable(bool en) {
usbd_sof_enable(_usbd_rhport, SOF_CONSUMER_USER, en);
- return true;
}
//--------------------------------------------------------------------+
@@ -405,7 +411,7 @@ bool tud_init(uint8_t rhport) {
// skip if already initialized
if (tud_inited()) return true;
- TU_LOG_USBD("USBD init on controller %u\r\n", rhport);
+ TU_LOG_USBD("USBD init on controller %u, Highspeed = %u\r\n", rhport, TUD_OPT_HIGH_SPEED);
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));
@@ -753,14 +759,47 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
break;
case TUSB_REQ_SET_FEATURE:
- // Only support remote wakeup for device feature
- TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
+ // Handle the feature selector
+ switch(p_request->wValue)
+ {
+ // Support for remote wakeup
+ case TUSB_REQ_FEATURE_REMOTE_WAKEUP:
+ TU_LOG_USBD(" 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;
+ tud_control_status(rhport, p_request);
+ break;
- // Host may enable remote wake up before suspending especially HID device
- _usbd_dev.remote_wakeup_en = true;
- tud_control_status(rhport, p_request);
+#if CFG_TUD_TEST_MODE
+ // Support for TEST_MODE
+ case TUSB_REQ_FEATURE_TEST_MODE: {
+ // Only handle the test mode if supported and valid
+ TU_VERIFY(dcd_enter_test_mode && dcd_check_test_mode_support && 0 == tu_u16_low(p_request->wIndex));
+
+ uint8_t selector = tu_u16_high(p_request->wIndex);
+
+ // Stall request if the selected test mode isn't supported
+ if (!dcd_check_test_mode_support((test_mode_t)selector))
+ {
+ TU_LOG_USBD(" Unsupported Test Mode (test selector index: %d)\r\n", selector);
+
+ return false;
+ }
+
+ // Acknowledge request
+ tud_control_status(rhport, p_request);
+
+ TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector);
+
+ usbd_control_set_complete_callback(process_test_mode_cb);
+ break;
+ }
+#endif /* CFG_TUD_TEST_MODE */
+
+ // Stall unsupported feature selector
+ default: return false;
+ }
break;
case TUSB_REQ_CLEAR_FEATURE:
@@ -1088,6 +1127,20 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
}
}
+#if CFG_TUD_TEST_MODE
+static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
+{
+ // At this point it should already be ensured that dcd_enter_test_mode() is defined
+
+ // Only enter the test mode after the request for it has completed
+ TU_VERIFY(CONTROL_STAGE_ACK == stage);
+
+ dcd_enter_test_mode(rhport, (test_mode_t)tu_u16_high(request->wIndex));
+
+ return true;
+}
+#endif /* CFG_TUD_TEST_MODE */
+
//--------------------------------------------------------------------+
// DCD Event Handler
//--------------------------------------------------------------------+
@@ -1140,7 +1193,7 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr)
}
if (tu_bit_test(_usbd_dev.sof_consumer, SOF_CONSUMER_USER)) {
- dcd_event_t const event_sof = {.rhport = event->rhport, .event_id = DCD_EVENT_SOF};
+ dcd_event_t const event_sof = {.rhport = event->rhport, .event_id = DCD_EVENT_SOF, .sof.frame_count = event->sof.frame_count};
queue_event(&event_sof, in_isr);
}
break;
diff --git a/src/device/usbd.h b/src/device/usbd.h
index 6216d97ac..26e857d36 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -60,7 +60,7 @@ void tud_task (void) {
// Check if there is pending events need processing by tud_task()
bool tud_task_event_ready(void);
-#ifndef _TUSB_DCD_H_
+#ifndef TUSB_DCD_H_
extern void dcd_int_handler(uint8_t rhport);
#endif
@@ -98,7 +98,7 @@ bool tud_disconnect(void);
bool tud_connect(void);
// Enable or disable the Start Of Frame callback support
-bool tud_sof_cb_enable(bool en);
+void tud_sof_cb_enable(bool en);
// Carry out Data and Status stage of control transfer
// - If len = 0, it is equivalent to sending status only
diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c
index 4dc93d2d8..d9b8e1fc3 100644
--- a/src/portable/analog/max3421/hcd_max3421.c
+++ b/src/portable/analog/max3421/hcd_max3421.c
@@ -174,7 +174,8 @@ enum {
enum {
EP_STATE_IDLE = 0,
EP_STATE_COMPLETE = 1,
- EP_STATE_ATTEMPT_1 = 2, // pending 1st attempt
+ EP_STATE_ABORTING = 2,
+ EP_STATE_ATTEMPT_1 = 3, // pending 1st attempt
EP_STATE_ATTEMPT_MAX = 15
};
@@ -459,6 +460,7 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param;
_tuh_cfg = cfg->max3421;
+ _tuh_cfg.max_nak = tu_min8(_tuh_cfg.max_nak, EP_STATE_ATTEMPT_MAX-EP_STATE_ATTEMPT_1);
return true;
}
@@ -678,7 +680,6 @@ static void xact_generic(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool
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);
@@ -702,14 +703,19 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf
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;
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ 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);
- return false;
+ if (EP_STATE_ATTEMPT_1 <= ep->state && ep->state < EP_STATE_ATTEMPT_MAX) {
+ hcd_int_disable(rhport);
+ ep->state = EP_STATE_ABORTING;
+ hcd_int_enable(rhport);
+ }
+
+ return true;
}
// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked
@@ -819,7 +825,6 @@ static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t re
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;
@@ -829,34 +834,30 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
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);
+ if (ep->state == EP_STATE_ABORTING) {
+ ep->state = EP_STATE_IDLE;
} else {
- if (ep->state < EP_STATE_ATTEMPT_MAX) {
+ if (ep_num == 0) {
+ // control endpoint -> retry immediately and return
+ hxfr_write(rhport, _hcd_data.hxfr, in_isr);
+ return;
+ } else if (EP_STATE_ATTEMPT_1 <= ep->state && 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);
- }
+ 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;
@@ -864,6 +865,14 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) {
// occurred when initialized without any pending transfer. Skip for now
return;
+ case HRSL_SUCCESS:
+ xfer_result = XFER_RESULT_SUCCESS;
+ break;
+
+ case HRSL_STALL:
+ xfer_result = XFER_RESULT_STALLED;
+ break;
+
default:
TU_LOG3("HRSL: %02X\r\n", hrsl);
xfer_result = XFER_RESULT_FAILED;
@@ -942,9 +951,8 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
if (hirq & HIRQ_FRAME_IRQ) {
_hcd_data.frame_count++;
+ // reset all endpoints nak counter, retry with 1st pending ep.
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) {
@@ -1004,7 +1012,7 @@ void hcd_int_handler(uint8_t rhport, bool 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 ) {
+ if (hirq) {
hirq_write(rhport, hirq, in_isr);
}
}
diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c
index f9ec666e5..93e1d78dd 100644
--- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c
+++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c
@@ -309,10 +309,12 @@ void dcd_disconnect(uint8_t rhport)
void dcd_sof_enable(uint8_t rhport, bool en)
{
- (void) rhport;
- (void) en;
-
- // TODO implement later
+ ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+ if (en) {
+ dcd_reg->USBINTR |= INTR_SOF;
+ } else {
+ dcd_reg->USBINTR &= ~INTR_SOF;
+ }
}
//--------------------------------------------------------------------+
@@ -679,7 +681,8 @@ void dcd_int_handler(uint8_t rhport)
if (int_status & INTR_SOF)
{
- dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
+ const uint32_t frame = dcd_reg->FRINDEX;
+ dcd_event_sof(rhport, frame, true);
}
}
diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c
index bfc0baa56..f912bef89 100644
--- a/src/portable/espressif/esp32sx/dcd_esp32sx.c
+++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c
@@ -31,7 +31,8 @@
#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && CFG_TUD_ENABLED)
// Espressif
-#include "xtensa_api.h"
+#include "xtensa/xtensa_api.h"
+
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "soc/dport_reg.h"
diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c
index 976d3dfd0..005b63faf 100644
--- a/src/portable/microchip/samd/dcd_samd.c
+++ b/src/portable/microchip/samd/dcd_samd.c
@@ -183,9 +183,12 @@ void dcd_connect(uint8_t rhport)
void dcd_sof_enable(uint8_t rhport, bool en)
{
(void) rhport;
- (void) en;
- // TODO implement later
+ if (en) {
+ USB->DEVICE.INTENSET.bit.SOF = 1;
+ } else {
+ USB->DEVICE.INTENCLR.bit.SOF = 1;
+ }
}
/*------------------------------------------------------------------*/
@@ -374,7 +377,9 @@ void dcd_int_handler (uint8_t rhport)
if ( int_status & USB_DEVICE_INTFLAG_SOF )
{
USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF;
- dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
+ const uint32_t frame = USB->DEVICE.FNUM.bit.FNUM;
+ dcd_event_sof(0, frame, true);
+ //dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
}
// SAMD doesn't distinguish between Suspend and Disconnect state.
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index 2fe721d6b..abce35245 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -120,6 +120,9 @@ static struct {
// nRF can only carry one DMA at a time, this is used to guard the access to EasyDMA
atomic_flag dma_running;
+
+ // Track whether sof has been manually enabled
+ bool sof_enabled;
} _dcd;
/*------------------------------------------------------------------*/
@@ -147,7 +150,7 @@ static void start_dma(volatile uint32_t* reg_startep) {
static void edpt_dma_start(volatile uint32_t* reg_startep) {
if (atomic_flag_test_and_set(&_dcd.dma_running)) {
- usbd_defer_func((osal_task_func_t)(uintptr_t ) edpt_dma_start, (void*) (uintptr_t) reg_startep, true);
+ usbd_defer_func((osal_task_func_t)(uintptr_t ) edpt_dma_start, (void*) (uintptr_t) reg_startep, is_in_isr());
} else {
start_dma(reg_startep);
}
@@ -283,9 +286,13 @@ void dcd_connect(uint8_t rhport) {
void dcd_sof_enable(uint8_t rhport, bool en) {
(void) rhport;
- (void) en;
-
- // TODO implement later
+ if (en) {
+ _dcd.sof_enabled = true;
+ NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk;
+ } else {
+ _dcd.sof_enabled = false;
+ NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk;
+ }
}
//--------------------------------------------------------------------+
@@ -607,13 +614,16 @@ void dcd_int_handler(uint8_t rhport) {
}
}
- if (!iso_enabled) {
- // ISO endpoint is not used, SOF is only enabled one-time for remote wakeup
- // so we disable it now
- NRF_USBD->INTENCLR = USBD_INTENSET_SOF_Msk;
+ if (!iso_enabled && !_dcd.sof_enabled) {
+ // SOF interrupt not manually enabled and ISO endpoint is not used,
+ // SOF is only enabled one-time for remote wakeup so we disable it now
+
+ NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk;
}
- dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
+ const uint32_t frame = NRF_USBD->FRAMECNTR;
+ dcd_event_sof(0, frame, true);
+ //dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
}
if (int_status & USBD_INTEN_USBEVENT_Msk) {
diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c
index 50400d1f5..7c6044ca0 100644
--- a/src/portable/renesas/rusb2/dcd_rusb2.c
+++ b/src/portable/renesas/rusb2/dcd_rusb2.c
@@ -29,10 +29,6 @@
#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
-
#include "device/dcd.h"
#include "rusb2_type.h"
@@ -74,6 +70,8 @@ typedef struct
{
pipe_state_t pipe[PIPE_COUNT];
uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */
+ // Track whether sof has been manually enabled
+ bool sof_enabled;
} dcd_data_t;
static dcd_data_t _dcd;
@@ -664,6 +662,10 @@ void dcd_init(uint8_t rhport)
rusb2_reg_t* rusb = RUSB2_REG(rhport);
rusb2_module_start(rhport, true);
+// We disable SOF for now until needed later on.
+// Since TinyUSB doesn't use SOF for now, and this interrupt often (1ms interval)
+_dcd.sof_enabled = false;
+
#ifdef RUSB2_SUPPORT_HIGHSPEED
if ( rusb2_is_highspeed_rhport(rhport) ) {
rusb->SYSCFG_b.HSE = 1;
@@ -708,7 +710,7 @@ void dcd_init(uint8_t rhport)
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_DVST_Msk | RUSB2_INTSTS0_CTRT_Msk | (_dcd.sof_enabled ? RUSB2_INTSTS0_SOFR_Msk : 0) |
RUSB2_INTSTS0_RESM_Msk;
rusb->BEMPENB = 1;
rusb->BRDYENB = 1;
@@ -756,10 +758,9 @@ void dcd_disconnect(uint8_t rhport)
void dcd_sof_enable(uint8_t rhport, bool en)
{
- (void) rhport;
- (void) en;
-
- // TODO implement later
+ rusb2_reg_t* rusb = RUSB2_REG(rhport);
+ _dcd.sof_enabled = en;
+ rusb->INTENB0_b.SOFE = en ? 1: 0;
}
//--------------------------------------------------------------------+
@@ -949,18 +950,19 @@ void dcd_int_handler(uint8_t rhport)
// Resumed
if ( is0 & RUSB2_INTSTS0_RESM_Msk ) {
dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
-#if (0 == USE_SOF)
- rusb->INTENB0_b.SOFE = 0;
-#endif
+ if (!_dcd.sof_enabled) {
+ rusb->INTENB0_b.SOFE = 0;
+ }
}
// 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)
- rusb->INTENB0_b.SOFE = 0;
-#endif
+ const uint32_t frame = rusb->FRMNUM_b.FRNM;
+ dcd_event_sof(rhport, frame, true);
+ if (!_dcd.sof_enabled) {
+ rusb->INTENB0_b.SOFE = 0;
+ }
}
// Device state changes
@@ -979,9 +981,9 @@ void dcd_int_handler(uint8_t rhport)
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
+ if (!_dcd.sof_enabled) {
+ rusb->INTENB0_b.SOFE = 1;
+ }
default: break;
}
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index a26c66892..9ce37f992 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -102,25 +102,29 @@
#include "tusb_option.h"
-#if CFG_TUD_ENABLED && defined(TUP_USBIP_FSDEV)
+#if CFG_TUD_ENABLED && defined(TUP_USBIP_FSDEV) && \
+ !(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0)
#include "device/dcd.h"
-#ifdef TUP_USBIP_FSDEV_STM32
-// Undefine to reduce the dependence on HAL
-#undef USE_HAL_DRIVER
-#include "portable/st/stm32_fsdev/dcd_stm32_fsdev.h"
+#if defined(TUP_USBIP_FSDEV_STM32)
+ // Undefine to reduce the dependence on HAL
+ #undef USE_HAL_DRIVER
+ #include "fsdev_stm32.h"
+#elif defined(TUP_USBIP_FSDEV_CH32)
+ #include "fsdev_ch32.h"
+#else
+ #error "Unknown USB IP"
#endif
-/*****************************************************
- * Configuration
- *****************************************************/
+#include "fsdev_common.h"
-// HW supports max of 8 bidirectional endpoints, but this can be reduced to save RAM
-// (8u here would mean 8 IN and 8 OUT)
-#ifndef MAX_EP_COUNT
-#define MAX_EP_COUNT 8U
-#endif
+//--------------------------------------------------------------------+
+// Configuration
+//--------------------------------------------------------------------+
+
+// hardware limit endpoint
+#define FSDEV_EP_COUNT 8
// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it
// Both of these MUST be a multiple of 2, and are in byte units.
@@ -132,11 +136,6 @@
#define DCD_STM32_BTABLE_SIZE (FSDEV_PMA_SIZE - DCD_STM32_BTABLE_BASE)
#endif
-/***************************************************
- * Checks, structs, defines, function definitions, etc.
- */
-
-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_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");
@@ -162,9 +161,9 @@ typedef struct {
bool allocated[2];
} ep_alloc_t;
-static xfer_ctl_t xfer_status[MAX_EP_COUNT][2];
+static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2];
-static ep_alloc_t ep_alloc_status[STFSDEV_EP_COUNT];
+static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT];
static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6];
@@ -199,7 +198,7 @@ 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
- TU_ASSERT(epnum < MAX_EP_COUNT, &xfer_status[0][0]);
+ TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX, &xfer_status[0][0]);
return &xfer_status[epnum][dir];
}
@@ -239,7 +238,7 @@ void dcd_init(uint8_t rhport)
USB->ISTR = 0; // Clear pending interrupts
// Reset endpoints to disabled
- for (uint32_t i = 0; i < STFSDEV_EP_COUNT; i++) {
+ for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) {
// This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED.
pcd_set_endpoint(USB, i, 0u);
}
@@ -248,43 +247,9 @@ void dcd_init(uint8_t rhport)
dcd_handle_bus_reset();
// Enable pull-up if supported
- if (dcd_connect) {
- dcd_connect(rhport);
- }
+ dcd_connect(rhport);
}
-// Define only on MCU with internal pull-up. BSP can define on MCU without internal PU.
-#if defined(USB_BCDR_DPPU)
-
-// Disable internal D+ PU
-void dcd_disconnect(uint8_t rhport)
-{
- (void)rhport;
- USB->BCDR &= ~(USB_BCDR_DPPU);
-}
-
-// Enable internal D+ PU
-void dcd_connect(uint8_t rhport)
-{
- (void)rhport;
- USB->BCDR |= USB_BCDR_DPPU;
-}
-
-#elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151
-// Disable internal D+ PU
-void dcd_disconnect(uint8_t rhport)
-{
- (void)rhport;
- SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU);
-}
-
-// Enable internal D+ PU
-void dcd_connect(uint8_t rhport)
-{
- (void)rhport;
- SYSCFG->PMC |= SYSCFG_PMC_USB_PU;
-}
-#endif
void dcd_sof_enable(uint8_t rhport, bool en)
{
@@ -298,126 +263,6 @@ void dcd_sof_enable(uint8_t rhport, bool en)
}
}
-// Enable device interrupt
-void dcd_int_enable(uint8_t rhport)
-{
- (void)rhport;
- // Member here forces write to RAM before allowing ISR to execute
- __DSB();
- __ISB();
-#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || CFG_TUSB_MCU == OPT_MCU_STM32L4
- NVIC_EnableIRQ(USB_IRQn);
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
- NVIC_EnableIRQ(USB_LP_IRQn);
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F3
-// Some STM32F302/F303 devices allow to remap the USB interrupt vectors from
-// shared USB/CAN IRQs to separate CAN and USB IRQs.
-// This dynamically checks if this remap is active to enable the right IRQs.
-#ifdef SYSCFG_CFGR1_USB_IT_RMP
- if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) {
- NVIC_EnableIRQ(USB_HP_IRQn);
- NVIC_EnableIRQ(USB_LP_IRQn);
- NVIC_EnableIRQ(USBWakeUp_RMP_IRQn);
- } else
-#endif
- {
- NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn);
- NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn);
- NVIC_EnableIRQ(USBWakeUp_IRQn);
- }
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
- NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
- NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
- NVIC_EnableIRQ(USBWakeUp_IRQn);
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32G4
- NVIC_EnableIRQ(USB_HP_IRQn);
- 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);
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L5
- NVIC_EnableIRQ(USB_FS_IRQn);
-
-#else
-#error Unknown arch in USB driver
-#endif
-}
-
-// Disable device interrupt
-void dcd_int_disable(uint8_t rhport)
-{
- (void)rhport;
-
-#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0 || CFG_TUSB_MCU == OPT_MCU_STM32L4
- NVIC_DisableIRQ(USB_IRQn);
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
- NVIC_DisableIRQ(USB_LP_IRQn);
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F3
-// Some STM32F302/F303 devices allow to remap the USB interrupt vectors from
-// shared USB/CAN IRQs to separate CAN and USB IRQs.
-// This dynamically checks if this remap is active to disable the right IRQs.
-#ifdef SYSCFG_CFGR1_USB_IT_RMP
- if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) {
- NVIC_DisableIRQ(USB_HP_IRQn);
- NVIC_DisableIRQ(USB_LP_IRQn);
- NVIC_DisableIRQ(USBWakeUp_RMP_IRQn);
- } else
-#endif
- {
- NVIC_DisableIRQ(USB_HP_CAN_TX_IRQn);
- NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn);
- NVIC_DisableIRQ(USBWakeUp_IRQn);
- }
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
- NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
- NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
- NVIC_DisableIRQ(USBWakeUp_IRQn);
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32G4
- NVIC_DisableIRQ(USB_HP_IRQn);
- 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);
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L5
- NVIC_DisableIRQ(USB_FS_IRQn);
-
-#else
-#error Unknown arch in USB driver
-#endif
-
- // CMSIS has a membar after disabling interrupts
-}
-
// Receive Set Address request, mcu port must also include status IN response
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
{
@@ -461,7 +306,7 @@ static void dcd_handle_bus_reset(void)
{
USB->DADDR = 0u; // disable USB peripheral by clearing the EF flag
- for (uint32_t i = 0; i < STFSDEV_EP_COUNT; i++) {
+ for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) {
// Clear EP allocation status
ep_alloc_status[i].ep_num = 0xFF;
ep_alloc_status[i].ep_type = 0xFF;
@@ -470,7 +315,7 @@ static void dcd_handle_bus_reset(void)
}
// Reset PMA allocation
- ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * MAX_EP_COUNT;
+ ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX;
dcd_edpt_open(0, &ep0OUT_desc);
dcd_edpt_open(0, &ep0IN_desc);
@@ -653,7 +498,6 @@ static void dcd_ep_ctr_handler(void)
void dcd_int_handler(uint8_t rhport)
{
-
(void)rhport;
uint32_t int_status = USB->ISTR;
@@ -774,7 +618,7 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type)
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
- for (uint8_t i = 0; i < STFSDEV_EP_COUNT; i++) {
+ for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
// Check if already allocated
if (ep_alloc_status[i].allocated[dir] &&
ep_alloc_status[i].ep_type == ep_type &&
@@ -818,7 +662,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
uint16_t pma_addr;
uint32_t wType;
- TU_ASSERT(ep_idx < STFSDEV_EP_COUNT);
+ TU_ASSERT(ep_idx < FSDEV_EP_COUNT);
TU_ASSERT(buffer_size <= 64);
// Set type
@@ -865,7 +709,7 @@ void dcd_edpt_close_all(uint8_t rhport)
{
(void)rhport;
- for (uint32_t i = 1; i < STFSDEV_EP_COUNT; i++) {
+ for (uint32_t i = 1; i < FSDEV_EP_COUNT; i++) {
// Reset endpoint
pcd_set_endpoint(USB, i, 0);
// Clear EP allocation status
@@ -876,7 +720,7 @@ void dcd_edpt_close_all(uint8_t rhport)
}
// Reset PMA allocation
- ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * MAX_EP_COUNT + 2 * CFG_TUD_ENDPOINT0_SIZE;
+ ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX + 2 * CFG_TUD_ENDPOINT0_SIZE;
}
/**
@@ -1155,7 +999,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui
}
if (wNBytes) {
- temp1 = *srcVal;
+ temp1 = (uint16_t) *srcVal;
*pdwVal = temp1;
}
diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h
new file mode 100644
index 000000000..85fe3266c
--- /dev/null
+++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h
@@ -0,0 +1,232 @@
+/*
+* The MIT License (MIT)
+ *
+ * Copyright (c) 2024, hathach (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.
+ *
+ */
+/** <h2><center>&copy; Copyright (c) 2016 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
+ */
+
+#ifndef TUSB_FSDEV_CH32_H
+#define TUSB_FSDEV_CH32_H
+
+#include "common/tusb_compiler.h"
+
+#if CFG_TUSB_MCU == OPT_MCU_CH32V20X
+ #include <ch32v20x.h>
+
+#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X
+ #include <ch32f20x.h>
+#endif
+
+#define FSDEV_PMA_SIZE (512u)
+
+// volatile 32-bit aligned
+#define _va32 volatile TU_ATTR_ALIGNED(4)
+
+typedef struct {
+ _va32 uint16_t EP0R; // 00: USB Endpoint 0 register
+ _va32 uint16_t EP1R; // 04: USB Endpoint 1 register
+ _va32 uint16_t EP2R; // 08: USB Endpoint 2 register
+ _va32 uint16_t EP3R; // 0C: USB Endpoint 3 register
+ _va32 uint16_t EP4R; // 10: USB Endpoint 4 register
+ _va32 uint16_t EP5R; // 14: USB Endpoint 5 register
+ _va32 uint16_t EP6R; // 18: USB Endpoint 6 register
+ _va32 uint16_t EP7R; // 1C: USB Endpoint 7 register
+ _va32 uint16_t RESERVED7[16]; // Reserved
+ _va32 uint16_t CNTR; // 40: Control register
+ _va32 uint16_t ISTR; // 44: Interrupt status register
+ _va32 uint16_t FNR; // 48: Frame number register
+ _va32 uint16_t DADDR; // 4C: Device address register
+ _va32 uint16_t BTABLE; // 50: Buffer Table address register
+} USB_TypeDef;
+
+TU_VERIFY_STATIC(sizeof(USB_TypeDef) == 0x54, "Size is not correct");
+TU_VERIFY_STATIC(offsetof(USB_TypeDef, CNTR) == 0x40, "Wrong offset");
+
+#define USB_BASE (APB1PERIPH_BASE + 0x00005C00UL) /*!< USB_IP Peripheral Registers base address */
+#define USB_PMAADDR (APB1PERIPH_BASE + 0x00006000UL) /*!< USB_IP Packet Memory Area base address */
+#define USB ((USB_TypeDef *)USB_BASE)
+
+/******************************************************************************/
+/* */
+/* USB Device General registers */
+/* */
+/******************************************************************************/
+#define USB_CNTR (USB_BASE + 0x40U) /*!< Control register */
+#define USB_ISTR (USB_BASE + 0x44U) /*!< Interrupt status register */
+#define USB_FNR (USB_BASE + 0x48U) /*!< Frame number register */
+#define USB_DADDR (USB_BASE + 0x4CU) /*!< Device address register */
+#define USB_BTABLE (USB_BASE + 0x50U) /*!< Buffer Table address register */
+
+/**************************** ISTR interrupt events *************************/
+#define USB_ISTR_CTR ((uint16_t)0x8000U) /*!< Correct TRansfer (clear-only bit) */
+#define USB_ISTR_PMAOVR ((uint16_t)0x4000U) /*!< DMA OVeR/underrun (clear-only bit) */
+#define USB_ISTR_ERR ((uint16_t)0x2000U) /*!< ERRor (clear-only bit) */
+#define USB_ISTR_WKUP ((uint16_t)0x1000U) /*!< WaKe UP (clear-only bit) */
+#define USB_ISTR_SUSP ((uint16_t)0x0800U) /*!< SUSPend (clear-only bit) */
+#define USB_ISTR_RESET ((uint16_t)0x0400U) /*!< RESET (clear-only bit) */
+#define USB_ISTR_SOF ((uint16_t)0x0200U) /*!< Start Of Frame (clear-only bit) */
+#define USB_ISTR_ESOF ((uint16_t)0x0100U) /*!< Expected Start Of Frame (clear-only bit) */
+#define USB_ISTR_DIR ((uint16_t)0x0010U) /*!< DIRection of transaction (read-only bit) */
+#define USB_ISTR_EP_ID ((uint16_t)0x000FU) /*!< EndPoint IDentifier (read-only bit) */
+
+/* Legacy defines */
+#define USB_ISTR_PMAOVRM USB_ISTR_PMAOVR
+
+#define USB_CLR_CTR (~USB_ISTR_CTR) /*!< clear Correct TRansfer bit */
+#define USB_CLR_PMAOVR (~USB_ISTR_PMAOVR) /*!< clear DMA OVeR/underrun bit*/
+#define USB_CLR_ERR (~USB_ISTR_ERR) /*!< clear ERRor bit */
+#define USB_CLR_WKUP (~USB_ISTR_WKUP) /*!< clear WaKe UP bit */
+#define USB_CLR_SUSP (~USB_ISTR_SUSP) /*!< clear SUSPend bit */
+#define USB_CLR_RESET (~USB_ISTR_RESET) /*!< clear RESET bit */
+#define USB_CLR_SOF (~USB_ISTR_SOF) /*!< clear Start Of Frame bit */
+#define USB_CLR_ESOF (~USB_ISTR_ESOF) /*!< clear Expected Start Of Frame bit */
+
+/* Legacy defines */
+#define USB_CLR_PMAOVRM USB_CLR_PMAOVR
+
+/************************* CNTR control register bits definitions ***********/
+#define USB_CNTR_CTRM ((uint16_t)0x8000U) /*!< Correct TRansfer Mask */
+#define USB_CNTR_PMAOVR ((uint16_t)0x4000U) /*!< DMA OVeR/underrun Mask */
+#define USB_CNTR_ERRM ((uint16_t)0x2000U) /*!< ERRor Mask */
+#define USB_CNTR_WKUPM ((uint16_t)0x1000U) /*!< WaKe UP Mask */
+#define USB_CNTR_SUSPM ((uint16_t)0x0800U) /*!< SUSPend Mask */
+#define USB_CNTR_RESETM ((uint16_t)0x0400U) /*!< RESET Mask */
+#define USB_CNTR_SOFM ((uint16_t)0x0200U) /*!< Start Of Frame Mask */
+#define USB_CNTR_ESOFM ((uint16_t)0x0100U) /*!< Expected Start Of Frame Mask */
+#define USB_CNTR_RESUME ((uint16_t)0x0010U) /*!< RESUME request */
+#define USB_CNTR_FSUSP ((uint16_t)0x0008U) /*!< Force SUSPend */
+#define USB_CNTR_LPMODE ((uint16_t)0x0004U) /*!< Low-power MODE */
+#define USB_CNTR_PDWN ((uint16_t)0x0002U) /*!< Power DoWN */
+#define USB_CNTR_FRES ((uint16_t)0x0001U) /*!< Force USB RESet */
+
+/* Legacy defines */
+#define USB_CNTR_PMAOVRM USB_CNTR_PMAOVR
+#define USB_CNTR_LP_MODE USB_CNTR_LPMODE
+
+/******************** FNR Frame Number Register bit definitions ************/
+#define USB_FNR_RXDP ((uint16_t)0x8000U) /*!< status of D+ data line */
+#define USB_FNR_RXDM ((uint16_t)0x4000U) /*!< status of D- data line */
+#define USB_FNR_LCK ((uint16_t)0x2000U) /*!< LoCKed */
+#define USB_FNR_LSOF ((uint16_t)0x1800U) /*!< Lost SOF */
+#define USB_FNR_FN ((uint16_t)0x07FFU) /*!< Frame Number */
+
+/******************** DADDR Device ADDRess bit definitions ****************/
+#define USB_DADDR_EF ((uint8_t)0x80U) /*!< USB device address Enable Function */
+#define USB_DADDR_ADD ((uint8_t)0x7FU) /*!< USB device address */
+
+/****************************** Endpoint register *************************/
+#define USB_EP0R USB_BASE /*!< endpoint 0 register address */
+#define USB_EP1R (USB_BASE + 0x04U) /*!< endpoint 1 register address */
+#define USB_EP2R (USB_BASE + 0x08U) /*!< endpoint 2 register address */
+#define USB_EP3R (USB_BASE + 0x0CU) /*!< endpoint 3 register address */
+#define USB_EP4R (USB_BASE + 0x10U) /*!< endpoint 4 register address */
+#define USB_EP5R (USB_BASE + 0x14U) /*!< endpoint 5 register address */
+#define USB_EP6R (USB_BASE + 0x18U) /*!< endpoint 6 register address */
+#define USB_EP7R (USB_BASE + 0x1CU) /*!< endpoint 7 register address */
+/* bit positions */
+#define USB_EP_CTR_RX ((uint16_t)0x8000U) /*!< EndPoint Correct TRansfer RX */
+#define USB_EP_DTOG_RX ((uint16_t)0x4000U) /*!< EndPoint Data TOGGLE RX */
+#define USB_EPRX_STAT ((uint16_t)0x3000U) /*!< EndPoint RX STATus bit field */
+#define USB_EP_SETUP ((uint16_t)0x0800U) /*!< EndPoint SETUP */
+#define USB_EP_T_FIELD ((uint16_t)0x0600U) /*!< EndPoint TYPE */
+#define USB_EP_KIND ((uint16_t)0x0100U) /*!< EndPoint KIND */
+#define USB_EP_CTR_TX ((uint16_t)0x0080U) /*!< EndPoint Correct TRansfer TX */
+#define USB_EP_DTOG_TX ((uint16_t)0x0040U) /*!< EndPoint Data TOGGLE TX */
+#define USB_EPTX_STAT ((uint16_t)0x0030U) /*!< EndPoint TX STATus bit field */
+#define USB_EPADDR_FIELD ((uint16_t)0x000FU) /*!< EndPoint ADDRess FIELD */
+
+/* EndPoint REGister MASK (no toggle fields) */
+#define USB_EPREG_MASK (USB_EP_CTR_RX|USB_EP_SETUP|USB_EP_T_FIELD|USB_EP_KIND|USB_EP_CTR_TX|USB_EPADDR_FIELD)
+ /*!< EP_TYPE[1:0] EndPoint TYPE */
+#define USB_EP_TYPE_MASK ((uint16_t)0x0600U) /*!< EndPoint TYPE Mask */
+#define USB_EP_BULK ((uint16_t)0x0000U) /*!< EndPoint BULK */
+#define USB_EP_CONTROL ((uint16_t)0x0200U) /*!< EndPoint CONTROL */
+#define USB_EP_ISOCHRONOUS ((uint16_t)0x0400U) /*!< EndPoint ISOCHRONOUS */
+#define USB_EP_INTERRUPT ((uint16_t)0x0600U) /*!< EndPoint INTERRUPT */
+#define USB_EP_T_MASK ((uint16_t) ~USB_EP_T_FIELD & USB_EPREG_MASK)
+
+#define USB_EPKIND_MASK ((uint16_t) ~USB_EP_KIND & USB_EPREG_MASK) /*!< EP_KIND EndPoint KIND */
+ /*!< STAT_TX[1:0] STATus for TX transfer */
+#define USB_EP_TX_DIS ((uint16_t)0x0000U) /*!< EndPoint TX DISabled */
+#define USB_EP_TX_STALL ((uint16_t)0x0010U) /*!< EndPoint TX STALLed */
+#define USB_EP_TX_NAK ((uint16_t)0x0020U) /*!< EndPoint TX NAKed */
+#define USB_EP_TX_VALID ((uint16_t)0x0030U) /*!< EndPoint TX VALID */
+#define USB_EPTX_DTOG1 ((uint16_t)0x0010U) /*!< EndPoint TX Data TOGgle bit1 */
+#define USB_EPTX_DTOG2 ((uint16_t)0x0020U) /*!< EndPoint TX Data TOGgle bit2 */
+#define USB_EPTX_DTOGMASK (USB_EPTX_STAT|USB_EPREG_MASK)
+ /*!< STAT_RX[1:0] STATus for RX transfer */
+#define USB_EP_RX_DIS ((uint16_t)0x0000U) /*!< EndPoint RX DISabled */
+#define USB_EP_RX_STALL ((uint16_t)0x1000U) /*!< EndPoint RX STALLed */
+#define USB_EP_RX_NAK ((uint16_t)0x2000U) /*!< EndPoint RX NAKed */
+#define USB_EP_RX_VALID ((uint16_t)0x3000U) /*!< EndPoint RX VALID */
+#define USB_EPRX_DTOG1 ((uint16_t)0x1000U) /*!< EndPoint RX Data TOGgle bit1 */
+#define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */
+#define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK)
+
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+#if CFG_TUSB_MCU == OPT_MCU_CH32V20X
+static const IRQn_Type fsdev_irq[] = {
+ USB_HP_CAN1_TX_IRQn,
+ USB_LP_CAN1_RX0_IRQn,
+ USBWakeUp_IRQn
+};
+enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) };
+#else
+ #error "Unsupported MCU"
+#endif
+
+void dcd_int_enable(uint8_t rhport) {
+ (void)rhport;
+ for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) {
+ NVIC_EnableIRQ(fsdev_irq[i]);
+ }
+}
+
+void dcd_int_disable(uint8_t rhport) {
+ (void)rhport;
+ for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) {
+ NVIC_DisableIRQ(fsdev_irq[i]);
+ }
+}
+
+void dcd_disconnect(uint8_t rhport) {
+ (void) rhport;
+ EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN;
+}
+
+void dcd_connect(uint8_t rhport) {
+ (void) rhport;
+ EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
+}
+
+#endif
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h b/src/portable/st/stm32_fsdev/fsdev_common.h
index 7992f34a1..af5d8afab 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h
+++ b/src/portable/st/stm32_fsdev/fsdev_common.h
@@ -1,174 +1,43 @@
/*
+ * The MIT License (MIT)
+ *
* Copyright(c) 2016 STMicroelectronics
* Copyright(c) N Conrad
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ * Copyright (c) 2024, hathach (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:
*
- * 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.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * 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.
+ * 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.
*/
-// This file contains source copied from ST's HAL, and thus should have their copyright statement.
+#ifndef TUSB_FSDEV_COMMON_H
+#define TUSB_FSDEV_COMMON_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "stdint.h"
// 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)
-#ifndef PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_
-#define PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_
-
-#if CFG_TUSB_MCU == OPT_MCU_STM32F0
- #include "stm32f0xx.h"
- #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
- // PMA dedicated to USB (no sharing with CAN)
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
- #include "stm32f1xx.h"
- #define FSDEV_PMA_SIZE (512u)
- // NO internal Pull-ups
- // *B, and *C: 2 x 16 bits/word
-
- // F1 names this differently from the rest
- #define USB_CNTR_LPMODE USB_CNTR_LP_MODE
-
-#elif defined(STM32F302xB) || defined(STM32F302xC) || \
- defined(STM32F303xB) || defined(STM32F303xC) || \
- defined(STM32F373xC)
- #include "stm32f3xx.h"
- #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)
-
-#elif defined(STM32F302x6) || defined(STM32F302x8) || \
- defined(STM32F302xD) || defined(STM32F302xE) || \
- defined(STM32F303xD) || defined(STM32F303xE)
- #include "stm32f3xx.h"
- #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 FSDEV_PMA_SIZE (1024u)
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
- #include "stm32l1xx.h"
- #define FSDEV_PMA_SIZE (512u)
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32G4
- #include "stm32g4xx.h"
- #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 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 FSDEV_PMA_SIZE (1024u)
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L5
- #include "stm32l5xx.h"
- #define FSDEV_PMA_SIZE (1024u)
-
- #ifndef USB_PMAADDR
- #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS))
- #endif
-
-#else
- #error You are using an untested or unimplemented STM32 variant. Please update the driver.
- // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4
-#endif
-
// For purposes of accessing the packet
#if ((FSDEV_PMA_SIZE) == 512u)
#define FSDEV_PMA_STRIDE (2u)
@@ -181,24 +50,24 @@
// 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;
+static volatile uint32_t * const pma32 = (volatile 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;
+static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR;
-TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) {
+TU_ATTR_ALWAYS_INLINE static inline volatile 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) {
+TU_ATTR_ALWAYS_INLINE static inline volatile 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) {
+TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) {
return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u);
}
#endif
@@ -218,10 +87,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si
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);
+ volatile uint32_t *reg = (volatile uint32_t *)(USB_DRD_BASE + bEpIdx*4);
*reg = wRegValue;
#else
- __O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
+ volatile uint16_t *reg = (volatile uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
*reg = (uint16_t)wRegValue;
#endif
}
@@ -229,9 +98,9 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, ui
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);
+ volatile const uint32_t *reg = (volatile const uint32_t *)(USB_DRD_BASE + bEpIdx*4);
#else
- __I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
+ volatile const uint16_t *reg = (volatile const uint16_t *)((&USBx->EP0R) + bEpIdx*2u);
#endif
return *reg;
}
@@ -283,7 +152,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USB
(void) USBx;
return (pma32[2*bEpIdx] & 0x03FF0000) >> 16;
#else
- __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
+ volatile const uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
return *regPtr & 0x3ffU;
#endif
}
@@ -293,7 +162,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USB
(void) USBx;
return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16;
#else
- __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
+ volatile const uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
return *regPtr & 0x3ffU;
#endif
}
@@ -363,7 +232,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, u
(void) USBx;
pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16);
#else
- __IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
+ volatile uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx);
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
#endif
}
@@ -375,7 +244,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_dbuf1_cnt(USB_TypeDef * U
(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);
+ volatile uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx);
*reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU);
#endif
}
@@ -387,7 +256,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDe
(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);
+ volatile uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u);
*pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10);
#endif
}
@@ -472,13 +341,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef *
return (regVal & USB_EPRX_STAT) >> (12u);
}
-
-/**
- * @brief Toggles DTOG_RX / DTOG_TX bit 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_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPREG_MASK;
@@ -493,12 +355,6 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
-/**
- * @brief Clears DTOG_RX / DTOG_TX bit 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_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
if((regVal & USB_EP_DTOG_RX) != 0) {
@@ -513,12 +369,6 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx,
}
}
-/**
- * @brief set & clear EP_KIND bit.
- * @param USBx USB peripheral instance register address.
- * @param bEpIdx Endpoint Number.
- * @retval None
- */
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;
@@ -534,18 +384,8 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, u
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
-// This checks if the device has "LPM"
-#if defined(USB_ISTR_L1REQ)
-#define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ)
-#else
-#define USB_ISTR_L1REQ_FORCED ((uint16_t)0x0000U)
+#ifdef __cplusplus
+ }
#endif
-#define USB_ISTR_ALL_EVENTS (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | \
- USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ_FORCED )
-
-// Number of endpoints in hardware
-// TODO should use TUP_DCD_ENDPOINT_MAX
-#define STFSDEV_EP_COUNT (8u)
-
-#endif /* PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ */
+#endif
diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h
new file mode 100644
index 000000000..b3fa11b88
--- /dev/null
+++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h
@@ -0,0 +1,292 @@
+/*
+ * The MIT License (MIT)
+ *
+ * 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.
+ */
+
+#ifndef TUSB_FSDEV_STM32_H
+#define TUSB_FSDEV_STM32_H
+
+#if CFG_TUSB_MCU == OPT_MCU_STM32F0
+ #include "stm32f0xx.h"
+ #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
+ // PMA dedicated to USB (no sharing with CAN)
+
+#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
+ #include "stm32f1xx.h"
+ #define FSDEV_PMA_SIZE (512u)
+ // NO internal Pull-ups
+ // *B, and *C: 2 x 16 bits/word
+
+ // F1 names this differently from the rest
+ #define USB_CNTR_LPMODE USB_CNTR_LP_MODE
+
+#elif defined(STM32F302xB) || defined(STM32F302xC) || \
+ defined(STM32F303xB) || defined(STM32F303xC) || \
+ defined(STM32F373xC)
+ #include "stm32f3xx.h"
+ #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)
+
+#elif defined(STM32F302x6) || defined(STM32F302x8) || \
+ defined(STM32F302xD) || defined(STM32F302xE) || \
+ defined(STM32F303xD) || defined(STM32F303xE)
+ #include "stm32f3xx.h"
+ #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 FSDEV_PMA_SIZE (1024u)
+
+#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
+ #include "stm32l1xx.h"
+ #define FSDEV_PMA_SIZE (512u)
+
+#elif CFG_TUSB_MCU == OPT_MCU_STM32G4
+ #include "stm32g4xx.h"
+ #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 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 FSDEV_PMA_SIZE (1024u)
+
+#elif CFG_TUSB_MCU == OPT_MCU_STM32L5
+ #include "stm32l5xx.h"
+ #define FSDEV_PMA_SIZE (1024u)
+
+ #ifndef USB_PMAADDR
+ #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS))
+ #endif
+
+#else
+ #error You are using an untested or unimplemented STM32 variant. Please update the driver.
+ // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4
+#endif
+
+// This checks if the device has "LPM"
+#if defined(USB_ISTR_L1REQ)
+#define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ)
+#else
+#define USB_ISTR_L1REQ_FORCED ((uint16_t)0x0000U)
+#endif
+
+#define USB_ISTR_ALL_EVENTS (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | \
+ USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ_FORCED )
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+#if TU_CHECK_MCU(OPT_MCU_STM32L1) && !defined(USBWakeUp_IRQn)
+ #define USBWakeUp_IRQn USB_FS_WKUP_IRQn
+#endif
+
+static const IRQn_Type fsdev_irq[] = {
+ #if TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32L0, OPT_MCU_STM32L4)
+ USB_IRQn,
+ #elif CFG_TUSB_MCU == OPT_MCU_STM32F1
+ USB_HP_CAN1_TX_IRQn,
+ USB_LP_CAN1_RX0_IRQn,
+ USBWakeUp_IRQn,
+ #elif CFG_TUSB_MCU == OPT_MCU_STM32F3
+ // USB remap handles dcd functions
+ USB_HP_CAN_TX_IRQn,
+ USB_LP_CAN_RX0_IRQn,
+ USBWakeUp_IRQn,
+ #elif CFG_TUSB_MCU == OPT_MCU_STM32G0
+ #ifdef STM32G0B0xx
+ USB_IRQn,
+ #else
+ USB_UCPD1_2_IRQn,
+ #endif
+ #elif TU_CHECK_MCU(OPT_MCU_STM32G4, OPT_MCU_STM32L1)
+ USB_HP_IRQn,
+ USB_LP_IRQn,
+ USBWakeUp_IRQn,
+ #elif CFG_TUSB_MCU == OPT_MCU_STM32H5
+ USB_DRD_FS_IRQn,
+ #elif CFG_TUSB_MCU == OPT_MCU_STM32L5
+ USB_FS_IRQn,
+ #elif CFG_TUSB_MCU == OPT_MCU_STM32WB
+ USB_HP_IRQn,
+ USB_LP_IRQn,
+ #else
+ #error Unknown arch in USB driver
+ #endif
+};
+enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) };
+
+void dcd_int_enable(uint8_t rhport) {
+ (void)rhport;
+
+ // forces write to RAM before allowing ISR to execute
+ __DSB(); __ISB();
+
+ #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP)
+ // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from
+ // shared USB/CAN IRQs to separate CAN and USB IRQs.
+ // This dynamically checks if this remap is active to enable the right IRQs.
+ if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) {
+ NVIC_EnableIRQ(USB_HP_IRQn);
+ NVIC_EnableIRQ(USB_LP_IRQn);
+ NVIC_EnableIRQ(USBWakeUp_RMP_IRQn);
+ } else
+ #endif
+ {
+ for (uint8_t i = 0; i < FSDEV_IRQ_NUM; i++) {
+ NVIC_EnableIRQ(fsdev_irq[i]);
+ }
+ }
+}
+
+void dcd_int_disable(uint8_t rhport) {
+ (void)rhport;
+
+ #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP)
+ // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from
+ // shared USB/CAN IRQs to separate CAN and USB IRQs.
+ // This dynamically checks if this remap is active to enable the right IRQs.
+ if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) {
+ NVIC_DisableIRQ(USB_HP_IRQn);
+ NVIC_DisableIRQ(USB_LP_IRQn);
+ NVIC_DisableIRQ(USBWakeUp_RMP_IRQn);
+ } else
+ #endif
+ {
+ for (uint8_t i = 0; i < FSDEV_IRQ_NUM; i++) {
+ NVIC_DisableIRQ(fsdev_irq[i]);
+ }
+ }
+
+ // CMSIS has a membar after disabling interrupts
+}
+
+// Define only on MCU with internal pull-up. BSP can define on MCU without internal PU.
+#if defined(USB_BCDR_DPPU)
+
+void dcd_disconnect(uint8_t rhport) {
+ (void)rhport;
+ USB->BCDR &= ~(USB_BCDR_DPPU);
+}
+
+void dcd_connect(uint8_t rhport) {
+ (void)rhport;
+ USB->BCDR |= USB_BCDR_DPPU;
+}
+
+#elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151
+
+void dcd_disconnect(uint8_t rhport) {
+ (void)rhport;
+ SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU);
+}
+
+void dcd_connect(uint8_t rhport) {
+ (void)rhport;
+ SYSCFG->PMC |= SYSCFG_PMC_USB_PU;
+}
+#endif
+
+
+#endif /* TUSB_FSDEV_STM32_H */
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index 692096fc8..dbcd586c5 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -1195,4 +1195,25 @@ void dcd_int_handler(uint8_t rhport) {
// }
}
+#if defined(TUP_USBIP_DWC2_TEST_MODE) && CFG_TUD_TEST_MODE
+
+bool dcd_check_test_mode_support(test_mode_t test_selector) {
+ // Check if test mode selector is unsupported
+ if (TEST_FORCE_ENABLE < test_selector || TEST_J > test_selector) {
+ return false;
+ }
+
+ return true;
+}
+
+void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) {
+ // Get port address...
+ dwc2_regs_t* dwc2 = DWC2_REG(rhport);
+
+ // Enable the test mode
+ dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (test_selector << DCTL_TCTL_Pos);
+}
+
+#endif /* TUP_USBIP_DWC2_TEST_MODE && CFG_TUD_TEST_MODE */
+
#endif
diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h
index c15771237..cb694b326 100644
--- a/src/portable/synopsys/dwc2/dwc2_type.h
+++ b/src/portable/synopsys/dwc2/dwc2_type.h
@@ -1,17 +1,34 @@
-/**
- * @author MCD Application Team
- * Ha Thach (tinyusb.org)
- *
- * @attention
- *
- * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024, hathach (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.
+ *
+ */
+/** <h2><center>&copy; Copyright (c) 2019 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
- *
*/
#ifndef _TUSB_DWC2_TYPES_H_
diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h
new file mode 100644
index 000000000..0a50a6169
--- /dev/null
+++ b/src/portable/wch/ch32_usbfs_reg.h
@@ -0,0 +1,111 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024 Matthew Tran
+ * Copyright (c) 2024 hathach
+ *
+ * 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 USB_CH32_USBFS_REG_H
+#define USB_CH32_USBFS_REG_H
+
+#if CFG_TUSB_MCU == OPT_MCU_CH32V307
+ #include <ch32v30x.h>
+ #define USBHD_IRQn OTG_FS_IRQn
+
+#elif CFG_TUSB_MCU == OPT_MCU_CH32V20X
+ #include <ch32v20x.h>
+
+#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X
+ #include <ch32f20x.h>
+#endif
+
+// CTRL
+#define USBFS_CTRL_DMA_EN (1 << 0)
+#define USBFS_CTRL_CLR_ALL (1 << 1)
+#define USBFS_CTRL_RESET_SIE (1 << 2)
+#define USBFS_CTRL_INT_BUSY (1 << 3)
+#define USBFS_CTRL_SYS_CTRL (1 << 4)
+#define USBFS_CTRL_DEV_PUEN (1 << 5)
+#define USBFS_CTRL_LOW_SPEED (1 << 6)
+#define USBFS_CTRL_HOST_MODE (1 << 7)
+
+// INT_EN
+#define USBFS_INT_EN_BUS_RST (1 << 0)
+#define USBFS_INT_EN_DETECT (1 << 0)
+#define USBFS_INT_EN_TRANSFER (1 << 1)
+#define USBFS_INT_EN_SUSPEND (1 << 2)
+#define USBFS_INT_EN_HST_SOF (1 << 3)
+#define USBFS_INT_EN_FIFO_OV (1 << 4)
+#define USBFS_INT_EN_DEV_NAK (1 << 6)
+#define USBFS_INT_EN_DEV_SOF (1 << 7)
+
+// INT_FG
+#define USBFS_INT_FG_BUS_RST (1 << 0)
+#define USBFS_INT_FG_DETECT (1 << 0)
+#define USBFS_INT_FG_TRANSFER (1 << 1)
+#define USBFS_INT_FG_SUSPEND (1 << 2)
+#define USBFS_INT_FG_HST_SOF (1 << 3)
+#define USBFS_INT_FG_FIFO_OV (1 << 4)
+#define USBFS_INT_FG_SIE_FREE (1 << 5)
+#define USBFS_INT_FG_TOG_OK (1 << 6)
+#define USBFS_INT_FG_IS_NAK (1 << 7)
+
+// INT_ST
+#define USBFS_INT_ST_MASK_UIS_ENDP(x) (((x) >> 0) & 0x0F)
+#define USBFS_INT_ST_MASK_UIS_TOKEN(x) (((x) >> 4) & 0x03)
+
+// UDEV_CTRL
+#define USBFS_UDEV_CTRL_PORT_EN (1 << 0)
+#define USBFS_UDEV_CTRL_GP_BIT (1 << 1)
+#define USBFS_UDEV_CTRL_LOW_SPEED (1 << 2)
+#define USBFS_UDEV_CTRL_DM_PIN (1 << 4)
+#define USBFS_UDEV_CTRL_DP_PIN (1 << 5)
+#define USBFS_UDEV_CTRL_PD_DIS (1 << 7)
+
+// TX_CTRL
+#define USBFS_EP_T_RES_MASK (3 << 0)
+#define USBFS_EP_T_TOG (1 << 2)
+#define USBFS_EP_T_AUTO_TOG (1 << 3)
+
+#define USBFS_EP_T_RES_ACK (0 << 0)
+#define USBFS_EP_T_RES_NYET (1 << 0)
+#define USBFS_EP_T_RES_NAK (2 << 0)
+#define USBFS_EP_T_RES_STALL (3 << 0)
+
+// RX_CTRL
+#define USBFS_EP_R_RES_MASK (3 << 0)
+#define USBFS_EP_R_TOG (1 << 2)
+#define USBFS_EP_R_AUTO_TOG (1 << 3)
+
+#define USBFS_EP_R_RES_ACK (0 << 0)
+#define USBFS_EP_R_RES_NYET (1 << 0)
+#define USBFS_EP_R_RES_NAK (2 << 0)
+#define USBFS_EP_R_RES_STALL (3 << 0)
+
+// token PID
+#define PID_OUT 0
+#define PID_SOF 1
+#define PID_IN 2
+#define PID_SETUP 3
+
+#endif // USB_CH32_USBFS_REG_H
diff --git a/src/portable/wch/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h
index 9b956231f..130e4f223 100644
--- a/src/portable/wch/ch32_usbhs_reg.h
+++ b/src/portable/wch/ch32_usbhs_reg.h
@@ -1,10 +1,37 @@
-#ifndef _USB_CH32_USBHS_REG_H
-#define _USB_CH32_USBHS_REG_H
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024 Matthew Tran
+ * Copyright (c) 2024 hathach
+ *
+ * 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.
+ */
-#if (CFG_TUSB_MCU == OPT_MCU_CH32V307)
-#include <ch32v30x.h>
-#elif (CFG_TUSB_MCU == OPT_MCU_CH32F20X)
-#include <ch32f20x.h>
+#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 ******************/
@@ -36,8 +63,13 @@
// USB DEV AD
#define USBHS_DEV_AD_OFFSET 0x03
+
// USB FRAME_NO
#define USBHS_FRAME_NO_OFFSET 0x04
+#define USBHS_FRAME_NO_NUM_MASK (0x7FF)
+#define USBHS_FRAME_NO_MICROFRAME_SHIFT (11)
+#define USBHS_FRAME_NO_MICROFRAME_MASK (0x7 << USBHS_FRAME_NO_MICROFRAME_SHIFT)
+
// USB SUSPEND
#define USBHS_SUSPEND_OFFSET 0x06
#define USBHS_DEV_REMOTE_WAKEUP (1 << 2)
@@ -47,7 +79,10 @@
// USB SPEED TYPE
#define USBHS_SPEED_TYPE_OFFSET 0x08
-#define USBSPEED_MASK (0x03)
+#define USBHS_SPEED_TYPE_MASK 0x03
+#define USBHS_SPEED_TYPE_FULL 0
+#define USBHS_SPEED_TYPE_HIGH 1
+#define USBHS_SPEED_TYPE_LOW 2
// USB_MIS_ST
#define USBHS_MIS_ST_OFFSET 0x09
@@ -72,12 +107,16 @@
#define USBHS_ISO_ACT_FLAG (1 << 6)
// INT_ST
-#define USBHS_INT_ST_OFFSET 0x0B
-#define USBHS_DEV_UIS_IS_NAK (1 << 7)
-#define USBHS_DEV_UIS_TOG_OK (1 << 6)
-#define MASK_UIS_TOKEN (3 << 4)
-#define MASK_UIS_ENDP (0x0F)
-#define MASK_UIS_H_RES (0x0F)
+#define USBHS_INT_ST_OFFSET 0x0B
+#define USBHS_DEV_UIS_IS_NAK (1 << 7)
+#define USBHS_DEV_UIS_TOG_OK (1 << 6)
+#define MASK_UIS_TOKEN (3 << 4)
+#define USBHS_TOKEN_PID_OUT (0 << 4)
+#define USBHS_TOKEN_PID_SOF (1 << 4)
+#define USBHS_TOKEN_PID_IN (2 << 4)
+#define USBHS_TOKEN_PID_SETUP (3 << 4)
+#define MASK_UIS_ENDP (0x0F)
+#define MASK_UIS_H_RES (0x0F)
#define USBHS_TOGGLE_OK (0x40)
#define USBHS_HOST_RES (0x0f)
@@ -340,10 +379,5 @@
#define USBHS_UH_T_TOG_AUTO (1 << 5)
#define USBHS_UH_T_DATA_NO (1 << 6)
-// 00: OUT, 01:SOF, 10:IN, 11:SETUP
-#define PID_OUT 0
-#define PID_SOF 1
-#define PID_IN 2
-#define PID_SETUP 3
#endif
diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c
new file mode 100644
index 000000000..9ed370b40
--- /dev/null
+++ b/src/portable/wch/dcd_ch32_usbfs.c
@@ -0,0 +1,344 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024 Matthew Tran
+ * Copyright (c) 2024 hathach
+ *
+ * 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_WCH_USBFS) && CFG_TUD_WCH_USBIP_USBFS
+
+#include "device/dcd.h"
+#include "ch32_usbfs_reg.h"
+
+/* private defines */
+#define EP_MAX (8)
+
+#define EP_DMA(ep) ((&USBOTG_FS->UEP0_DMA)[ep])
+#define EP_TX_LEN(ep) ((&USBOTG_FS->UEP0_TX_LEN)[2 * ep])
+#define EP_TX_CTRL(ep) ((&USBOTG_FS->UEP0_TX_CTRL)[4 * ep])
+#define EP_RX_CTRL(ep) ((&USBOTG_FS->UEP0_RX_CTRL)[4 * ep])
+
+/* private data */
+struct usb_xfer {
+ bool valid;
+ uint8_t* buffer;
+ size_t len;
+ size_t processed_len;
+ size_t max_size;
+};
+
+static struct {
+ bool ep0_tog;
+ bool isochronous[EP_MAX];
+ struct usb_xfer xfer[EP_MAX][2];
+ TU_ATTR_ALIGNED(4) uint8_t buffer[EP_MAX][2][64];
+ TU_ATTR_ALIGNED(4) struct {
+ // OUT transfers >64 bytes will overwrite queued IN data!
+ uint8_t out[64];
+ uint8_t in[1023];
+ uint8_t pad;
+ } ep3_buffer;
+} data;
+
+/* private helpers */
+static void update_in(uint8_t rhport, uint8_t ep, bool force) {
+ struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_IN];
+ if (xfer->valid) {
+ if (force || xfer->len) {
+ size_t len = TU_MIN(xfer->max_size, xfer->len);
+ if (ep == 0) {
+ memcpy(data.buffer[ep][TUSB_DIR_OUT], xfer->buffer, len); // ep0 uses same chunk
+ } else if (ep == 3) {
+ memcpy(data.ep3_buffer.in, xfer->buffer, len);
+ } else {
+ memcpy(data.buffer[ep][TUSB_DIR_IN], xfer->buffer, len);
+ }
+ xfer->buffer += len;
+ xfer->len -= len;
+ xfer->processed_len += len;
+
+ EP_TX_LEN(ep) = len;
+ if (ep == 0) {
+ EP_TX_CTRL(0) = USBFS_EP_T_RES_ACK | (data.ep0_tog ? USBFS_EP_T_TOG : 0);
+ data.ep0_tog = !data.ep0_tog;
+ } else if (data.isochronous[ep]) {
+ EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NYET;
+ } else {
+ EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_ACK;
+ }
+ } else {
+ xfer->valid = false;
+ EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK;
+ dcd_event_xfer_complete(
+ rhport, ep | TUSB_DIR_IN_MASK, xfer->processed_len,
+ XFER_RESULT_SUCCESS, true);
+ }
+ }
+}
+
+static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) {
+ struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_OUT];
+ if (xfer->valid) {
+ size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len));
+ if (ep == 3) {
+ memcpy(xfer->buffer, data.ep3_buffer.out, len);
+ } else {
+ memcpy(xfer->buffer, data.buffer[ep][TUSB_DIR_OUT], len);
+ }
+ xfer->buffer += len;
+ xfer->len -= len;
+ xfer->processed_len += len;
+
+ if (xfer->len == 0 || len < xfer->max_size) {
+ xfer->valid = false;
+ dcd_event_xfer_complete(rhport, ep, xfer->processed_len, XFER_RESULT_SUCCESS, true);
+ }
+
+ if (ep == 0) {
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+ }
+ }
+}
+
+/* public functions */
+void dcd_init(uint8_t rhport) {
+ // init registers
+ USBOTG_FS->BASE_CTRL = USBFS_CTRL_SYS_CTRL | USBFS_CTRL_INT_BUSY | USBFS_CTRL_DMA_EN;
+ USBOTG_FS->UDEV_CTRL = USBFS_UDEV_CTRL_PD_DIS | USBFS_UDEV_CTRL_PORT_EN;
+ USBOTG_FS->DEV_ADDR = 0x00;
+
+ USBOTG_FS->INT_FG = 0xFF;
+ USBOTG_FS->INT_EN = USBFS_INT_EN_BUS_RST | USBFS_INT_EN_TRANSFER | USBFS_INT_EN_SUSPEND;
+
+ // setup endpoint 0
+ EP_DMA(0) = (uint32_t) &data.buffer[0][0];
+ EP_TX_LEN(0) = 0;
+ EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK;
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+
+ // enable other endpoints but NAK everything
+ USBOTG_FS->UEP4_1_MOD = 0xCC;
+ USBOTG_FS->UEP2_3_MOD = 0xCC;
+ USBOTG_FS->UEP5_6_MOD = 0xCC;
+ USBOTG_FS->UEP7_MOD = 0x0C;
+
+ for (uint8_t ep = 1; ep < EP_MAX; ep++) {
+ EP_DMA(ep) = (uint32_t) &data.buffer[ep][0];
+ EP_TX_LEN(ep) = 0;
+ EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK;
+ EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NAK;
+ }
+ EP_DMA(3) = (uint32_t) &data.ep3_buffer.out[0];
+
+ dcd_connect(rhport);
+}
+
+void dcd_int_handler(uint8_t rhport) {
+ (void) rhport;
+ uint8_t status = USBOTG_FS->INT_FG;
+ if (status & USBFS_INT_FG_TRANSFER) {
+ uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST);
+ uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST);
+
+ switch (token) {
+ case PID_OUT: {
+ uint16_t rx_len = USBOTG_FS->RX_LEN;
+ update_out(rhport, ep, rx_len);
+ break;
+ }
+
+ case PID_IN:
+ update_in(rhport, ep, false);
+ break;
+
+ case PID_SETUP:
+ // setup clears stall
+ EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK;
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+
+ data.ep0_tog = true;
+ dcd_event_setup_received(rhport, &data.buffer[0][TUSB_DIR_OUT][0], true);
+ break;
+ }
+
+ USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER;
+ } else if (status & USBFS_INT_FG_BUS_RST) {
+ data.ep0_tog = true;
+ data.xfer[0][TUSB_DIR_OUT].max_size = 64;
+ data.xfer[0][TUSB_DIR_IN].max_size = 64;
+
+ dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true);
+
+ USBOTG_FS->DEV_ADDR = 0x00;
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+
+ USBOTG_FS->INT_FG = USBFS_INT_FG_BUS_RST;
+ } else if (status & USBFS_INT_FG_SUSPEND) {
+ dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_SUSPEND};
+ dcd_event_handler(&event, true);
+ USBOTG_FS->INT_FG = USBFS_INT_FG_SUSPEND;
+ }
+}
+
+void dcd_int_enable(uint8_t rhport) {
+ (void) rhport;
+ NVIC_EnableIRQ(USBHD_IRQn);
+}
+
+void dcd_int_disable(uint8_t rhport) {
+ (void) rhport;
+ NVIC_DisableIRQ(USBHD_IRQn);
+}
+
+void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
+ (void) dev_addr;
+ dcd_edpt_xfer(rhport, 0x80, NULL, 0); // zlp status response
+}
+
+void dcd_remote_wakeup(uint8_t rhport) {
+ (void) rhport;
+ // TODO optional
+}
+
+void dcd_connect(uint8_t rhport) {
+ (void) rhport;
+ USBOTG_FS->BASE_CTRL |= USBFS_CTRL_DEV_PUEN;
+}
+
+void dcd_disconnect(uint8_t rhport) {
+ (void) rhport;
+ USBOTG_FS->BASE_CTRL &= ~USBFS_CTRL_DEV_PUEN;
+}
+
+void dcd_sof_enable(uint8_t rhport, bool en) {
+ (void) rhport;
+ (void) en;
+
+ // TODO implement later
+}
+
+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) {
+ USBOTG_FS->DEV_ADDR = (uint8_t) request->wValue;
+ }
+ EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK;
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+}
+
+bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
+ (void) rhport;
+ uint8_t ep = tu_edpt_number(desc_ep->bEndpointAddress);
+ uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress);
+ TU_ASSERT(ep < EP_MAX);
+
+ data.isochronous[ep] = desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS;
+ data.xfer[ep][dir].max_size = tu_edpt_packet_size(desc_ep);
+
+ if (ep != 0) {
+ if (dir == TUSB_DIR_OUT) {
+ if (data.isochronous[ep]) {
+ EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_NYET;
+ } else {
+ EP_RX_CTRL(ep) = USBFS_EP_R_AUTO_TOG | USBFS_EP_R_RES_ACK;
+ }
+ } else {
+ EP_TX_LEN(ep) = 0;
+ EP_TX_CTRL(ep) = USBFS_EP_T_AUTO_TOG | USBFS_EP_T_RES_NAK;
+ }
+ }
+ return true;
+}
+
+void dcd_edpt_close_all(uint8_t rhport) {
+ (void) rhport;
+ // TODO optional
+}
+
+void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
+ (void) rhport;
+ (void) ep_addr;
+ // TODO optional
+}
+
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
+ (void) rhport;
+ uint8_t ep = tu_edpt_number(ep_addr);
+ uint8_t dir = tu_edpt_dir(ep_addr);
+
+ struct usb_xfer* xfer = &data.xfer[ep][dir];
+ dcd_int_disable(rhport);
+ xfer->valid = true;
+ xfer->buffer = buffer;
+ xfer->len = total_bytes;
+ xfer->processed_len = 0;
+ dcd_int_enable(rhport);
+
+ if (dir == TUSB_DIR_IN) {
+ update_in(rhport, ep, true);
+ }
+ return true;
+}
+
+void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
+ (void) rhport;
+ uint8_t ep = tu_edpt_number(ep_addr);
+ uint8_t dir = tu_edpt_dir(ep_addr);
+ if (ep == 0) {
+ if (dir == TUSB_DIR_OUT) {
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_STALL;
+ } else {
+ EP_TX_LEN(0) = 0;
+ EP_TX_CTRL(0) = USBFS_EP_T_RES_STALL;
+ }
+ } else {
+ if (dir == TUSB_DIR_OUT) {
+ EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | USBFS_EP_R_RES_STALL;
+ } else {
+ EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~USBFS_EP_T_RES_MASK) | USBFS_EP_T_RES_STALL;
+ }
+ }
+}
+
+void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
+ (void) rhport;
+ uint8_t ep = tu_edpt_number(ep_addr);
+ uint8_t dir = tu_edpt_dir(ep_addr);
+ if (ep == 0) {
+ if (dir == TUSB_DIR_OUT) {
+ EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
+ }
+ } else {
+ if (dir == TUSB_DIR_OUT) {
+ EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~(USBFS_EP_R_RES_MASK | USBFS_EP_R_TOG)) | USBFS_EP_R_RES_ACK;
+ } else {
+ EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK | USBFS_EP_T_TOG)) | USBFS_EP_T_RES_NAK;
+ }
+ }
+}
+
+#endif
diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c
index 68e2179e9..622f9c508 100644
--- a/src/portable/wch/dcd_ch32_usbhs.c
+++ b/src/portable/wch/dcd_ch32_usbhs.c
@@ -2,6 +2,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2022 Greg Davill
+ * Copyright (c) 2023 Denis Krasutski
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,379 +27,394 @@
#include "tusb_option.h"
-#if CFG_TUD_ENABLED && ((CFG_TUSB_MCU == OPT_MCU_CH32V307) || (CFG_TUSB_MCU == OPT_MCU_CH32F20X))
-#include "device/dcd.h"
-
+#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && CFG_TUD_WCH_USBIP_USBHS
#include "ch32_usbhs_reg.h"
+#include "device/dcd.h"
// Max number of bi-directional endpoints including EP0
-#define EP_MAX 16
+#define EP_MAX 16
typedef struct {
- uint8_t *buffer;
- // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API
- uint16_t total_len;
- uint16_t queued_len;
- uint16_t max_size;
- bool short_packet;
+ uint8_t* buffer;
+ uint16_t total_len;
+ uint16_t queued_len;
+ uint16_t max_size;
+ bool is_last_packet;
+ bool is_iso;
} xfer_ctl_t;
+typedef enum {
+ EP_RESPONSE_ACK,
+ EP_RESPONSE_NAK,
+} ep_response_list_t;
+
#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir]
static xfer_ctl_t xfer_status[EP_MAX][2];
-#define EP_TX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_TX_LEN) + (ep)*2)
-#define EP_TX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_TX_CTRL) + (ep)*4)
-#define EP_RX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_RX_CTRL) + (ep)*4)
-#define EP_RX_MAX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_MAX_LEN) + (ep)*2)
+#define EP_TX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_TX_LEN) + (ep) * 2)
+#define EP_TX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_TX_CTRL) + (ep) * 4)
+#define EP_RX_CTRL(ep) *(volatile uint8_t *)((volatile uint8_t *)&(USBHSD->UEP0_RX_CTRL) + (ep) * 4)
+#define EP_RX_MAX_LEN(ep) *(volatile uint16_t *)((volatile uint16_t *)&(USBHSD->UEP0_MAX_LEN) + (ep) * 2)
#define EP_TX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_TX_DMA) + (ep - 1))
#define EP_RX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_RX_DMA) + (ep - 1))
/* Endpoint Buffer */
-TU_ATTR_ALIGNED(4) uint8_t EP0_DatabufHD[64]; // ep0(64)
+TU_ATTR_ALIGNED(4) static uint8_t ep0_buffer[CFG_TUD_ENDPOINT0_SIZE];
+
+static void ep_set_response_and_toggle(uint8_t ep_num, tusb_dir_t ep_dir, ep_response_list_t response_type) {
+ if (ep_dir == TUSB_DIR_IN) {
+ uint8_t response = (response_type == EP_RESPONSE_ACK) ? USBHS_EP_T_RES_ACK : USBHS_EP_T_RES_NAK;
+ if (ep_num == 0) {
+ if (response_type == EP_RESPONSE_ACK) {
+ if (EP_TX_LEN(ep_num) == 0) {
+ EP_TX_CTRL(ep_num) |= USBHS_EP_T_TOG_1;
+ } else {
+ EP_TX_CTRL(ep_num) ^= USBHS_EP_T_TOG_1;
+ }
+ }
+ }
+ if (xfer_status[ep_num][TUSB_DIR_IN].is_iso == true) {
+ EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG;
+ } else {
+ EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | response;
+ }
+ } else {
+ uint8_t response = (response_type == EP_RESPONSE_ACK) ? USBHS_EP_R_RES_ACK : USBHS_EP_R_RES_NAK;
+ if (ep_num == 0) {
+ if (response_type == EP_RESPONSE_ACK) {
+ if (xfer_status[ep_num][TUSB_DIR_OUT].queued_len == 0) {
+ EP_RX_CTRL(ep_num) |= USBHS_EP_R_TOG_1;
+ }
+ } else {
+ EP_RX_CTRL(ep_num) ^= USBHS_EP_R_TOG_1;
+ }
+ }
+ EP_RX_CTRL(ep_num) = (EP_RX_CTRL(ep_num) & ~(USBHS_EP_R_RES_MASK)) | response;
+ }
+}
+
+static void xfer_data_packet(uint8_t ep_num, tusb_dir_t ep_dir, xfer_ctl_t* xfer) {
+ if (ep_dir == TUSB_DIR_IN) {
+ uint16_t remaining = xfer->total_len - xfer->queued_len;
+ uint16_t next_tx_size = TU_MIN(remaining, xfer->max_size);
+
+ if (ep_num == 0) {
+ memcpy(ep0_buffer, &xfer->buffer[xfer->queued_len], next_tx_size);
+ } else {
+ EP_TX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len];
+ }
+
+ EP_TX_LEN(ep_num) = next_tx_size;
+ xfer->queued_len += next_tx_size;
+ if (xfer->queued_len == xfer->total_len) {
+ xfer->is_last_packet = true;
+ }
+ if (xfer->is_iso == true) {
+ /* Enable EP to generate ISA_ACT interrupt */
+ USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num);
+ }
+ } else { /* TUSB_DIR_OUT */
+ uint16_t left_to_receive = xfer->total_len - xfer->queued_len;
+ uint16_t max_possible_rx_size = TU_MIN(xfer->max_size, left_to_receive);
-volatile uint8_t USBHS_Dev_Endp0_Tog = 0x01;
+ if (max_possible_rx_size == left_to_receive) {
+ xfer->is_last_packet = true;
+ }
+
+ if (ep_num > 0) {
+ EP_RX_DMA_ADDR(ep_num) = (uint32_t) &xfer->buffer[xfer->queued_len];
+ EP_RX_MAX_LEN(ep_num) = max_possible_rx_size;
+ }
+ }
+ ep_set_response_and_toggle(ep_num, ep_dir, USBHS_EP_R_RES_ACK);
+}
void dcd_init(uint8_t rhport) {
- (void)rhport;
+ (void) rhport;
- memset(&xfer_status, 0, sizeof(xfer_status));
+ memset(&xfer_status, 0, sizeof(xfer_status));
- USBHSD->HOST_CTRL = 0x00;
- USBHSD->HOST_CTRL = USBHS_PHY_SUSPENDM;
+ USBHSD->HOST_CTRL = 0x00;
+ USBHSD->HOST_CTRL = USBHS_PHY_SUSPENDM;
- USBHSD->CONTROL = 0;
+ USBHSD->CONTROL = 0;
#if TUD_OPT_HIGH_SPEED
- USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED;
+ USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED;
#else
- #error OPT_MODE_FULL_SPEED not currently supported on CH32
- USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_FULL_SPEED;
+ #error OPT_MODE_FULL_SPEED not currently supported on CH32
+ USBHSD->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_FULL_SPEED;
#endif
- USBHSD->INT_EN = 0;
- USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_DETECT_EN | USBHS_SUSPEND_EN;
-
- /* ALL endpoint enable */
- USBHSD->ENDP_CONFIG = 0xffffffff;
-
- USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN;
- USBHSD->ENDP_TYPE = 0x00;
- USBHSD->BUF_MODE = 0x00;
+ USBHSD->INT_EN = 0;
+ USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_BUS_RST_EN | USBHS_SUSPEND_EN | USBHS_ISO_ACT_EN;
- USBHSD->UEP0_MAX_LEN = 64;
+ USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN;
+ USBHSD->ENDP_TYPE = 0x00;
+ USBHSD->BUF_MODE = 0x00;
- USBHSD->UEP0_DMA = (uint32_t)EP0_DatabufHD;
+ for (int ep = 0; ep < EP_MAX; ep++) {
+ EP_TX_LEN(ep) = 0;
+ EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK;
+ EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
- USBHSD->UEP0_TX_LEN = 0;
- USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_NAK;
- USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK;
+ EP_RX_MAX_LEN(ep) = 0;
+ }
- for (int ep = 1; ep < EP_MAX; ep++) {
- EP_TX_LEN(ep) = 0;
- EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK;
- EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ USBHSD->UEP0_DMA = (uint32_t) ep0_buffer;
+ USBHSD->UEP0_MAX_LEN = CFG_TUD_ENDPOINT0_SIZE;
+ xfer_status[0][TUSB_DIR_OUT].max_size = CFG_TUD_ENDPOINT0_SIZE;
+ xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE;
- EP_RX_MAX_LEN(ep) = 512;
- }
-
- USBHSD->DEV_AD = 0;
- USBHSD->CONTROL |= USBHS_DEV_PU_EN;
+ USBHSD->DEV_AD = 0;
+ USBHSD->CONTROL |= USBHS_DEV_PU_EN;
}
void dcd_int_enable(uint8_t rhport) {
- (void)rhport;
-
- NVIC_EnableIRQ(USBHS_IRQn);
+ (void) rhport;
+ NVIC_EnableIRQ(USBHS_IRQn);
}
void dcd_int_disable(uint8_t rhport) {
- (void)rhport;
-
- NVIC_DisableIRQ(USBHS_IRQn);
+ (void) rhport;
+ NVIC_DisableIRQ(USBHS_IRQn);
}
void dcd_edpt_close_all(uint8_t rhport) {
- (void)rhport;
+ (void) rhport;
+
+ for (size_t ep = 1; ep < EP_MAX; ep++) {
+ EP_TX_LEN(ep) = 0;
+ EP_TX_CTRL(ep) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK;
+ EP_RX_CTRL(ep) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+
+ EP_RX_MAX_LEN(ep) = 0;
+ }
+
+ USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN;
}
void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
- (void)dev_addr;
+ (void) dev_addr;
- // Response with zlp status
- dcd_edpt_xfer(rhport, 0x80, NULL, 0);
+ // Response with zlp status
+ dcd_edpt_xfer(rhport, 0x80, NULL, 0);
}
-void dcd_remote_wakeup(uint8_t rhport)
-{
+void dcd_remote_wakeup(uint8_t rhport) {
(void) rhport;
}
-void dcd_sof_enable(uint8_t rhport, bool en)
-{
- (void) rhport;
- if (en) {
- USBHSD->INT_EN |= USBHS_SOF_ACT_EN;
- } else {
- USBHSD->INT_EN &= ~(USBHS_SOF_ACT_EN);
- }
+void dcd_sof_enable(uint8_t rhport, bool en) {
+ (void) rhport;
+ if (en) {
+ USBHSD->INT_EN |= USBHS_SOF_ACT_EN;
+ } else {
+ USBHSD->INT_EN &= ~(USBHS_SOF_ACT_EN);
+ }
}
-void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) {
- (void)rhport;
+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) {
- USBHSD->DEV_AD = (uint8_t)request->wValue;
- }
+ if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
+ request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
+ request->bRequest == TUSB_REQ_SET_ADDRESS) {
+ USBHSD->DEV_AD = (uint8_t) request->wValue;
+ }
- EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK;
- EP_RX_CTRL(0) = USBHS_EP_R_RES_ACK;
+ EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ EP_RX_CTRL(0) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0;
}
-bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) {
- (void)rhport;
-
- uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
- uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
+bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
+ (void) rhport;
- TU_ASSERT(epnum < EP_MAX);
+ uint8_t const ep_num = tu_edpt_number(desc_edpt->bEndpointAddress);
+ tusb_dir_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
- xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir);
- xfer->max_size = tu_edpt_packet_size(desc_edpt);
-
- if (epnum != 0) {
- if (tu_edpt_dir(desc_edpt->bEndpointAddress) == TUSB_DIR_OUT) {
- EP_RX_CTRL(epnum) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_ACK;
- } else {
- EP_TX_LEN(epnum) = 0;
- EP_TX_CTRL(epnum) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
- }
- }
+ TU_ASSERT(ep_num < EP_MAX);
+ if (ep_num == 0) {
return true;
-}
-
-int usbd_ep_close(const uint8_t ep) {
- (void)ep;
-
- return 0;
-}
-void dcd_edpt_stall(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);
+ xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, dir);
+ xfer->max_size = tu_edpt_packet_size(desc_edpt);
- if (epnum == 0) {
- if (dir == TUSB_DIR_OUT) {
- USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_STALL;
- } else {
- USBHSD->UEP0_TX_LEN = 0;
- USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_STALL;
- }
- } else {
- if (dir == TUSB_DIR_OUT) {
- EP_RX_CTRL(epnum) = (EP_RX_CTRL(epnum) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_STALL;
-
- } else {
- EP_TX_CTRL(epnum) = (EP_TX_CTRL(epnum) & ~USBHS_EP_T_RES_MASK) | USBHS_EP_T_RES_STALL;
- }
+ xfer->is_iso = (desc_edpt->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS);
+ if (dir == TUSB_DIR_OUT) {
+ USBHSD->ENDP_CONFIG |= (USBHS_EP0_R_EN << ep_num);
+ EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ if (xfer->is_iso == true) {
+ USBHSD->ENDP_TYPE |= (USBHS_EP0_R_TYP << ep_num);
}
-}
-
-void dcd_edpt_clear_stall(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);
-
- if (epnum == 0) {
- if (dir == TUSB_DIR_OUT) {
- USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK;
- } else {
- }
+ EP_RX_MAX_LEN(ep_num) = xfer->max_size;
+ } else {
+ if (xfer->is_iso == true) {
+ USBHSD->ENDP_TYPE |= (USBHS_EP0_T_TYP << ep_num);
} else {
- if (dir == TUSB_DIR_OUT) {
- EP_RX_CTRL(epnum) = (EP_RX_CTRL(epnum) & ~(USBHS_EP_R_RES_MASK | USBHS_EP_T_TOG_MASK)) | USBHS_EP_T_RES_ACK;
-
- } else {
- EP_TX_CTRL(epnum) = (EP_TX_CTRL(epnum) & ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK)) | USBHS_EP_T_RES_NAK;
- }
+ /* Enable all types except Isochronous to avoid ISO_ACT interrupt generation */
+ USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num);
}
-}
-
-bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) {
- (void)rhport;
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ EP_TX_LEN(ep_num) = 0;
+ EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ }
- xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir);
- xfer->buffer = buffer;
- // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API
- xfer->total_len = total_bytes;
- xfer->queued_len = 0;
- xfer->short_packet = false;
+ return true;
+}
- // uint16_t num_packets = (total_bytes / xfer->max_size);
- uint16_t short_packet_size = total_bytes % (xfer->max_size + 1);
+void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
+ (void) rhport;
- // Zero-size packet is special case.
- if (short_packet_size == 0 || (total_bytes == 0)) {
- xfer->short_packet = true;
- }
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const dir = tu_edpt_dir(ep_addr);
- if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) {
- if (!total_bytes) {
- xfer->short_packet = true;
- if (epnum == 0) {
- USBHSD->UEP0_TX_LEN = 0;
- USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_ACK | (USBHS_Dev_Endp0_Tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
- USBHS_Dev_Endp0_Tog ^= 1;
- } else {
- EP_TX_LEN(epnum) = 0;
- EP_TX_CTRL(epnum) = (EP_TX_CTRL(epnum) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_ACK;
- }
- } else {
- if (epnum == 0) {
- xfer->queued_len += short_packet_size;
- memcpy(&EP0_DatabufHD[0], buffer, short_packet_size);
+ if (dir == TUSB_DIR_OUT) {
+ EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ EP_RX_MAX_LEN(ep_num) = 0;
+ USBHSD->ENDP_TYPE &= ~(USBHS_EP0_R_TYP << ep_num);
+ USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_R_EN << ep_num);
+ } else { // TUSB_DIR_IN
+ EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
+ EP_TX_LEN(ep_num) = 0;
+ USBHSD->ENDP_TYPE &= ~(USBHS_EP0_T_TYP << ep_num);
+ USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num);
+ }
+}
- USBHSD->UEP0_TX_LEN = short_packet_size;
- USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_ACK | (USBHS_Dev_Endp0_Tog ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
- USBHS_Dev_Endp0_Tog ^= 1;
- } else {
- xfer->queued_len += short_packet_size;
+void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
+ (void) rhport;
- EP_TX_DMA_ADDR(epnum) = (uint32_t)buffer;
- USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << epnum);
- EP_TX_LEN(epnum) = short_packet_size;
- EP_TX_CTRL(epnum) = (EP_TX_CTRL(epnum) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_ACK;
- }
- }
- } else { /* TUSB_DIR_OUT */
- if (epnum == 0) {
- uint32_t read_count = USBHSD->RX_LEN;
- read_count = TU_MIN(read_count, total_bytes);
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const dir = tu_edpt_dir(ep_addr);
- if ((total_bytes == 8)) {
- read_count = 8;
- memcpy(buffer, &EP0_DatabufHD[0], 8);
- } else {
- memcpy(buffer, &EP0_DatabufHD[0], read_count);
- }
- } else {
- EP_RX_DMA_ADDR(epnum) = (uint32_t)xfer->buffer;
- USBHSD->ENDP_CONFIG |= (USBHS_EP0_R_EN << epnum);
- }
-
- // usbd_ep_read(ep_addr, buffer, total_bytes, &ret_bytes);
- }
- return true;
+ if (dir == TUSB_DIR_OUT) {
+ EP_RX_CTRL(ep_num) = USBHS_EP_R_RES_STALL;
+ } else {
+ EP_TX_LEN(0) = 0;
+ EP_TX_CTRL(ep_num) = USBHS_EP_T_RES_STALL;
+ }
}
+void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
+ (void) rhport;
-static void receive_packet(xfer_ctl_t *xfer, uint16_t xfer_size) {
- // xfer->queued_len = xfer->total_len - remaining;
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const dir = tu_edpt_dir(ep_addr);
- uint16_t remaining = xfer->total_len - xfer->queued_len;
- uint16_t to_recv_size;
+ if (dir == TUSB_DIR_OUT) {
+ EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK;
+ } else {
+ EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_R_RES_NAK;
+ }
+}
- if (remaining <= xfer->max_size) {
- // Avoid buffer overflow.
- to_recv_size = (xfer_size > remaining) ? remaining : xfer_size;
- } else {
- // Room for full packet, choose recv_size based on what the microcontroller
- // claims.
- to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size;
- }
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
+ (void) rhport;
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const dir = tu_edpt_dir(ep_addr);
- if (to_recv_size) {
- }
+ xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, dir);
+ xfer->buffer = buffer;
+ xfer->total_len = total_bytes;
+ xfer->queued_len = 0;
+ xfer->is_last_packet = false;
- xfer->queued_len += xfer_size;
+ xfer_data_packet(ep_num, dir, xfer);
- // Per USB spec, a short OUT packet (including length 0) is always
- // indicative of the end of a transfer (at least for ctl, bulk, int).
- xfer->short_packet = (xfer_size < xfer->max_size);
+ return true;
}
void dcd_int_handler(uint8_t rhport) {
- (void)rhport;
-
- uint32_t end_num, rx_token;
- uint8_t intflag = 0;
-
- intflag = USBHSD->INT_FG;
-
- if (intflag & USBHS_TRANSFER_FLAG) {
-
- end_num = (USBHSD->INT_ST) & MASK_UIS_ENDP;
- rx_token = (((USBHSD->INT_ST) & MASK_UIS_TOKEN) >> 4) & 0x03;
-
- uint8_t endp = end_num | (rx_token == PID_IN ? TUSB_DIR_IN_MASK : 0);
-
- xfer_ctl_t *xfer = XFER_CTL_BASE(end_num, tu_edpt_dir(endp));
-
- if (rx_token == PID_SOF) {
- dcd_event_sof(rhport, USBHSD->FRAME_NO, true);
-
- } else if (rx_token == PID_OUT) {
- uint16_t rx_len = USBHSD->RX_LEN;
-
- receive_packet(xfer, rx_len);
+ (void) rhport;
- if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) {
- xfer->short_packet = false;
+ uint8_t int_flag = USBHSD->INT_FG;
+ uint8_t int_status = USBHSD->INT_ST;
- dcd_event_xfer_complete(0, endp, xfer->queued_len, XFER_RESULT_SUCCESS, true);
- }
+ if (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)) {
+ uint8_t const token = int_status & MASK_UIS_TOKEN;
- if (end_num == 0) {
- USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0;
- }
+ if (token == USBHS_TOKEN_PID_SOF) {
+ uint32_t frame_count = USBHSD->FRAME_NO & USBHS_FRAME_NO_NUM_MASK;
+ dcd_event_sof(rhport, frame_count, true);
+ }else {
+ uint8_t const ep_num = int_status & MASK_UIS_ENDP;
+ tusb_dir_t const ep_dir = (token == USBHS_TOKEN_PID_IN) ? TUSB_DIR_IN : TUSB_DIR_OUT;
+ uint8_t const ep_addr = tu_edpt_addr(ep_num, ep_dir);
+ xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, ep_dir);
- } else if (rx_token == PID_IN) {
- if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) {
- xfer->short_packet = false;
- xfer->total_len = 0;
- dcd_event_xfer_complete(0, endp, xfer->queued_len, XFER_RESULT_SUCCESS, true);
+ if (token == USBHS_TOKEN_PID_OUT) {
+ uint16_t rx_len = USBHSD->RX_LEN;
- EP_TX_CTRL(end_num) = (EP_TX_CTRL(end_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NAK;
+ if (ep_num == 0) {
+ memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, rx_len);
+ }
- if (end_num == 0) {
- }
- } else {
- dcd_edpt_xfer(0, endp, xfer->buffer + xfer->queued_len, xfer->total_len - xfer->queued_len);
- }
+ xfer->queued_len += rx_len;
+ if (rx_len < xfer->max_size) {
+ xfer->is_last_packet = true;
+ }
+ } else if (token == USBHS_TOKEN_PID_IN) {
+ if (xfer->is_iso && xfer->is_last_packet) {
+ /* Disable EP to avoid ISO_ACT interrupt generation */
+ USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num);
+ } else {
+ // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet
}
+ }
- USBHSD->INT_FG = USBHS_TRANSFER_FLAG; /* Clear flag */
- } else if (intflag & USBHS_SETUP_FLAG) {
- USBHS_Dev_Endp0_Tog = 1;
- dcd_event_setup_received(0, EP0_DatabufHD, true);
+ if (xfer->is_last_packet == true) {
+ ep_set_response_and_toggle(ep_num, ep_dir, EP_RESPONSE_NAK);
+ dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true);
+ } else {
+ /* prepare next part of packet to xref */
+ xfer_data_packet(ep_num, ep_dir, xfer);
+ }
+ }
- USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */
- } else if (intflag & USBHS_DETECT_FLAG) {
- USBHS_Dev_Endp0_Tog = 1;
+ USBHSD->INT_FG = (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)); /* Clear flag */
+ } else if (int_flag & USBHS_SETUP_FLAG) {
+ ep_set_response_and_toggle(0, TUSB_DIR_IN, EP_RESPONSE_NAK);
+ ep_set_response_and_toggle(0, TUSB_DIR_OUT, EP_RESPONSE_NAK);
+ dcd_event_setup_received(0, ep0_buffer, true);
- xfer_status[0][TUSB_DIR_OUT].max_size = 64;
- xfer_status[0][TUSB_DIR_IN].max_size = 64;
+ USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */
+ } else if (int_flag & USBHS_BUS_RST_FLAG) {
+ // TODO CH32 does not detect actual speed at this time (should be known at end of reset)
+ // This interrupt probably triggered at start of bus reset
+// tusb_speed_t actual_speed;
+// switch(USBHSD->SPEED_TYPE & USBHS_SPEED_TYPE_MASK){
+// case USBHS_SPEED_TYPE_HIGH:
+// actual_speed = TUSB_SPEED_HIGH;
+// break;
+// case USBHS_SPEED_TYPE_FULL:
+// actual_speed = TUSB_SPEED_FULL;
+// break;
+// case USBHS_SPEED_TYPE_LOW:
+// actual_speed = TUSB_SPEED_LOW;
+// break;
+// default:
+// TU_ASSERT(0,);
+// break;
+// }
+// dcd_event_bus_reset(0, actual_speed, true);
- dcd_event_bus_reset(0, TUSB_SPEED_HIGH, true);
+ dcd_event_bus_reset(0, TUSB_SPEED_HIGH, true);
- USBHSD->DEV_AD = 0;
- USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0;
+ USBHSD->DEV_AD = 0;
+ EP_RX_CTRL(0) = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0;
+ EP_TX_CTRL(0) = USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0;
- USBHSD->INT_FG = USBHS_DETECT_FLAG; /* Clear flag */
- } else if (intflag & USBHS_SUSPEND_FLAG) {
- dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SUSPEND };
- dcd_event_handler(&event, true);
+ USBHSD->INT_FG = USBHS_BUS_RST_FLAG; /* Clear flag */
+ } else if (int_flag & USBHS_SUSPEND_FLAG) {
+ dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_SUSPEND};
+ dcd_event_handler(&event, true);
- USBHSD->INT_FG = USBHS_SUSPEND_FLAG; /* Clear flag */
- }
+ USBHSD->INT_FG = USBHS_SUSPEND_FLAG; /* Clear flag */
+ }
}
#endif
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 8d5527936..db8b94580 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -29,14 +29,12 @@
#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.
+// Version is release as major.minor.revision eg 1.0.0
#define TUSB_VERSION_MAJOR 0
-#define TUSB_VERSION_MINOR 16
+#define TUSB_VERSION_MINOR 17
#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_NUMBER (TUSB_VERSION_MAJOR * 10000 + TUSB_VERSION_MINOR * 100 + TUSB_VERSION_REVISION)
#define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION)
//--------------------------------------------------------------------+
@@ -123,6 +121,8 @@
#define OPT_MCU_ESP32 902 ///< Espressif ESP32 (for host max3421e)
#define OPT_MCU_ESP32C3 903 ///< Espressif ESP32-C3
#define OPT_MCU_ESP32C6 904 ///< Espressif ESP32-C6
+#define OPT_MCU_ESP32C2 905 ///< Espressif ESP32-C2
+#define OPT_MCU_ESP32H2 906 ///< Espressif ESP32-H2
#define TUP_MCU_ESPRESSIF (CFG_TUSB_MCU >= 900 && CFG_TUSB_MCU < 1000) // check if Espressif MCU
// Dialog
@@ -181,6 +181,7 @@
// WCH
#define OPT_MCU_CH32V307 2200 ///< WCH CH32V307
#define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x
+#define OPT_MCU_CH32V20X 2220 ///< WCH CH32V20X
// NXP LPC MCX
@@ -204,19 +205,9 @@
#define OPT_OS_RTTHREAD 6 ///< RT-Thread
#define OPT_OS_RTX4 7 ///< Keil RTX 4
-// Allow to use command line to change the config name/location
-#ifdef CFG_TUSB_CONFIG_FILE
- #include CFG_TUSB_CONFIG_FILE
-#else
- #include "tusb_config.h"
-#endif
-
-#include "common/tusb_mcu.h"
-
-//--------------------------------------------------------------------
-// RootHub Mode Configuration
-// CFG_TUSB_RHPORTx_MODE contains operation mode and speed for that port
-//--------------------------------------------------------------------
+//--------------------------------------------------------------------+
+// Mode and Speed
+//--------------------------------------------------------------------+
// Low byte is operational mode
#define OPT_MODE_NONE 0x0000 ///< Disabled
@@ -230,7 +221,24 @@
#define OPT_MODE_HIGH_SPEED 0x0400 ///< High Speed
#define OPT_MODE_SPEED_MASK 0xff00
-//------------- Roothub as Device -------------//
+//--------------------------------------------------------------------+
+// Include tusb_config.h and tusb_mcu.h
+//--------------------------------------------------------------------+
+
+// Allow to use command line to change the config name/location
+#ifdef CFG_TUSB_CONFIG_FILE
+ #include CFG_TUSB_CONFIG_FILE
+#else
+ #include "tusb_config.h"
+#endif
+
+#include "common/tusb_mcu.h"
+
+//--------------------------------------------------------------------
+// RootHub Mode detection
+//--------------------------------------------------------------------
+
+//------------- Root hub as Device -------------//
#if defined(CFG_TUSB_RHPORT0_MODE) && ((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_DEVICE)
#define TUD_RHPORT_MODE (CFG_TUSB_RHPORT0_MODE)
@@ -258,7 +266,7 @@
// highspeed support indicator
#define TUD_OPT_HIGH_SPEED (CFG_TUD_MAX_SPEED ? (CFG_TUD_MAX_SPEED & OPT_MODE_HIGH_SPEED) : TUP_RHPORT_HIGHSPEED)
-//------------- Roothub as Host -------------//
+//------------- Root hub as Host -------------//
#if defined(CFG_TUSB_RHPORT0_MODE) && ((CFG_TUSB_RHPORT0_MODE) & OPT_MODE_HOST)
#define TUH_RHPORT_MODE (CFG_TUSB_RHPORT0_MODE)
@@ -364,6 +372,20 @@
#define CFG_TUD_INTERFACE_MAX 16
#endif
+// default to max hardware endpoint, but can be smaller to save RAM
+#ifndef CFG_TUD_ENDPPOINT_MAX
+ #define CFG_TUD_ENDPPOINT_MAX TUP_DCD_ENDPOINT_MAX
+#endif
+
+#if CFG_TUD_ENDPPOINT_MAX > TUP_DCD_ENDPOINT_MAX
+ #error "CFG_TUD_ENDPPOINT_MAX must be less than or equal to TUP_DCD_ENDPOINT_MAX"
+#endif
+
+// USB 2.0 compliance test mode support
+#ifndef CFG_TUD_TEST_MODE
+ #define CFG_TUD_TEST_MODE 0
+#endif
+
//------------- Device Class Driver -------------//
#ifndef CFG_TUD_BTH
#define CFG_TUD_BTH 0
@@ -459,26 +481,26 @@
#define CFG_TUH_CDC 0
#endif
+// FTDI is not part of CDC class, only to re-use CDC driver API
#ifndef CFG_TUH_CDC_FTDI
- // FTDI is not part of CDC class, only to re-use CDC driver API
#define CFG_TUH_CDC_FTDI 0
#endif
+// List of product IDs that can use the FTDI CDC driver. 0x0403 is FTDI's VID
#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
+// CP210X is not part of CDC class, only to re-use CDC driver API
#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
+// List of product IDs that can use the CP210X CDC driver. 0x10C4 is Silicon Labs' VID
#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
@@ -488,8 +510,8 @@
#define CFG_TUH_CDC_CH34X 0
#endif
+// List of product IDs that can use the CH34X CDC driver
#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 */ \