From 1755bba509edf2d5bc49cadecb6e956497732b37 Mon Sep 17 00:00:00 2001 From: Rocky04 Date: Mon, 15 Jan 2024 12:47:13 +0000 Subject: [PATCH 01/48] Add DWC2 Test Mode SUpport --- src/common/tusb_mcu.h | 2 + src/device/dcd.h | 28 ++++++++++++++ src/device/usbd.c | 53 ++++++++++++++++++++++++--- src/portable/synopsys/dwc2/dcd_dwc2.c | 30 +++++++++++++++ 4 files changed, 107 insertions(+), 6 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 35f94efbc..146accabf 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -195,6 +195,7 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32F7) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 + #define TUP_USBIP_DWC2_TEST_MODE_SUPPORT // FS has 6, HS has 9 #define TUP_DCD_ENDPOINT_MAX 9 @@ -262,6 +263,7 @@ #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_USBIP_DWC2_TEST_MODE_SUPPORT #elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV diff --git a/src/device/dcd.h b/src/device/dcd.h index 18a708347..7755ef107 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -58,6 +58,7 @@ typedef enum DCD_EVENT_SETUP_RECEIVED, DCD_EVENT_XFER_COMPLETE, + DCD_EVENT_TEST_MODE, // Not an DCD event, just a convenient way to defer ISR function USBD_EVENT_FUNC_CALL, @@ -97,9 +98,23 @@ typedef struct TU_ATTR_ALIGNED(4) void (*func) (void*); void* param; }func_call; + + // TEST MODE + struct { + uint8_t selector; + }test_mode; }; } dcd_event_t; +typedef enum _test_mode_selector +{ + 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"); //--------------------------------------------------------------------+ @@ -149,6 +164,12 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Enable/Disable Start-of-frame interrupt. Default is disabled void dcd_sof_enable(uint8_t rhport, bool en); +// Check if the test mode is supported +bool dcd_test_mode_supported(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; + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ @@ -240,6 +261,13 @@ static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_i dcd_event_handler(&event, in_isr); } +TU_ATTR_ALWAYS_INLINE static inline void dcd_event_enter_test_mode(uint8_t rhport, uint8_t test_selector, bool in_isr) +{ + dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_TEST_MODE }; + event.test_mode.selector = test_selector; + dcd_event_handler(&event, in_isr); +} + #ifdef __cplusplus } #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index f0d9fba52..90fde92b5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -587,6 +587,11 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) if ( event.func_call.func ) event.func_call.func(event.func_call.param); break; + case DCD_EVENT_TEST_MODE: + TU_LOG_USBD(": Enter Test Mode with selector index = %d)\r\n", event.test_mode.selector); + if (dcd_enter_test_mode) dcd_enter_test_mode(event.rhport, event.test_mode.selector); + break; + case DCD_EVENT_SOF: default: TU_BREAKPOINT(); @@ -725,14 +730,50 @@ 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); - // Host may enable remote wake up before suspending especially HID device - _usbd_dev.remote_wakeup_en = true; - tud_control_status(rhport, p_request); + break; + + // Support for TEST_MODE + case TUSB_REQ_FEATURE_TEST_MODE: + // Only handle the test mode is supported and valid + if (!dcd_enter_test_mode || !dcd_test_mode_supported || 0 != tu_u16_low(p_request->wIndex)) + { + return false; + } + + uint8_t selector = tu_u16_high(p_request->wIndex); + + // Stall request if the selected test mode isn't supported + if (!dcd_test_mode_supported(selector)) + { + TU_LOG_USBD(" Unsupported Test Mode (test selector index: %d)\r\n", selector); + + return false; + } + + TU_LOG_USBD(" Schedule Test Mode (test selector index: %d)\r\n", selector); + + // Acknowledge request + tud_control_status(rhport, p_request); + + // Schedule the execution of the test mode so that the request can be answered + dcd_event_enter_test_mode(rhport, selector, false); + + break; + + // Stall unsupported feature selector + default: return false; + } break; case TUSB_REQ_CLEAR_FEATURE: diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index c6132a1f5..ee4b2b28d 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1351,4 +1351,34 @@ void dcd_int_handler(uint8_t rhport) // } } +#if defined(TUP_USBIP_DWC2_TEST_MODE_SUPPORT) + +bool dcd_test_mode_supported(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) { + // Disable test mode if not supported + if (!dcd_test_mode_supported(test_selector)) { + test_selector = 0; + } + + // Delay the entering a bit so there is enough time to acknowledge request + uint32_t count = SystemCoreClock / 20000; + while (count--) __NOP(); + + // 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_SUPPORT */ + #endif From c3e96e667f45e695bc855db4011f1a7f46d24b29 Mon Sep 17 00:00:00 2001 From: Rocky04 Date: Mon, 15 Jan 2024 15:10:46 +0000 Subject: [PATCH 02/48] Change to control complete cb --- src/device/dcd.h | 19 +++------------ src/device/usbd.c | 34 ++++++++++++++------------- src/portable/synopsys/dwc2/dcd_dwc2.c | 11 +++------ 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/src/device/dcd.h b/src/device/dcd.h index 7755ef107..2248cd392 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -58,7 +58,6 @@ typedef enum DCD_EVENT_SETUP_RECEIVED, DCD_EVENT_XFER_COMPLETE, - DCD_EVENT_TEST_MODE, // Not an DCD event, just a convenient way to defer ISR function USBD_EVENT_FUNC_CALL, @@ -71,7 +70,7 @@ typedef struct TU_ATTR_ALIGNED(4) uint8_t rhport; uint8_t event_id; - union + union { // BUS RESET struct { @@ -98,11 +97,6 @@ typedef struct TU_ATTR_ALIGNED(4) void (*func) (void*); void* param; }func_call; - - // TEST MODE - struct { - uint8_t selector; - }test_mode; }; } dcd_event_t; @@ -164,8 +158,8 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // Enable/Disable Start-of-frame interrupt. Default is disabled void dcd_sof_enable(uint8_t rhport, bool en); -// Check if the test mode is supported -bool dcd_test_mode_supported(test_mode_t test_selector) TU_ATTR_WEAK; +// 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; @@ -261,13 +255,6 @@ static inline void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_i dcd_event_handler(&event, in_isr); } -TU_ATTR_ALWAYS_INLINE static inline void dcd_event_enter_test_mode(uint8_t rhport, uint8_t test_selector, bool in_isr) -{ - dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_TEST_MODE }; - event.test_mode.selector = test_selector; - dcd_event_handler(&event, in_isr); -} - #ifdef __cplusplus } #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index 90fde92b5..fbdba4d2f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -285,6 +285,7 @@ tu_static osal_queue_t _usbd_q; 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); +static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); // from usbd_control.c void usbd_control_reset(void); @@ -587,11 +588,6 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) if ( event.func_call.func ) event.func_call.func(event.func_call.param); break; - case DCD_EVENT_TEST_MODE: - TU_LOG_USBD(": Enter Test Mode with selector index = %d)\r\n", event.test_mode.selector); - if (dcd_enter_test_mode) dcd_enter_test_mode(event.rhport, event.test_mode.selector); - break; - case DCD_EVENT_SOF: default: TU_BREAKPOINT(); @@ -740,35 +736,29 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; tud_control_status(rhport, p_request); - break; // Support for TEST_MODE case TUSB_REQ_FEATURE_TEST_MODE: - // Only handle the test mode is supported and valid - if (!dcd_enter_test_mode || !dcd_test_mode_supported || 0 != tu_u16_low(p_request->wIndex)) - { - return false; - } + // 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_test_mode_supported(selector)) + if (!dcd_check_test_mode_support(selector)) { TU_LOG_USBD(" Unsupported Test Mode (test selector index: %d)\r\n", selector); return false; } - TU_LOG_USBD(" Schedule Test Mode (test selector index: %d)\r\n", selector); - // Acknowledge request tud_control_status(rhport, p_request); - // Schedule the execution of the test mode so that the request can be answered - dcd_event_enter_test_mode(rhport, selector, false); + TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector); + usbd_control_set_complete_callback(process_test_mode_cb); break; // Stall unsupported feature selector @@ -1115,6 +1105,18 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } } +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, tu_u16_high(request->wIndex)); + + return true; +} + //--------------------------------------------------------------------+ // DCD Event Handler //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ee4b2b28d..aa4a8bfb2 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1353,7 +1353,7 @@ void dcd_int_handler(uint8_t rhport) #if defined(TUP_USBIP_DWC2_TEST_MODE_SUPPORT) -bool dcd_test_mode_supported(test_mode_t test_selector) { +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; @@ -1363,15 +1363,10 @@ bool dcd_test_mode_supported(test_mode_t test_selector) { } void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) { - // Disable test mode if not supported - if (!dcd_test_mode_supported(test_selector)) { + // Disable test mode if not supported as a fall back + if (!dcd_check_test_mode_support(test_selector)) { test_selector = 0; } - - // Delay the entering a bit so there is enough time to acknowledge request - uint32_t count = SystemCoreClock / 20000; - while (count--) __NOP(); - // Get port address... dwc2_regs_t* dwc2 = DWC2_REG(rhport); From 3c4184dc15fad3eccf53c247a1c8de56bd4bd517 Mon Sep 17 00:00:00 2001 From: Rocky04 Date: Mon, 15 Jan 2024 16:16:09 +0100 Subject: [PATCH 03/48] Removed whitespace --- src/device/dcd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/dcd.h b/src/device/dcd.h index 2248cd392..8a890cec3 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -70,7 +70,7 @@ typedef struct TU_ATTR_ALIGNED(4) uint8_t rhport; uint8_t event_id; - union + union { // BUS RESET struct { From 783a4f002b3c876aef6077ea57d0060b072e8ca9 Mon Sep 17 00:00:00 2001 From: Rocky04 Date: Mon, 15 Jan 2024 16:45:58 +0100 Subject: [PATCH 04/48] Test mode support only for Hi-Speed devices --- src/common/tusb_mcu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index d74d7a2c5..ef28ac8fb 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -195,7 +195,6 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32F7) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_USBIP_DWC2_TEST_MODE_SUPPORT // FS has 6, HS has 9 #define TUP_DCD_ENDPOINT_MAX 9 @@ -203,6 +202,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_SUPPORT #endif #elif TU_CHECK_MCU(OPT_MCU_STM32H7) @@ -265,13 +265,13 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32U5) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_USBIP_DWC2_TEST_MODE_SUPPORT // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \ defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) #define TUP_DCD_ENDPOINT_MAX 9 #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_USBIP_DWC2_TEST_MODE_SUPPORT #else #define TUP_DCD_ENDPOINT_MAX 6 #endif From e0ebece2c76a77457ea67d66065d08750ae77eaa Mon Sep 17 00:00:00 2001 From: Rocky04 Date: Mon, 15 Jan 2024 18:23:59 +0100 Subject: [PATCH 05/48] Missed static keyword --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 661ba95a3..83217a869 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1098,7 +1098,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } } -bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +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 From d0373f4749e320c7cb3fac9cce068b4398e60f2f Mon Sep 17 00:00:00 2001 From: Rocky04 Date: Mon, 19 Feb 2024 17:44:18 +0000 Subject: [PATCH 06/48] Opt-out for USB Test-Mode --- src/device/usbd.c | 4 ++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 83217a869..1da6f0b53 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -731,6 +731,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const tud_control_status(rhport, p_request); break; + #if !defined(TUSB_NO_TEST_MODE_SUPPORT) // Support for TEST_MODE case TUSB_REQ_FEATURE_TEST_MODE: // Only handle the test mode if supported and valid @@ -753,6 +754,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const usbd_control_set_complete_callback(process_test_mode_cb); break; + #endif /* !TUSB_NO_TEST_MODE_SUPPORT */ // Stall unsupported feature selector default: return false; @@ -1098,6 +1100,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } } +#if !defined(TUSB_NO_TEST_MODE_SUPPORT) 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 @@ -1109,6 +1112,7 @@ static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_req return true; } +#endif /* !TUSB_NO_TEST_MODE_SUPPORT */ //--------------------------------------------------------------------+ // DCD Event Handler diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 381aeca71..8163ba8e1 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1186,7 +1186,7 @@ void dcd_int_handler(uint8_t rhport) { // } } -#if defined(TUP_USBIP_DWC2_TEST_MODE_SUPPORT) +#if defined(TUP_USBIP_DWC2_TEST_MODE_SUPPORT) && !defined(TUSB_NO_TEST_MODE_SUPPORT) bool dcd_check_test_mode_support(test_mode_t test_selector) { // Check if test mode selector is unsupported @@ -1209,6 +1209,6 @@ void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) { dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (test_selector << DCTL_TCTL_Pos); } -#endif /* TUP_USBIP_DWC2_TEST_MODE_SUPPORT */ +#endif /* TUP_USBIP_DWC2_TEST_MODE_SUPPORT && !TUSB_NO_TEST_MODE_SUPPORT */ #endif From 82547372d1a83f03d137a20f71b2d60a5702a75a Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Mon, 6 May 2024 08:42:08 +0200 Subject: [PATCH 07/48] edpt_dma_start() is called during interrupt time as well, dcd_edpt_xfer() needs DI/EI at one point --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 2fe721d6b..805eb1dda 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -77,6 +77,18 @@ #endif #endif +/** disable interrupts */ +#define DISABLE_IRQ() \ + uint32_t prim = __get_PRIMASK(); \ + __disable_irq(); + +/** (re)enable interrupts */ +#define ENABLE_IRQ() \ + if (!prim) \ + { \ + __enable_irq(); \ + } + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ @@ -147,7 +159,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); } @@ -434,11 +446,15 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE)); if (control_status) { + DISABLE_IRQ(); + // Status Phase also requires EasyDMA has to be available as well !!!! edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS); // The nRF doesn't interrupt on status transmit so we queue up a success response. dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr()); + + ENABLE_IRQ(); } else if (dir == TUSB_DIR_OUT) { xfer->started = true; if (epnum == 0) { From 6f47746e5ff6e33b25e12742d62bcbf69f8a27a0 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Mon, 13 May 2024 16:41:11 +0700 Subject: [PATCH 08/48] more ci update (#2642) * Circi use small docker * caching espressif docker image * only run make job on pull request or push to master * hw test run on pull request only, rename build_cmake to build.yml * enable all ci build, cmake(clang) and make(*) only run with pull_request or push to master --- .circleci/config.yml | 2 + .github/actions/setup_toolchain/action.yml | 11 +++-- .../setup_toolchain/download/action.yml | 21 ++++++---- .../setup_toolchain/espressif/action.yml | 42 +++++++++++++++++++ .../workflows/{build_cmake.yml => build.yml} | 11 ++++- .github/workflows/build_iar.yml | 9 ---- .github/workflows/hil_test.yml | 10 ----- tools/get_deps.py | 13 +++++- 8 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 .github/actions/setup_toolchain/espressif/action.yml rename .github/workflows/{build_cmake.yml => build.yml} (90%) diff --git a/.circleci/config.yml b/.circleci/config.yml index d5d401c51..d91de8419 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,8 @@ jobs: # See: https://circleci.com/developer/images/image/cimg/base - image: cimg/base:current + resource_class: small + # Add steps to the job # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps steps: diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml index e6c79e7dd..34bcbc68b 100644 --- a/.github/actions/setup_toolchain/action.yml +++ b/.github/actions/setup_toolchain/action.yml @@ -2,11 +2,11 @@ name: Setup Toolchain inputs: toolchain: + description: 'Toolchain name' required: true - type: string toolchain_url: + description: 'Toolchain URL or version' required: false - type: string outputs: build_option: @@ -24,8 +24,10 @@ runs: - name: Pull ESP-IDF docker if: inputs.toolchain == 'esp-idf' - run: docker pull espressif/idf:${{ inputs.toolchain_url }} - shell: bash + uses: ./.github/actions/setup_toolchain/espressif + with: + toolchain: ${{ inputs.toolchain }} + toolchain_url: ${{ inputs.toolchain_url }} - name: Download Toolchain if: >- @@ -33,6 +35,7 @@ runs: inputs.toolchain != 'esp-idf' uses: ./.github/actions/setup_toolchain/download with: + toolchain: ${{ inputs.toolchain }} toolchain_url: ${{ inputs.toolchain_url }} - name: Set toolchain option diff --git a/.github/actions/setup_toolchain/download/action.yml b/.github/actions/setup_toolchain/download/action.yml index db85e9027..0b35bddb1 100644 --- a/.github/actions/setup_toolchain/download/action.yml +++ b/.github/actions/setup_toolchain/download/action.yml @@ -1,29 +1,32 @@ name: Download Toolchain inputs: - toolchain_url: + toolchain: + description: 'Toolchain name' + required: true + toolchain_url: + description: 'Toolchain URL' required: true - type: string runs: using: "composite" steps: - name: Cache Toolchain uses: actions/cache@v4 - id: cache-toolchain + id: cache-toolchain-download with: - path: ~/cache/toolchain - key: ${{ runner.os }}-${{ inputs.toolchain_url }} + path: ~/cache/${{ inputs.toolchain }} + key: ${{ runner.os }}-${{ inputs.toolchain }}-${{ inputs.toolchain_url }} - name: Install Toolchain - if: steps.cache-toolchain.outputs.cache-hit != 'true' + if: steps.cache-toolchain-download.outputs.cache-hit != 'true' run: | - mkdir -p ~/cache/toolchain + mkdir -p ~/cache/${{ inputs.toolchain }} wget --progress=dot:mega ${{ inputs.toolchain_url }} -O toolchain.tar.gz - tar -C ~/cache/toolchain -xaf toolchain.tar.gz + tar -C ~/cache/${{ inputs.toolchain }} -xaf toolchain.tar.gz shell: bash - name: Set Toolchain Path run: | - echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin` + echo >> $GITHUB_PATH `echo ~/cache/${{ inputs.toolchain }}/*/bin` shell: bash diff --git a/.github/actions/setup_toolchain/espressif/action.yml b/.github/actions/setup_toolchain/espressif/action.yml new file mode 100644 index 000000000..a4c6127c6 --- /dev/null +++ b/.github/actions/setup_toolchain/espressif/action.yml @@ -0,0 +1,42 @@ +name: Setup ESP-IDF Toolchain + +inputs: + toolchain: + description: 'Toolchain name' + required: true + toolchain_url: + description: 'Toolchain URL or version' + required: true + +runs: + using: "composite" + steps: + - id: set-docker-image + run: | + DOCKER_IMAGE=$HOME/cache/${{ inputs.toolchain }}/docker_image.tar + echo "DOCKER_IMAGE=$DOCKER_IMAGE" >> $GITHUB_ENV + echo "DOCKER_IMAGE=$DOCKER_IMAGE" >> $GITHUB_OUTPUT + shell: bash + + - name: Cache Docker Image + uses: actions/cache@v4 + id: cache-toolchain-espressif + with: + path: ${{ steps.set-docker-image.outputs.DOCKER_IMAGE }} + key: ${{ runner.os }}-${{ inputs.toolchain }}-${{ inputs.toolchain_url }} + + - name: Pull and Save Docker Image + if: steps.cache-toolchain-espressif.outputs.cache-hit != 'true' + run: | + docker pull espressif/idf:${{ inputs.toolchain_url }} + mkdir -p ~/cache/${{ inputs.toolchain }} + docker save -o $DOCKER_IMAGE espressif/idf:${{ inputs.toolchain_url }} + du -sh $DOCKER_IMAGE + shell: bash + + - name: Load Docker Image + if: steps.cache-toolchain-espressif.outputs.cache-hit == 'true' + run: | + du -sh $DOCKER_IMAGE + docker load --input $DOCKER_IMAGE + shell: bash diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build.yml similarity index 90% rename from .github/workflows/build_cmake.yml rename to .github/workflows/build.yml index 4723cf8d9..d51e1c92a 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ on: - 'tools/get_deps.py' - 'tools/build.py' - '.github/actions/**' - - '.github/workflows/build_cmake.yml' + - '.github/workflows/build.yml' - '.github/workflows/build_util.yml' - '.github/workflows/ci_set_matrix.py' pull_request: @@ -24,7 +24,7 @@ on: - 'tools/get_deps.py' - 'tools/build.py' - '.github/actions/**' - - '.github/workflows/build_cmake.yml' + - '.github/workflows/build.yml' - '.github/workflows/build_util.yml' - '.github/workflows/ci_set_matrix.py' concurrency: @@ -67,6 +67,10 @@ jobs: - 'arm-gcc' - 'msp430-gcc' - 'riscv-gcc' + if: >- + matrix.toolchain != 'arm-clang' || + github.event_name == 'pull_request' || + (github.event_name == 'push' && github.ref == 'refs/heads/master') with: build-system: 'cmake' toolchain: ${{ matrix.toolchain }} @@ -77,6 +81,9 @@ jobs: # Build Make # --------------------------------------- make: + if: >- + github.event_name == 'pull_request' || + (github.event_name == 'push' && github.ref == 'refs/heads/master') needs: set-matrix uses: ./.github/workflows/build_util.yml strategy: diff --git a/.github/workflows/build_iar.yml b/.github/workflows/build_iar.yml index 34dbda192..c8a095c18 100644 --- a/.github/workflows/build_iar.yml +++ b/.github/workflows/build_iar.yml @@ -2,15 +2,6 @@ name: Build IAR on: workflow_dispatch: - push: - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'tools/get_deps.py' - - 'test/hil/**' - - '.github/workflows/build_iar.yml' pull_request: branches: [ master ] paths: diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml index 796ff32dc..eb3f2cbab 100644 --- a/.github/workflows/hil_test.yml +++ b/.github/workflows/hil_test.yml @@ -2,16 +2,6 @@ name: Hardware Test on: workflow_dispatch: - push: - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'test/hil/**' - - 'tools/get_deps.py' - - '.github/actions/**' - - '.github/workflows/hil_test.yml' pull_request: branches: [ master ] paths: diff --git a/tools/get_deps.py b/tools/get_deps.py index 20cbe64c7..2c2f97b4b 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -242,10 +242,12 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument('families', nargs='*', default=[], help='Families to fetch') parser.add_argument('-b', '--board', action='append', default=[], help='Boards to fetch') + parser.add_argument('--print', action='store_true', help='Print commit hash only') args = parser.parse_args() families = args.families boards = args.board + print_only = args.print if len(families) == 0 and len(boards) == 0: print("Warning: family and board are not specified, only fetching mandatory dependencies.") @@ -268,8 +270,15 @@ def main(): if f in deps_optional[d][2]: deps.append(d) - with Pool() as pool: - status = sum(pool.map(get_a_dep, deps)) + if print_only: + pvalue = {} + for d in deps: + commit = deps_all[d][1] + pvalue[d] = commit + print(pvalue) + else: + with Pool() as pool: + status = sum(pool.map(get_a_dep, deps)) return status From 7cf1bdd2848d6c36e9659acaf77c83a1fa99d04f Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Mon, 13 May 2024 20:27:49 +0700 Subject: [PATCH 09/48] Ci tweak3 (#2643) - enable --one-per-family to build 1 board per family, also skip family if board specified in -b also present - minimize ci run for push event - only build one board per family - skip hil test on both pi4 and hfp - full build will be runn for PR event - IAR always build 1 board per family regardless of event - update build.py to optimize make - remove all setup python since we don't really need it --- .github/actions/setup_toolchain/action.yml | 3 + .github/workflows/build.yml | 50 +++++--- .github/workflows/build_iar.yml | 50 -------- .github/workflows/build_renesas.yml | 5 - .github/workflows/build_util.yml | 21 +++- .github/workflows/ci_set_matrix.py | 22 +++- .github/workflows/hil_test.yml | 12 +- .github/workflows/pre-commit.yml | 5 - hw/bsp/stm32f0/family.c | 2 +- hw/bsp/stm32f1/family.c | 2 +- hw/bsp/stm32f2/family.c | 3 +- hw/bsp/stm32f3/family.c | 5 +- hw/bsp/stm32u5/family.c | 3 +- hw/bsp/stm32wb/family.c | 5 +- tools/build.py | 136 ++++++++++++--------- 15 files changed, 163 insertions(+), 161 deletions(-) delete mode 100644 .github/workflows/build_iar.yml diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml index 34bcbc68b..19fe28b0c 100644 --- a/.github/actions/setup_toolchain/action.yml +++ b/.github/actions/setup_toolchain/action.yml @@ -32,6 +32,7 @@ runs: - name: Download Toolchain if: >- inputs.toolchain != 'arm-gcc' && + inputs.toolchain != 'arm-iar' && inputs.toolchain != 'esp-idf' uses: ./.github/actions/setup_toolchain/download with: @@ -44,6 +45,8 @@ runs: BUILD_OPTION="" if [[ "${{ inputs.toolchain }}" == *"clang"* ]]; then BUILD_OPTION="--toolchain clang" + elif [[ "${{ inputs.toolchain }}" == "arm-iar" ]]; then + BUILD_OPTION="--toolchain iar" fi echo "build_option=$BUILD_OPTION" echo "build_option=$BUILD_OPTION" >> $GITHUB_OUTPUT diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d51e1c92a..2cd348847 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,11 +37,6 @@ jobs: outputs: json: ${{ steps.set-matrix-json.outputs.matrix }} steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Checkout TinyUSB uses: actions/checkout@v4 @@ -63,27 +58,22 @@ jobs: matrix: toolchain: - 'aarch64-gcc' - - 'arm-clang' +# - 'arm-clang' - 'arm-gcc' - 'msp430-gcc' - 'riscv-gcc' - if: >- - matrix.toolchain != 'arm-clang' || - github.event_name == 'pull_request' || - (github.event_name == 'push' && github.ref == 'refs/heads/master') with: build-system: 'cmake' toolchain: ${{ matrix.toolchain }} toolchain_url: ${{ fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].toolchain_url }} build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].family) }} + one-per-family: ${{ github.event_name != 'pull_request' }} # --------------------------------------- # Build Make # --------------------------------------- make: - if: >- - github.event_name == 'pull_request' || - (github.event_name == 'push' && github.ref == 'refs/heads/master') + #if: github.event_name == 'pull_request' needs: set-matrix uses: ./.github/workflows/build_util.yml strategy: @@ -100,6 +90,7 @@ jobs: toolchain: ${{ matrix.toolchain }} toolchain_url: ${{ fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].toolchain_url }} build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].family) }} + one-per-family: ${{ github.event_name != 'pull_request' }} # --------------------------------------- # Build Make on Windows/MacOS @@ -114,7 +105,8 @@ jobs: os: ${{ matrix.os }} build-system: 'make' toolchain: 'arm-gcc' - build-args: '["-bstm32f411disco"]' + build-args: '["stm32h7"]' + one-per-family: true # --------------------------------------- # Build Espressif @@ -134,3 +126,33 @@ jobs: toolchain: 'esp-idf' toolchain_url: 'v5.1.1' build-args: '["-b${{ matrix.board }}"]' + + # --------------------------------------- + # Build IAR on HFP self-hosted + # --------------------------------------- + arm-iar: + if: github.repository_owner == 'hathach' + needs: set-matrix + runs-on: [self-hosted, Linux, X64, hifiphile] + env: + BUILD_ARGS: ${{ join(fromJSON(needs.set-matrix.outputs.json)['arm-iar'].family, ' ') }} + steps: + - name: Clean workspace + run: | + echo "Cleaning up previous run" + rm -rf "${{ github.workspace }}" + mkdir -p "${{ github.workspace }}" + + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Get Dependencies + run: python3 tools/get_deps.py $BUILD_ARGS + + - name: Build + run: python3 tools/build.py --one-per-family --toolchain iar $BUILD_ARGS + + - name: Test on actual hardware (hardware in the loop) + if: github.event_name == 'pull_request' + run: | + python3 test/hil/hil_test.py hfp.json diff --git a/.github/workflows/build_iar.yml b/.github/workflows/build_iar.yml deleted file mode 100644 index c8a095c18..000000000 --- a/.github/workflows/build_iar.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Build IAR - -on: - workflow_dispatch: - pull_request: - branches: [ master ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'tools/get_deps.py' - - 'test/hil/**' - - '.github/workflows/build_iar.yml' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - cmake: - if: github.repository_owner == 'hathach' - runs-on: [self-hosted, Linux, X64, hifiphile] - strategy: - fail-fast: false - matrix: - family: - # Alphabetical order - # Note: bundle multiple families into a matrix since there is only one self-hosted instance can - # run IAR build. Too many matrix can hurt due to setup/teardown overhead. - - 'lpc43 stm32f0 stm32f1 stm32f7 stm32g0 stm32g4 stm32l4' - steps: - - name: Clean workspace - run: | - echo "Cleaning up previous run" - rm -rf "${{ github.workspace }}" - mkdir -p "${{ github.workspace }}" - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Get Dependencies - run: python3 tools/get_deps.py ${{ matrix.family }} - - - name: Build - run: python3 tools/build.py --toolchain iar ${{ matrix.family }} - - - name: Test on actual hardware (hardware in the loop) - run: | - python3 test/hil/hil_test.py hfp.json diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml index 1be49344f..3d2cbab28 100644 --- a/.github/workflows/build_renesas.yml +++ b/.github/workflows/build_renesas.yml @@ -34,11 +34,6 @@ jobs: # Alphabetical order - 'rx' steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Checkout TinyUSB uses: actions/checkout@v4 diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml index f8ad1900c..49a9feabd 100644 --- a/.github/workflows/build_util.yml +++ b/.github/workflows/build_util.yml @@ -15,6 +15,10 @@ on: build-args: required: true type: string + one-per-family: + required: false + default: false + type: boolean os: required: false type: string @@ -31,11 +35,6 @@ jobs: - name: Checkout TinyUSB uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Setup Toolchain id: setup-toolchain uses: ./.github/actions/setup_toolchain @@ -48,10 +47,20 @@ jobs: with: arg: ${{ matrix.arg }} + - name: Set build one-per-family option + id: set-one-per-family + run: | + if [[ "${{ inputs.one-per-family }}" == "true" ]]; then + BUILD_OPTION="--one-per-family" + fi + echo "build_option=$BUILD_OPTION" + echo "build_option=$BUILD_OPTION" >> $GITHUB_OUTPUT + shell: bash + - name: Build if: inputs.toolchain != 'esp-idf' run: | - python tools/build.py -s ${{ inputs.build-system }} ${{ steps.setup-toolchain.outputs.build_option }} ${{ matrix.arg }} + python tools/build.py -s ${{ inputs.build-system }} ${{ steps.setup-toolchain.outputs.build_option }} ${{ steps.set-one-per-family.outputs.build_option }} ${{ matrix.arg }} - name: Build using ESP-IDF docker if: inputs.toolchain == 'esp-idf' diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index ea758d917..62239c9ad 100644 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -4,6 +4,7 @@ import json toolchain_list = { "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz", "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-17.0.1/LLVMEmbeddedToolchainForArm-17.0.1-Linux-x86_64.tar.xz", + "arm-iar": "", "arm-gcc": "", "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1/xpack-riscv-none-embed-gcc-10.1.0-1.1-linux-x64.tar.gz", @@ -28,12 +29,12 @@ family_list = { "rp2040": ["arm-gcc"], "samd11 samd21 saml2x": ["arm-gcc", "arm-clang"], "samd5x_e5x samg": ["arm-gcc", "arm-clang"], - "stm32f0 stm32f1 stm32f2 stm32f3": ["arm-gcc", "arm-clang"], - "stm32f4": ["arm-gcc", "arm-clang"], - "stm32f7": ["arm-gcc", "arm-clang"], - "stm32g0 stm32g4 stm32h5": ["arm-gcc", "arm-clang"], - "stm32h7": ["arm-gcc", "arm-clang"], - "stm32l4 stm32u5 stm32wb": ["arm-gcc", "arm-clang"], + "stm32f0 stm32f1 stm32f2 stm32f3": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32f4": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32f7": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32g0 stm32g4 stm32h5": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32h7": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32l4 stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"], "xmc4000": ["arm-gcc"], } @@ -43,7 +44,16 @@ def set_matrix_json(): for toolchain in toolchain_list.keys(): filtered_families = [family for family, supported_toolchain in family_list.items() if toolchain in supported_toolchain] + + # always add board in hfp.json for arm-iar + if toolchain == 'arm-iar': + with open('test/hil/hfp.json') as f: + hfp_data = json.load(f) + hfp_boards = [f"-b{board['name']}" for board in hfp_data['boards']] + filtered_families = filtered_families + hfp_boards + matrix[toolchain] = {"family": filtered_families, "toolchain_url": toolchain_list[toolchain]} + print(json.dumps(matrix)) diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml index eb3f2cbab..adb5bf00e 100644 --- a/.github/workflows/hil_test.yml +++ b/.github/workflows/hil_test.yml @@ -30,11 +30,6 @@ jobs: - name: Checkout TinyUSB uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Parse HIL json id: parse_hil_json run: | @@ -78,11 +73,6 @@ jobs: - name: Checkout TinyUSB uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Parse HIL json id: parse_hil_json run: | @@ -131,7 +121,7 @@ jobs: - build-esp runs-on: [self-hosted, rp2040, nrf52840, esp32s3, hardware-in-the-loop] env: - BOARDS_LIST: "${{ needs.build.outputs.BOARDS_LIST }} ${{ needs.build-esp.outputs.BOARDS_LIST }}" + BOARDS_LIST: "${{ needs.build.outputs.BOARDS_LIST }} ${{ needs.build-esp.outputs.BOARDS_LIST }}" steps: - name: Clean workspace run: | diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index d1ffe6ca1..379a22ee2 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -14,11 +14,6 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - name: Setup Ruby uses: ruby/setup-ruby@v1 with: diff --git a/hw/bsp/stm32f0/family.c b/hw/bsp/stm32f0/family.c index 7ef126ae6..3079a1ed3 100644 --- a/hw/bsp/stm32f0/family.c +++ b/hw/bsp/stm32f0/family.c @@ -115,7 +115,7 @@ void board_init(void) { //--------------------------------------------------------------------+ void board_led_write(bool state) { - GPIO_PinState pin_state = (GPIO_PinState)(state ? LED_STATE_ON : (1 - LED_STATE_ON)); + GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON)); HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); } diff --git a/hw/bsp/stm32f1/family.c b/hw/bsp/stm32f1/family.c index 0c1b362ab..70f81e7fc 100644 --- a/hw/bsp/stm32f1/family.c +++ b/hw/bsp/stm32f1/family.c @@ -124,7 +124,7 @@ void board_init(void) { //--------------------------------------------------------------------+ void board_led_write(bool state) { - GPIO_PinState pin_state = (GPIO_PinState)(state ? LED_STATE_ON : (1 - LED_STATE_ON)); + GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON)); HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); } diff --git a/hw/bsp/stm32f2/family.c b/hw/bsp/stm32f2/family.c index 8b1c56423..62cca327b 100644 --- a/hw/bsp/stm32f2/family.c +++ b/hw/bsp/stm32f2/family.c @@ -108,7 +108,8 @@ void board_init(void) { //--------------------------------------------------------------------+ void board_led_write(bool state) { - HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); + GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON)); + HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); } uint32_t board_button_read(void) { diff --git a/hw/bsp/stm32f3/family.c b/hw/bsp/stm32f3/family.c index 7c194a694..e7488ba84 100644 --- a/hw/bsp/stm32f3/family.c +++ b/hw/bsp/stm32f3/family.c @@ -108,7 +108,8 @@ void board_init(void) { //--------------------------------------------------------------------+ void board_led_write(bool state) { - HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); + GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON)); + HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); } uint32_t board_button_read(void) { @@ -142,7 +143,7 @@ uint32_t board_millis(void) { #endif void HardFault_Handler(void) { - asm("bkpt"); + asm("bkpt 0"); } // Required by __libc_init_array in startup code if we are compiling using diff --git a/hw/bsp/stm32u5/family.c b/hw/bsp/stm32u5/family.c index ec64f7622..d779b5c96 100644 --- a/hw/bsp/stm32u5/family.c +++ b/hw/bsp/stm32u5/family.c @@ -203,7 +203,8 @@ void board_init(void) { //--------------------------------------------------------------------+ void board_led_write(bool state) { - HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); + GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON)); + HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); } uint32_t board_button_read(void) { diff --git a/hw/bsp/stm32wb/family.c b/hw/bsp/stm32wb/family.c index 1dc789407..6051388a7 100644 --- a/hw/bsp/stm32wb/family.c +++ b/hw/bsp/stm32wb/family.c @@ -136,7 +136,8 @@ void board_init(void) { //--------------------------------------------------------------------+ void board_led_write(bool state) { - HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); + GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON)); + HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); } uint32_t board_button_read(void) { @@ -174,7 +175,7 @@ uint32_t board_millis(void) { #endif void HardFault_Handler(void) { - asm("bkpt"); + asm("bkpt 1"); } // Required by __libc_init_array in startup code if we are compiling using diff --git a/tools/build.py b/tools/build.py index 967f7c95e..b937a7342 100644 --- a/tools/build.py +++ b/tools/build.py @@ -1,4 +1,5 @@ import argparse +import random import os import sys import time @@ -96,32 +97,61 @@ def build_board_cmake(board, toolchain): return ret -def build_family(family, toolchain, build_system): +def build_board_make_all_examples(board, toolchain, all_examples): + start_time = time.monotonic() + ret = [0, 0, 0] + + with Pool(processes=os.cpu_count()) as pool: + pool_args = list((map(lambda e, b=board, o=f"TOOLCHAIN={toolchain}": [e, b, o], all_examples))) + r = pool.starmap(build_utils.build_example, pool_args) + # sum all element of same index (column sum) + rsum = list(map(sum, list(zip(*r)))) + ret[0] += rsum[0] + ret[1] += rsum[1] + ret[2] += rsum[2] + duration = time.monotonic() - start_time + if ret[1] == 0: + status = SUCCEEDED + else: + status = FAILED + + flash_size = "-" + sram_size = "-" + example = 'all' + title = build_utils.build_format.format(example, board, status, "{:.2f}s".format(duration), flash_size, sram_size) + print(title) + return ret + + +def build_family(family, toolchain, build_system, one_per_family, boards): all_boards = [] for entry in os.scandir(f"hw/bsp/{family}/boards"): if entry.is_dir() and entry.name != 'pico_sdk': all_boards.append(entry.name) all_boards.sort() - # success, failed, skipped ret = [0, 0, 0] - if build_system == 'cmake': - for board in all_boards: - if build_board_cmake(board, toolchain): - ret[0] += 1 - else: - ret[1] += 1 - elif build_system == 'make': - all_examples = get_examples(family) - for example in all_examples: - with Pool(processes=os.cpu_count()) as pool: - pool_args = list((map(lambda b, e=example, o=f"TOOLCHAIN={toolchain}": [e, b, o], all_boards))) - r = pool.starmap(build_utils.build_example, pool_args) - # sum all element of same index (column sum) - rsum = list(map(sum, list(zip(*r)))) - ret[0] += rsum[0] - ret[1] += rsum[1] - ret[2] += rsum[2] + + # If only-one flag is set, select one random board + if one_per_family: + for b in boards: + # skip if -b already specify one in this family + if find_family(b) == family: + return ret + all_boards = [random.choice(all_boards)] + + # success, failed, skipped + all_examples = get_examples(family) + for board in all_boards: + r = [0, 0, 0] + if build_system == 'cmake': + r = build_board_cmake(board, toolchain) + elif build_system == 'make': + r = build_board_make_all_examples(board, toolchain, all_examples) + ret[0] += r[0] + ret[1] += r[1] + ret[2] += r[2] + return ret @@ -131,12 +161,14 @@ def main(): parser.add_argument('-b', '--board', action='append', default=[], help='Boards to build') parser.add_argument('-t', '--toolchain', default='gcc', help='Toolchain to use, default is gcc') parser.add_argument('-s', '--build-system', default='cmake', help='Build system to use, default is cmake') + parser.add_argument('-1', '--one-per-family', action='store_true', default=False, help='Build only one random board inside a family') args = parser.parse_args() families = args.families boards = args.board toolchain = args.toolchain build_system = args.build_system + one_per_family = args.one_per_family if len(families) == 0 and len(boards) == 0: print("Please specify families or board to build") @@ -145,50 +177,42 @@ def main(): print(build_separator) print(build_utils.build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) total_time = time.monotonic() - total_result = [0, 0, 0] + result = [0, 0, 0] - # build families: cmake, make - if families is not None: - all_families = [] - if 'all' in families: - for entry in os.scandir("hw/bsp"): - if entry.is_dir() and entry.name != 'espressif' and os.path.isfile(entry.path + "/family.cmake"): - all_families.append(entry.name) - else: - all_families = list(families) - all_families.sort() + # build families + all_families = [] + if 'all' in families: + for entry in os.scandir("hw/bsp"): + if entry.is_dir() and entry.name != 'espressif' and os.path.isfile(entry.path + "/family.cmake"): + all_families.append(entry.name) + else: + all_families = list(families) + all_families.sort() - # succeeded, failed - for f in all_families: - fret = build_family(f, toolchain, build_system) - total_result[0] += fret[0] - total_result[1] += fret[1] - total_result[2] += fret[2] + # succeeded, failed + for f in all_families: + fret = build_family(f, toolchain, build_system, one_per_family, boards) + result[0] += fret[0] + result[1] += fret[1] + result[2] += fret[2] - # build board (only cmake) - if boards is not None: - for b in boards: - if build_system == 'cmake': - r = build_board_cmake(b, toolchain) - total_result[0] += r[0] - total_result[1] += r[1] - total_result[2] += r[2] - elif build_system == 'make': - all_examples = get_examples(find_family(b)) - with Pool(processes=os.cpu_count()) as pool: - pool_args = list((map(lambda e, bb=b, o=f"TOOLCHAIN={toolchain}": [e, bb, o], all_examples))) - r = pool.starmap(build_utils.build_example, pool_args) - # sum all element of same index (column sum) - rsum = list(map(sum, list(zip(*r)))) - total_result[0] += rsum[0] - total_result[1] += rsum[1] - total_result[2] += rsum[2] + # build boards + for b in boards: + r = [0, 0, 0] + if build_system == 'cmake': + r = build_board_cmake(b, toolchain) + elif build_system == 'make': + all_examples = get_examples(find_family(b)) + r = build_board_make_all_examples(b, toolchain, all_examples) + result[0] += r[0] + result[1] += r[1] + result[2] += r[2] total_time = time.monotonic() - total_time print(build_separator) - print(f"Build Summary: {total_result[0]} {SUCCEEDED}, {total_result[1]} {FAILED} and took {total_time:.2f}s") + print(f"Build Summary: {result[0]} {SUCCEEDED}, {result[1]} {FAILED} and took {total_time:.2f}s") print(build_separator) - return total_result[1] + return result[1] if __name__ == '__main__': From 9d561410e58ba9efb6ef2bff7b03a2f47dee8d64 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Mon, 13 May 2024 18:57:03 +0200 Subject: [PATCH 10/48] revert (unverified) second race condition --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 805eb1dda..bb07063d2 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -77,18 +77,6 @@ #endif #endif -/** disable interrupts */ -#define DISABLE_IRQ() \ - uint32_t prim = __get_PRIMASK(); \ - __disable_irq(); - -/** (re)enable interrupts */ -#define ENABLE_IRQ() \ - if (!prim) \ - { \ - __enable_irq(); \ - } - /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ @@ -446,15 +434,11 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE)); if (control_status) { - DISABLE_IRQ(); - // Status Phase also requires EasyDMA has to be available as well !!!! edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS); // The nRF doesn't interrupt on status transmit so we queue up a success response. dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr()); - - ENABLE_IRQ(); } else if (dir == TUSB_DIR_OUT) { xfer->started = true; if (epnum == 0) { From e250b82377aa9c1433c6235501c72dd079544c75 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 13 May 2024 22:26:19 +0200 Subject: [PATCH 11/48] Adjust logic. --- src/common/tusb_mcu.h | 5 +++-- src/device/dcd.h | 6 +++--- src/device/usbd.c | 20 +++++++++++--------- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 ++-- src/tusb_option.h | 5 +++++ 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index e489e93e7..3a7d6ad33 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,7 +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_SUPPORT + #define TUP_USBIP_DWC2_TEST_MODE #endif #elif TU_CHECK_MCU(OPT_MCU_STM32H7) @@ -278,7 +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_SUPPORT + #define TUP_USBIP_DWC2_TEST_MODE #else #define TUP_DCD_ENDPOINT_MAX 6 #endif diff --git a/src/device/dcd.h b/src/device/dcd.h index b71b99869..9447d6d9d 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -97,8 +97,7 @@ typedef struct TU_ATTR_ALIGNED(4) { }; } dcd_event_t; -typedef enum _test_mode_selector -{ +typedef enum { TEST_J = 1, TEST_K, TEST_SE0_NAK, @@ -158,12 +157,13 @@ void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; // 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 //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 7dfdc8476..25d890dc7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -313,8 +313,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); @@ -766,16 +767,16 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const tud_control_status(rhport, p_request); break; - #if !defined(TUSB_NO_TEST_MODE_SUPPORT) +#if CFG_TUD_TEST_MODE // Support for TEST_MODE - case TUSB_REQ_FEATURE_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(selector)) + if (!dcd_check_test_mode_support((test_mode_t)selector)) { TU_LOG_USBD(" Unsupported Test Mode (test selector index: %d)\r\n", selector); @@ -788,8 +789,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector); usbd_control_set_complete_callback(process_test_mode_cb); - break; - #endif /* !TUSB_NO_TEST_MODE_SUPPORT */ + break; + } +#endif /* CFG_TUD_TEST_MODE */ // Stall unsupported feature selector default: return false; @@ -1121,7 +1123,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } } -#if !defined(TUSB_NO_TEST_MODE_SUPPORT) +#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 @@ -1129,11 +1131,11 @@ static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_req // Only enter the test mode after the request for it has completed TU_VERIFY(CONTROL_STAGE_ACK == stage); - dcd_enter_test_mode(rhport, tu_u16_high(request->wIndex)); + dcd_enter_test_mode(rhport, (test_mode_t)tu_u16_high(request->wIndex)); return true; } -#endif /* !TUSB_NO_TEST_MODE_SUPPORT */ +#endif /* CFG_TUD_TEST_MODE */ //--------------------------------------------------------------------+ // DCD Event Handler diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index c9580655f..fd2f08453 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1195,7 +1195,7 @@ void dcd_int_handler(uint8_t rhport) { // } } -#if defined(TUP_USBIP_DWC2_TEST_MODE_SUPPORT) && !defined(TUSB_NO_TEST_MODE_SUPPORT) +#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 @@ -1218,6 +1218,6 @@ void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) { dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (test_selector << DCTL_TCTL_Pos); } -#endif /* TUP_USBIP_DWC2_TEST_MODE_SUPPORT && !TUSB_NO_TEST_MODE_SUPPORT */ +#endif /* TUP_USBIP_DWC2_TEST_MODE && CFG_TUD_TEST_MODE */ #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 8d5527936..058427e0e 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -364,6 +364,11 @@ #define CFG_TUD_INTERFACE_MAX 16 #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 From ad734e658cc9e39021a93fc21e077f1b1709c0ff Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 13 May 2024 22:27:33 +0200 Subject: [PATCH 12/48] Remove dead code. --- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index fd2f08453..dbcd586c5 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1207,10 +1207,6 @@ bool dcd_check_test_mode_support(test_mode_t test_selector) { } void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) { - // Disable test mode if not supported as a fall back - if (!dcd_check_test_mode_support(test_selector)) { - test_selector = 0; - } // Get port address... dwc2_regs_t* dwc2 = DWC2_REG(rhport); From 3c24ba3ff2eb5fdb4e214f668a25ed2038a847ad Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Tue, 14 May 2024 12:44:36 +0700 Subject: [PATCH 13/48] build arm-clang on circleci with pull request (#2644) * Build arm-clang using circle ci (only on PR): cache most of mandatory deps, clang toolchain * update get_deps.py to include CMSIS_5 with --print + no arguments, prevent duplicated deps --- .circleci/config.yml | 125 ++++++++++++++++++++++------ .github/actions/get_deps/action.yml | 2 +- .github/workflows/build.yml | 4 +- tools/get_deps.py | 8 +- 4 files changed, 106 insertions(+), 33 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d91de8419..77ab30f00 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,33 +1,106 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/configuration-reference version: 2.1 -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs -jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job - docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:current - - resource_class: small - - # Add steps to the job - # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps +commands: + setup-toolchain: + parameters: + toolchain: + type: string + toolchain_url: + type: string steps: - # Checkout the code as the first step. - - checkout - run: - name: "Say hello" - command: "echo Hello, World!" + name: Make toolchain cache key + command: echo "<< parameters.toolchain >>-<< parameters.toolchain_url>>" > toolchain_key + - restore_cache: + name: Restore Toolchain Cache + key: deps-{{ checksum "toolchain_key" }} + paths: + - ~/cache/<< parameters.toolchain >> + - run: + name: Install Toolchain + command: | + # Only download if folder does not exist (not cached) + if [ ! -d ~/cache/<< parameters.toolchain >> ]; then + mkdir -p ~/cache/<< parameters.toolchain >> + wget << parameters.toolchain_url>> -O toolchain.tar.gz + tar -C ~/cache/<< parameters.toolchain >> -xaf toolchain.tar.gz + fi + - save_cache: + name: Save Toolchain Cache + key: deps-{{ checksum "toolchain_key" }} + paths: + - ~/cache/<< parameters.toolchain >> + - run: + name: Setup build environment + command: | + echo "export PATH=$PATH:`echo ~/cache/<< parameters.toolchain >>/*/bin`" >> $BASH_ENV + # Install Ninja + NINJA_URL=https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-linux.zip + wget $NINJA_URL -O ninja-linux.zip + unzip ninja-linux.zip -d ~/bin + + get-deps: + parameters: + family: + type: string + steps: + - run: + name: Make deps cache key + command: | + python tools/get_deps.py --print > deps_key + - restore_cache: + name: Restore Dependencies Cache + key: deps-{{ checksum "deps_key" }} + paths: + - lib/CMSIS_5 + - lib/FreeRTOS-Kernel + - lib/lwip + - tools/uf2 + - run: + name: Get Dependencies + command: | + python tools/get_deps.py << parameters.family >> + - save_cache: + name: Save Dependencies Cache + key: deps-{{ checksum "deps_key" }} + paths: + - lib/CMSIS_5 + - lib/FreeRTOS-Kernel + - lib/lwip + - tools/uf2 + +jobs: + arm-clang: + parameters: + family: + type: string + build-system: + type: string + + docker: + - image: cimg/base:current + resource_class: medium + environment: + TOOLCHAIN_URL: https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-17.0.1/LLVMEmbeddedToolchainForArm-17.0.1-Linux-x86_64.tar.xz + steps: + - checkout + - setup-toolchain: + toolchain: clang + toolchain_url: $TOOLCHAIN_URL + - get-deps: + family: << parameters.family >> + - run: + name: Build + command: python tools/build.py -s << parameters.build-system >> --toolchain clang << parameters.family >> -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. + build: jobs: - - say-hello + - arm-clang: + matrix: + parameters: + build-system: + - cmake + #family: ['stm32f1'] + #family: ['stm32f1', 'stm32f2'] + family: ['imxrt', 'kinetis_k kinetis_kl kinetis_k32l2', 'lpc11 lpc13 lpc15', 'lpc17 lpc18 lpc40 lpc43', 'lpc51 lpc54 lpc55', 'nrf', 'samd11 samd21 saml2x', 'samd5x_e5x samg', 'stm32f0 stm32f1 stm32f2 stm32f3', 'stm32f4', 'stm32f7', 'stm32g0 stm32g4 stm32h5', 'stm32h7', 'stm32l4 stm32u5 stm32wb'] diff --git a/.github/actions/get_deps/action.yml b/.github/actions/get_deps/action.yml index 38b44a70e..eea241c6c 100644 --- a/.github/actions/get_deps/action.yml +++ b/.github/actions/get_deps/action.yml @@ -2,8 +2,8 @@ name: Get dependencies inputs: arg: + description: 'Arguments to get_deps.py' required: true - type: string runs: using: "composite" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2cd348847..78d95fbbc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,7 +58,7 @@ jobs: matrix: toolchain: - 'aarch64-gcc' -# - 'arm-clang' + # - 'arm-clang' # clang is built by circle-ci - 'arm-gcc' - 'msp430-gcc' - 'riscv-gcc' @@ -81,7 +81,7 @@ jobs: matrix: toolchain: - 'aarch64-gcc' - #- 'arm-clang' + # - 'arm-clang' # clang is built by circle-ci - 'arm-gcc' - 'msp430-gcc' - 'riscv-gcc' diff --git a/tools/get_deps.py b/tools/get_deps.py index 2c2f97b4b..87c1c5ccd 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -249,9 +249,6 @@ def main(): boards = args.board print_only = args.print - if len(families) == 0 and len(boards) == 0: - print("Warning: family and board are not specified, only fetching mandatory dependencies.") - status = 0 deps = list(deps_mandatory.keys()) @@ -267,11 +264,14 @@ def main(): for f in families: for d in deps_optional: - if f in deps_optional[d][2]: + if d not in deps and f in deps_optional[d][2]: deps.append(d) if print_only: pvalue = {} + # print only without arguments, always add CMSIS_5 + if len(families) == 0 and len(boards) == 0: + deps.append('lib/CMSIS_5') for d in deps: commit = deps_all[d][1] pvalue[d] = commit From aa2685536ba9e2fbbe3f350a5bb3c6709e586722 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 May 2024 16:00:15 +0700 Subject: [PATCH 14/48] implement max3421e hcd_edpt_abort_xfer() --- hw/bsp/nrf/family.cmake | 10 +++ src/portable/analog/max3421/hcd_max3421.c | 88 ++++++++++++----------- 2 files changed, 58 insertions(+), 40 deletions(-) diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 5de69a8a3..9e86374dc 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -101,6 +101,15 @@ endfunction() #------------------------------------ # Functions #------------------------------------ + +#function(family_flash_adafruit_nrfutil TARGET) +# add_custom_target(${TARGET}-adafruit-nrfutil +# DEPENDS ${TARGET} +# COMMAND adafruit-nrfutil --verbose dfu serial --package $^ -p /dev/ttyACM0 -b 115200 --singlebank --touch 1200 +# ) +#endfunction() + + function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) @@ -133,4 +142,5 @@ function(family_configure_example TARGET RTOS) # Flashing family_flash_jlink(${TARGET}) +# family_flash_adafruit_nrfutil(${TARGET}) endfunction() 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,6 +834,37 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) { xfer_result_t xfer_result; switch(hresult) { + case HRSL_NAK: + if (ep->state == EP_STATE_ABORTING) { + ep->state = EP_STATE_IDLE; + } else { + 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); + } + return; + + case HRSL_BAD_REQ: + // occurred when initialized without any pending transfer. Skip for now + return; + case HRSL_SUCCESS: xfer_result = XFER_RESULT_SUCCESS; break; @@ -837,33 +873,6 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) { xfer_result = XFER_RESULT_STALLED; break; - case HRSL_NAK: - if (ep_num == 0) { - // control endpoint -> retry immediately - hxfr_write(rhport, _hcd_data.hxfr, in_isr); - } else { - if (ep->state < EP_STATE_ATTEMPT_MAX) { - ep->state++; - } - - max3421_ep_t * next_ep = find_next_pending_ep(ep); - if (ep == next_ep) { - // this endpoint is only one pending -> retry immediately - hxfr_write(rhport, _hcd_data.hxfr, in_isr); - } else if (next_ep) { - // switch to next pending endpoint TODO could have issue with double buffered if not clear previously out data - xact_generic(rhport, next_ep, true, in_isr); - } else { - // no more pending in this frame -> clear busy - atomic_flag_clear(&_hcd_data.busy); - } - } - return; - - case HRSL_BAD_REQ: - // occurred when initialized without any pending transfer. Skip for now - return; - default: TU_LOG3("HRSL: %02X\r\n", hrsl); xfer_result = XFER_RESULT_FAILED; @@ -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); } } From 83499a2cd0f38807619c92d9a4060d20379556b9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 May 2024 16:03:31 +0700 Subject: [PATCH 15/48] tweak action --- .github/actions/setup_toolchain/espressif/action.yml | 2 +- .github/workflows/codeql.yml | 6 +++--- .github/workflows/hil_test.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/setup_toolchain/espressif/action.yml b/.github/actions/setup_toolchain/espressif/action.yml index a4c6127c6..494b7910e 100644 --- a/.github/actions/setup_toolchain/espressif/action.yml +++ b/.github/actions/setup_toolchain/espressif/action.yml @@ -23,7 +23,7 @@ runs: id: cache-toolchain-espressif with: path: ${{ steps.set-docker-image.outputs.DOCKER_IMAGE }} - key: ${{ runner.os }}-${{ inputs.toolchain }}-${{ inputs.toolchain_url }} + key: ${{ inputs.toolchain }}-${{ inputs.toolchain_url }} - name: Pull and Save Docker Image if: steps.cache-toolchain-espressif.outputs.cache-hit != 'true' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1f7b60b9c..be4c2dd87 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -59,10 +59,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Install ARM GCC - uses: carlosperate/arm-none-eabi-gcc-action@v1 + - name: Setup Toolchain + uses: ./.github/actions/setup_toolchain with: - release: '11.2-2022.02' + toolchain: 'arm-gcc' # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml index adb5bf00e..39a9060a2 100644 --- a/.github/workflows/hil_test.yml +++ b/.github/workflows/hil_test.yml @@ -41,7 +41,7 @@ jobs: echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_ENV echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_OUTPUT - - name: Setup ARM Toolchain + - name: Setup Toolchain uses: ./.github/actions/setup_toolchain with: toolchain: 'arm-gcc' From 50278211f4117079ce5eda396f68d802d9cda615 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 May 2024 16:20:01 +0700 Subject: [PATCH 16/48] circleci light build for merged commit to master --- .circleci/config.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 77ab30f00..2d4532aee 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -91,7 +91,13 @@ jobs: family: << parameters.family >> - run: name: Build - command: python tools/build.py -s << parameters.build-system >> --toolchain clang << parameters.family >> + command: | + # Only build one board per family for non PRs i.e commit to master + ONE_PER_FAMILY="" + if [ -z "$CIRCLE_PULL_REQUEST" ]; then + ONE_PER_FAMILY="--one-per-family" + fi + python tools/build.py $ONE_PER_FAMILY -s << parameters.build-system >> --toolchain clang << parameters.family >> workflows: build: From db60fa1c63ae58c205e43e144253dab6815bb2d1 Mon Sep 17 00:00:00 2001 From: Matthew Tran Date: Sun, 19 Nov 2023 18:26:40 -0800 Subject: [PATCH 17/48] add CH32V20x USB OTG/FS driver --- .gitignore | 1 + README.rst | 2 +- docs/reference/dependencies.rst | 1 + docs/reference/supported.rst | 6 +- examples/device/cdc_msc_freertos/skip.txt | 1 + .../device/hid_composite_freertos/skip.txt | 1 + examples/device/msc_dual_lun/skip.txt | 1 + examples/device/video_capture/skip.txt | 1 + hw/bsp/ch32v20x/boards/nanoch32v203/board.h | 17 + hw/bsp/ch32v20x/boards/nanoch32v203/board.mk | 5 + hw/bsp/ch32v20x/ch32v20x_conf.h | 36 + hw/bsp/ch32v20x/ch32v20x_it.h | 15 + hw/bsp/ch32v20x/core_riscv.h | 572 ++++++++++ hw/bsp/ch32v20x/family.c | 82 ++ hw/bsp/ch32v20x/family.mk | 50 + hw/bsp/ch32v20x/system_ch32v20x.c | 976 ++++++++++++++++++ hw/bsp/ch32v20x/system_ch32v20x.h | 29 + hw/bsp/ch32v20x/wch-riscv.cfg | 18 + hw/bsp/ch32v307/family.mk | 5 + hw/bsp/fomu/family.mk | 4 + hw/bsp/gd32vf103/family.mk | 5 + src/class/video/video_device.c | 2 +- src/common/tusb_mcu.h | 4 + src/portable/wch/ch32_usbfs_reg.h | 77 ++ src/portable/wch/dcd_ch32_usbfs.c | 304 ++++++ src/tusb_option.h | 1 + tools/get_deps.py | 3 + tools/iar_template.ipcf | 1 + 28 files changed, 2215 insertions(+), 5 deletions(-) create mode 100644 hw/bsp/ch32v20x/boards/nanoch32v203/board.h create mode 100644 hw/bsp/ch32v20x/boards/nanoch32v203/board.mk create mode 100644 hw/bsp/ch32v20x/ch32v20x_conf.h create mode 100644 hw/bsp/ch32v20x/ch32v20x_it.h create mode 100644 hw/bsp/ch32v20x/core_riscv.h create mode 100644 hw/bsp/ch32v20x/family.c create mode 100644 hw/bsp/ch32v20x/family.mk create mode 100644 hw/bsp/ch32v20x/system_ch32v20x.c create mode 100644 hw/bsp/ch32v20x/system_ch32v20x.h create mode 100644 hw/bsp/ch32v20x/wch-riscv.cfg create mode 100644 src/portable/wch/ch32_usbfs_reg.h create mode 100644 src/portable/wch/dcd_ch32_usbfs.c diff --git a/.gitignore b/.gitignore index 56ae7600f..7a37d65dc 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,7 @@ hw/mcu/st/stm32l5xx_hal_driver hw/mcu/st/stm32u5xx_hal_driver hw/mcu/st/stm32wbxx_hal_driver hw/mcu/ti +hw/mcu/wch/ch32v20x hw/mcu/wch/ch32v307 hw/mcu/wch/ch32f20x lib/CMSIS_5 diff --git a/README.rst b/README.rst index 8c3145d33..dbe75adc8 100644 --- a/README.rst +++ b/README.rst @@ -157,7 +157,7 @@ Following CPUs are supported, check out `Supported Devices`_ for comprehensive l +--------------+------------------------------------------------------------+ | ValentyUSB | eptri | +--------------+------------------------------------------------------------+ -| WCH | CH32F20x, CH32V307, | +| WCH | CH32F20x, CH32V20x, CH32V307 | +--------------+------------------------------------------------------------+ License diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index 6ba6692e9..3a98594ff 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -55,6 +55,7 @@ hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/ hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git 2c5f06638be516c1b772f768456ba637f077bac8 stm32wb hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c123 hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.git 77c4095087e5ed2c548ec9058e655d0b8757663b ch32f20x +hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git de6d68c654340d7f27b00cebbfc9aa2740a1abc2 ch32v20x hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 17761f5cf9dbbf2dcf665b7c04934188add20082 ch32v307 lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 20285262657d1b482d132d20d755c8c330d55c1f imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2xstm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git 4ff01a7a4a51f53b44496aefee1e3c0071b7b173 all diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst index 7e7be25a4..3ca203e88 100644 --- a/docs/reference/supported.rst +++ b/docs/reference/supported.rst @@ -128,9 +128,9 @@ Supported MCUs +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ | ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ -| WCH | CH32V307 | ✔ | | ✔ | ch32v307 | | -| +-----------------------+--------+------+-----------+-------------------+--------------+ -| | CH32F20x | ✔ | | ✔ | ch32f205 | | +| WCH | CH32F20x | ✔ | | ✔ | ch32f205 | | +| | CH32V20x | ✔ | | ✖ | ch32v20x | | +| | CH32V307 | ✔ | | ✔ | ch32v307 | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index eb434c23b..457ddb760 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:CH32V307 mcu:CXD56 mcu:F1C100S diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt index a6f96b288..6aaa27661 100644 --- a/examples/device/hid_composite_freertos/skip.txt +++ b/examples/device/hid_composite_freertos/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:CH32V307 mcu:CXD56 mcu:F1C100S diff --git a/examples/device/msc_dual_lun/skip.txt b/examples/device/msc_dual_lun/skip.txt index a9e3a99b1..4d607dc05 100644 --- a/examples/device/msc_dual_lun/skip.txt +++ b/examples/device/msc_dual_lun/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:SAMD11 mcu:MKL25ZXX family:espressif diff --git a/examples/device/video_capture/skip.txt b/examples/device/video_capture/skip.txt index 5898664a2..714cabeec 100644 --- a/examples/device/video_capture/skip.txt +++ b/examples/device/video_capture/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.h b/hw/bsp/ch32v20x/boards/nanoch32v203/board.h new file mode 100644 index 000000000..c8d28d90f --- /dev/null +++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.h @@ -0,0 +1,17 @@ +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LED_PORT GPIOA +#define LED_PIN GPIO_Pin_15 +#define LED_STATE_ON 0 +#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk b/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk new file mode 100644 index 000000000..75dc05457 --- /dev/null +++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk @@ -0,0 +1,5 @@ +CFLAGS += \ + -DCH32V20x_D6 + +SRC_S += \ + $(CH32V20X_SDK_SRC)/Startup/startup_ch32v20x_D6.S diff --git a/hw/bsp/ch32v20x/ch32v20x_conf.h b/hw/bsp/ch32v20x/ch32v20x_conf.h new file mode 100644 index 000000000..949297fe6 --- /dev/null +++ b/hw/bsp/ch32v20x/ch32v20x_conf.h @@ -0,0 +1,36 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : ch32v20x_conf.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/06/06 + * Description : Library configuration file. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#ifndef __CH32V20x_CONF_H +#define __CH32V20x_CONF_H + +#include "ch32v20x_adc.h" +#include "ch32v20x_bkp.h" +#include "ch32v20x_can.h" +#include "ch32v20x_crc.h" +#include "ch32v20x_dbgmcu.h" +#include "ch32v20x_dma.h" +#include "ch32v20x_exti.h" +#include "ch32v20x_flash.h" +#include "ch32v20x_gpio.h" +#include "ch32v20x_i2c.h" +#include "ch32v20x_iwdg.h" +#include "ch32v20x_pwr.h" +#include "ch32v20x_rcc.h" +#include "ch32v20x_rtc.h" +#include "ch32v20x_spi.h" +#include "ch32v20x_tim.h" +#include "ch32v20x_usart.h" +#include "ch32v20x_wwdg.h" +#include "ch32v20x_it.h" +#include "ch32v20x_misc.h" + +#endif /* __CH32V20x_CONF_H */ diff --git a/hw/bsp/ch32v20x/ch32v20x_it.h b/hw/bsp/ch32v20x/ch32v20x_it.h new file mode 100644 index 000000000..e49c61ae2 --- /dev/null +++ b/hw/bsp/ch32v20x/ch32v20x_it.h @@ -0,0 +1,15 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : ch32v20x_it.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/06/06 + * Description : This file contains the headers of the interrupt handlers. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#ifndef __CH32V20x_IT_H +#define __CH32V20x_IT_H + +#endif /* __CH32V20x_IT_H */ diff --git a/hw/bsp/ch32v20x/core_riscv.h b/hw/bsp/ch32v20x/core_riscv.h new file mode 100644 index 000000000..be1b52a6c --- /dev/null +++ b/hw/bsp/ch32v20x/core_riscv.h @@ -0,0 +1,572 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : core_riscv.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/06/06 + * Description : RISC-V Core Peripheral Access Layer Header File for CH32V20x +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#ifndef __CORE_RISCV_H__ +#define __CORE_RISCV_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* IO definitions */ +#ifdef __cplusplus + #define __I volatile /* defines 'read only' permissions */ +#else + #define __I volatile const /* defines 'read only' permissions */ +#endif +#define __O volatile /* defines 'write only' permissions */ +#define __IO volatile /* defines 'read / write' permissions */ + +/* Standard Peripheral Library old types (maintained for legacy purpose) */ +typedef __I uint64_t vuc64; /* Read Only */ +typedef __I uint32_t vuc32; /* Read Only */ +typedef __I uint16_t vuc16; /* Read Only */ +typedef __I uint8_t vuc8; /* Read Only */ + +typedef const uint64_t uc64; /* Read Only */ +typedef const uint32_t uc32; /* Read Only */ +typedef const uint16_t uc16; /* Read Only */ +typedef const uint8_t uc8; /* Read Only */ + +typedef __I int64_t vsc64; /* Read Only */ +typedef __I int32_t vsc32; /* Read Only */ +typedef __I int16_t vsc16; /* Read Only */ +typedef __I int8_t vsc8; /* Read Only */ + +typedef const int64_t sc64; /* Read Only */ +typedef const int32_t sc32; /* Read Only */ +typedef const int16_t sc16; /* Read Only */ +typedef const int8_t sc8; /* Read Only */ + +typedef __IO uint64_t vu64; +typedef __IO uint32_t vu32; +typedef __IO uint16_t vu16; +typedef __IO uint8_t vu8; + +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef __IO int64_t vs64; +typedef __IO int32_t vs32; +typedef __IO int16_t vs16; +typedef __IO int8_t vs8; + +typedef int64_t s64; +typedef int32_t s32; +typedef int16_t s16; +typedef int8_t s8; + +typedef enum {NoREADY = 0, READY = !NoREADY} ErrorStatus; + +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; + +#define RV_STATIC_INLINE static inline + +/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */ +typedef struct{ + __I uint32_t ISR[8]; + __I uint32_t IPR[8]; + __IO uint32_t ITHRESDR; + __IO uint32_t RESERVED; + __IO uint32_t CFGR; + __I uint32_t GISR; + __IO uint8_t VTFIDR[4]; + uint8_t RESERVED0[12]; + __IO uint32_t VTFADDR[4]; + uint8_t RESERVED1[0x90]; + __O uint32_t IENR[8]; + uint8_t RESERVED2[0x60]; + __O uint32_t IRER[8]; + uint8_t RESERVED3[0x60]; + __O uint32_t IPSR[8]; + uint8_t RESERVED4[0x60]; + __O uint32_t IPRR[8]; + uint8_t RESERVED5[0x60]; + __IO uint32_t IACTR[8]; + uint8_t RESERVED6[0xE0]; + __IO uint8_t IPRIOR[256]; + uint8_t RESERVED7[0x810]; + __IO uint32_t SCTLR; +}PFIC_Type; + +/* memory mapped structure for SysTick */ +typedef struct +{ + __IO uint32_t CTLR; + __IO uint32_t SR; + __IO uint64_t CNT; + __IO uint64_t CMP; +}SysTick_Type; + +#define PFIC ((PFIC_Type *) 0xE000E000 ) +#define NVIC PFIC +#define NVIC_KEY1 ((uint32_t)0xFA050000) +#define NVIC_KEY2 ((uint32_t)0xBCAF0000) +#define NVIC_KEY3 ((uint32_t)0xBEEF0000) + +#define SysTick ((SysTick_Type *) 0xE000F000) + +/********************************************************************* + * @fn __enable_irq + * + * @brief Enable Global Interrupt + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __enable_irq(void) +{ + __asm volatile ("csrw 0x800, %0" : : "r" (0x6088) ); +} + +/********************************************************************* + * @fn __disable_irq + * + * @brief Disable Global Interrupt + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __disable_irq(void) +{ + __asm volatile ("csrw 0x800, %0" : : "r" (0x6000) ); +} + +/********************************************************************* + * @fn __NOP + * + * @brief nop + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __NOP(void) +{ + __asm volatile ("nop"); +} + +/********************************************************************* + * @fn NVIC_EnableIRQ + * + * @brief Disable Interrupt + * + * @param IRQn - Interrupt Numbers + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +/********************************************************************* + * @fn NVIC_DisableIRQ + * + * @brief Disable Interrupt + * + * @param IRQn - Interrupt Numbers + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +/********************************************************************* + * @fn NVIC_GetStatusIRQ + * + * @brief Get Interrupt Enable State + * + * @param IRQn - Interrupt Numbers + * + * @return 1 - Interrupt Pending Enable + * 0 - Interrupt Pending Disable + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetStatusIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +/********************************************************************* + * @fn NVIC_GetPendingIRQ + * + * @brief Get Interrupt Pending State + * + * @param IRQn - Interrupt Numbers + * + * @return 1 - Interrupt Pending Enable + * 0 - Interrupt Pending Disable + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +/********************************************************************* + * @fn NVIC_SetPendingIRQ + * + * @brief Set Interrupt Pending + * + * @param IRQn - Interrupt Numbers + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +/********************************************************************* + * @fn NVIC_ClearPendingIRQ + * + * @brief Clear Interrupt Pending + * + * @param IRQn - Interrupt Numbers + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + +/********************************************************************* + * @fn NVIC_GetActive + * + * @brief Get Interrupt Active State + * + * @param IRQn - Interrupt Numbers + * + * @return 1 - Interrupt Active + * 0 - Interrupt No Active + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)((NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + +/********************************************************************* + * @fn NVIC_SetPriority + * + * @brief Set Interrupt Priority + * + * @param IRQn - Interrupt Numbers + * priority - bit7 - Pre-emption Priority + * bit[6:5] - Subpriority + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint8_t priority) +{ + NVIC->IPRIOR[(uint32_t)(IRQn)] = priority; +} + +/********************************************************************* + * @fn __WFI + * + * @brief Wait for Interrupt + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void) +{ + NVIC->SCTLR &= ~(1<<3); // wfi + asm volatile ("wfi"); +} + +/********************************************************************* + * @fn _SEV + * + * @brief Set Event + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void _SEV(void) +{ + uint32_t t; + + t = NVIC->SCTLR; + NVIC->SCTLR |= (1<<3)|(1<<5); + NVIC->SCTLR = (NVIC->SCTLR & ~(1<<5)) | ( t & (1<<5)); +} + +/********************************************************************* + * @fn _WFE + * + * @brief Wait for Events + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void _WFE(void) +{ + NVIC->SCTLR |= (1<<3); + asm volatile ("wfi"); +} + +/********************************************************************* + * @fn __WFE + * + * @brief Wait for Events + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void) +{ + _SEV(); + _WFE(); + _WFE(); +} + +/********************************************************************* + * @fn SetVTFIRQ + * + * @brief Set VTF Interrupt + * + * @param addr - VTF interrupt service function base address. + * IRQn - Interrupt Numbers + * num - VTF Interrupt Numbers + * NewState - DISABLE or ENABLE + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){ + if(num > 3) return ; + + if (NewState != DISABLE) + { + NVIC->VTFIDR[num] = IRQn; + NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)|0x1); + } + else{ + NVIC->VTFIDR[num] = IRQn; + NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)&(~0x1)); + } +} + +/********************************************************************* + * @fn NVIC_SystemReset + * + * @brief Initiate a system reset request + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SystemReset(void) +{ + NVIC->CFGR = NVIC_KEY3|(1<<7); +} + +/********************************************************************* + * @fn __AMOADD_W + * + * @brief Atomic Add with 32bit value + * Atomically ADD 32bit value with value in memory using amoadd.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ADDed + * + * @return return memory value + add value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOADD_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoadd.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOAND_W + * + * @brief Atomic And with 32bit value + * Atomically AND 32bit value with value in memory using amoand.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ANDed + * + * @return return memory value & and value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOAND_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoand.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMAX_W + * + * @brief Atomic signed MAX with 32bit value + * Atomically signed max compare 32bit value with value in memory using amomax.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return the bigger value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMAX_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amomax.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMAXU_W + * + * @brief Atomic unsigned MAX with 32bit value + * Atomically unsigned max compare 32bit value with value in memory using amomaxu.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return return the bigger value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMAXU_W(volatile uint32_t *addr, uint32_t value) +{ + uint32_t result; + + __asm volatile ("amomaxu.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMIN_W + * + * @brief Atomic signed MIN with 32bit value + * Atomically signed min compare 32bit value with value in memory using amomin.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return the smaller value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMIN_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amomin.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMINU_W + * + * @brief Atomic unsigned MIN with 32bit value + * Atomically unsigned min compare 32bit value with value in memory using amominu.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return the smaller value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMINU_W(volatile uint32_t *addr, uint32_t value) +{ + uint32_t result; + + __asm volatile ("amominu.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOOR_W + * + * @brief Atomic OR with 32bit value + * Atomically OR 32bit value with value in memory using amoor.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ORed + * + * @return return memory value | and value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOOR_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoor.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOSWAP_W + * + * @brief Atomically swap new 32bit value into memory using amoswap.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * newval - New value to be stored into the address + * + * @return return the original value in memory + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOSWAP_W(volatile uint32_t *addr, uint32_t newval) +{ + uint32_t result; + + __asm volatile ("amoswap.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(newval) : "memory"); + return result; +} + +/********************************************************************* + * @fn __AMOXOR_W + * + * @brief Atomic XOR with 32bit value + * Atomically XOR 32bit value with value in memory using amoxor.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be XORed + * + * @return return memory value ^ and value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOXOR_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoxor.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/* Core_Exported_Functions */ +extern uint32_t __get_MSTATUS(void); +extern void __set_MSTATUS(uint32_t value); +extern uint32_t __get_MISA(void); +extern void __set_MISA(uint32_t value); +extern uint32_t __get_MTVEC(void); +extern void __set_MTVEC(uint32_t value); +extern uint32_t __get_MSCRATCH(void); +extern void __set_MSCRATCH(uint32_t value); +extern uint32_t __get_MEPC(void); +extern void __set_MEPC(uint32_t value); +extern uint32_t __get_MCAUSE(void); +extern void __set_MCAUSE(uint32_t value); +extern uint32_t __get_MTVAL(void); +extern void __set_MTVAL(uint32_t value); +extern uint32_t __get_MVENDORID(void); +extern uint32_t __get_MARCHID(void); +extern uint32_t __get_MIMPID(void); +extern uint32_t __get_MHARTID(void); +extern uint32_t __get_SP(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c new file mode 100644 index 000000000..247dacde6 --- /dev/null +++ b/hw/bsp/ch32v20x/family.c @@ -0,0 +1,82 @@ +#include +#include "ch32v20x.h" +#include "bsp/board_api.h" +#include "board.h" + +__attribute__((interrupt)) +void USBHD_IRQHandler(void) { + tud_int_handler(0); +} + +#if CFG_TUSB_OS == OPT_OS_NONE + +volatile uint32_t system_ticks = 0; + +__attribute__((interrupt)) +void SysTick_Handler(void) { + SysTick->SR = 0; + system_ticks++; +} + +uint32_t SysTick_Config(uint32_t ticks) { + NVIC_EnableIRQ(SysTicK_IRQn); + SysTick->CTLR = 0; + SysTick->SR = 0; + SysTick->CNT = 0; + SysTick->CMP = ticks-1; + SysTick->CTLR = 0xF; + return 0; +} + +uint32_t board_millis(void) { + return system_ticks; +} + +#endif + +void board_init(void) { + __disable_irq(); + +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(SystemCoreClock / 1000); +#endif + + switch (SystemCoreClock) { + case 48000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1); break; + case 96000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2); break; + case 144000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div3); break; + default: TU_ASSERT(0,); break; + } + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); + + LED_CLOCK_EN(); + GPIO_InitTypeDef GPIO_InitStructure = { + .GPIO_Pin = LED_PIN, + .GPIO_Mode = GPIO_Mode_Out_OD, + .GPIO_Speed = GPIO_Speed_50MHz, + }; + GPIO_Init(LED_PORT, &GPIO_InitStructure); + + __enable_irq(); + board_delay(2); +} + +void board_led_write(bool state) { + GPIO_WriteBit(LED_PORT, LED_PIN, state); +} + +uint32_t board_button_read(void) { + return false; +} + +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; + return 0; +} + +int board_uart_write(void const *buf, int len) { + (void) buf; + (void) len; + return len; +} diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk new file mode 100644 index 000000000..2d94f19fb --- /dev/null +++ b/hw/bsp/ch32v20x/family.mk @@ -0,0 +1,50 @@ +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +CROSS_COMPILE ?= riscv-none-elf- + +# Submodules +CH32V20X_SDK = hw/mcu/wch/ch32v20x +DEPS_SUBMODULES += $(CH32V20X_SDK) + +# WCH-SDK paths +CH32V20X_SDK_SRC = $(CH32V20X_SDK)/EVT/EXAM/SRC + +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -march=rv32imac_zicsr \ + -mabi=ilp32 \ + -mcmodel=medany \ + -ffunction-sections \ + -fdata-sections \ + -ffat-lto-objects \ + -flto \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_CH32V20X \ + -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED \ + +LDFLAGS_GCC += \ + -Wl,--gc-sections \ + -specs=nosys.specs \ + -specs=nano.specs \ + +LD_FILE = $(CH32V20X_SDK_SRC)/Ld/Link.ld + +SRC_C += \ + src/portable/wch/dcd_ch32_usbfs.c \ + $(CH32V20X_SDK_SRC)/Core/core_riscv.c \ + $(CH32V20X_SDK_SRC)/Peripheral/src/ch32v20x_gpio.c \ + $(CH32V20X_SDK_SRC)/Peripheral/src/ch32v20x_misc.c \ + $(CH32V20X_SDK_SRC)/Peripheral/src/ch32v20x_rcc.c \ + $(CH32V20X_SDK_SRC)/Peripheral/src/ch32v20x_usart.c \ + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(CH32V20X_SDK_SRC)/Peripheral/inc \ + +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V + +# wch-link is not supported yet in official openOCD yet. We need to either use +# 1. download openocd as part of mounriver studio http://www.mounriver.com/download or +# 2. compiled from modified source https://github.com/dragonlock2/miscboards/blob/main/wch/SDK/riscv-openocd.tar.xz +flash: $(BUILD)/$(PROJECT).elf + openocd -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "flash write_image $<" -c reset -c exit diff --git a/hw/bsp/ch32v20x/system_ch32v20x.c b/hw/bsp/ch32v20x/system_ch32v20x.c new file mode 100644 index 000000000..588f3165a --- /dev/null +++ b/hw/bsp/ch32v20x/system_ch32v20x.c @@ -0,0 +1,976 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : system_ch32v20x.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/06/06 + * Description : CH32V20x Device Peripheral Access Layer System Source File. + * For HSE = 32Mhz (CH32V208x/CH32V203RBT6) + * For HSE = 8Mhz (other CH32V203x) +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#include "ch32v20x.h" + +/* +* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after +* reset the HSI is used as SYSCLK source). +* If none of the define below is enabled, the HSI is used as System clock source. +*/ +//#define SYSCLK_FREQ_HSE HSE_VALUE +//#define SYSCLK_FREQ_48MHz_HSE 48000000 +//#define SYSCLK_FREQ_56MHz_HSE 56000000 +//#define SYSCLK_FREQ_72MHz_HSE 72000000 +#define SYSCLK_FREQ_96MHz_HSE 96000000 +//#define SYSCLK_FREQ_120MHz_HSE 120000000 +//#define SYSCLK_FREQ_144MHz_HSE 144000000 +//#define SYSCLK_FREQ_HSI HSI_VALUE +//#define SYSCLK_FREQ_48MHz_HSI 48000000 +//#define SYSCLK_FREQ_56MHz_HSI 56000000 +//#define SYSCLK_FREQ_72MHz_HSI 72000000 +//#define SYSCLK_FREQ_96MHz_HSI 96000000 +//#define SYSCLK_FREQ_120MHz_HSI 120000000 +//#define SYSCLK_FREQ_144MHz_HSI 144000000 + +/* Clock Definitions */ +#ifdef SYSCLK_FREQ_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_48MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_56MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_72MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_96MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_120MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_144MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_48MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_56MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_72MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_96MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSI; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_120MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSI; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_144MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSI; /* System Clock Frequency (Core Clock) */ +#else +uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */ + +#endif + +__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + +/* system_private_function_proto_types */ +static void SetSysClock(void); + +#ifdef SYSCLK_FREQ_HSE +static void SetSysClockToHSE( void ); +#elif defined SYSCLK_FREQ_48MHz_HSE +static void SetSysClockTo48_HSE( void ); +#elif defined SYSCLK_FREQ_56MHz_HSE +static void SetSysClockTo56_HSE( void ); +#elif defined SYSCLK_FREQ_72MHz_HSE +static void SetSysClockTo72_HSE( void ); +#elif defined SYSCLK_FREQ_96MHz_HSE +static void SetSysClockTo96_HSE( void ); +#elif defined SYSCLK_FREQ_120MHz_HSE +static void SetSysClockTo120_HSE( void ); +#elif defined SYSCLK_FREQ_144MHz_HSE +static void SetSysClockTo144_HSE( void ); +#elif defined SYSCLK_FREQ_48MHz_HSI +static void SetSysClockTo48_HSI( void ); +#elif defined SYSCLK_FREQ_56MHz_HSI +static void SetSysClockTo56_HSI( void ); +#elif defined SYSCLK_FREQ_72MHz_HSI +static void SetSysClockTo72_HSI( void ); +#elif defined SYSCLK_FREQ_96MHz_HSI +static void SetSysClockTo96_HSI( void ); +#elif defined SYSCLK_FREQ_120MHz_HSI +static void SetSysClockTo120_HSI( void ); +#elif defined SYSCLK_FREQ_144MHz_HSI +static void SetSysClockTo144_HSI( void ); + +#endif + +/********************************************************************* + * @fn SystemInit + * + * @brief Setup the microcontroller system Initialize the Embedded Flash Interface, + * the PLL and update the SystemCoreClock variable. + * + * @return none + */ +void SystemInit (void) +{ + RCC->CTLR |= (uint32_t)0x00000001; + RCC->CFGR0 &= (uint32_t)0xF8FF0000; + RCC->CTLR &= (uint32_t)0xFEF6FFFF; + RCC->CTLR &= (uint32_t)0xFFFBFFFF; + RCC->CFGR0 &= (uint32_t)0xFF80FFFF; + RCC->INTR = 0x009F0000; + SetSysClock(); +} + +/********************************************************************* + * @fn SystemCoreClockUpdate + * + * @brief Update SystemCoreClock variable according to Clock Register Values. + * + * @return none + */ +void SystemCoreClockUpdate (void) +{ + uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0; + + tmp = RCC->CFGR0 & RCC_SWS; + + switch (tmp) + { + case 0x00: + SystemCoreClock = HSI_VALUE; + break; + case 0x04: + SystemCoreClock = HSE_VALUE; + break; + case 0x08: + pllmull = RCC->CFGR0 & RCC_PLLMULL; + pllsource = RCC->CFGR0 & RCC_PLLSRC; + pllmull = ( pllmull >> 18) + 2; + + if(pllmull == 17) pllmull = 18; + + if (pllsource == 0x00) + { + if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){ + SystemCoreClock = HSI_VALUE * pllmull; + } + else{ + SystemCoreClock = (HSI_VALUE >> 1) * pllmull; + } + } + else + { +#if defined (CH32V20x_D8W) + if((RCC->CFGR0 & (3<<22)) == (3<<22)) + { + SystemCoreClock = ((HSE_VALUE>>1)) * pllmull; + } + else +#endif + if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET) + { +#if defined (CH32V20x_D8) || defined (CH32V20x_D8W) + SystemCoreClock = ((HSE_VALUE>>2) >> 1) * pllmull; +#else + SystemCoreClock = (HSE_VALUE >> 1) * pllmull; +#endif + } + else + { +#if defined (CH32V20x_D8) || defined (CH32V20x_D8W) + SystemCoreClock = (HSE_VALUE>>2) * pllmull; +#else + SystemCoreClock = HSE_VALUE * pllmull; +#endif + } + } + + if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2); + + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + + tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)]; + SystemCoreClock >>= tmp; +} + +/********************************************************************* + * @fn SetSysClock + * + * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClock(void) +{ +#ifdef SYSCLK_FREQ_HSE + SetSysClockToHSE(); +#elif defined SYSCLK_FREQ_48MHz_HSE + SetSysClockTo48_HSE(); +#elif defined SYSCLK_FREQ_56MHz_HSE + SetSysClockTo56_HSE(); +#elif defined SYSCLK_FREQ_72MHz_HSE + SetSysClockTo72_HSE(); +#elif defined SYSCLK_FREQ_96MHz_HSE + SetSysClockTo96_HSE(); +#elif defined SYSCLK_FREQ_120MHz_HSE + SetSysClockTo120_HSE(); +#elif defined SYSCLK_FREQ_144MHz_HSE + SetSysClockTo144_HSE(); +#elif defined SYSCLK_FREQ_48MHz_HSI + SetSysClockTo48_HSI(); +#elif defined SYSCLK_FREQ_56MHz_HSI + SetSysClockTo56_HSI(); +#elif defined SYSCLK_FREQ_72MHz_HSI + SetSysClockTo72_HSI(); +#elif defined SYSCLK_FREQ_96MHz_HSI + SetSysClockTo96_HSI(); +#elif defined SYSCLK_FREQ_120MHz_HSI + SetSysClockTo120_HSI(); +#elif defined SYSCLK_FREQ_144MHz_HSI + SetSysClockTo144_HSI(); + +#endif + + /* If none of the define above is enabled, the HSI is used as System clock + * source (default after reset) + */ +} + +#ifdef SYSCLK_FREQ_HSE + +/********************************************************************* + * @fn SetSysClockToHSE + * + * @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockToHSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1; + + /* Select HSE as system clock source + * CH32V20x_D6 (HSE=8MHZ) + * CH32V20x_D8 (HSE=32MHZ) + * CH32V20x_D8W (HSE=32MHZ) + */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_HSE; + + /* Wait till HSE is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04) + { + } + } + else + { + /* If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_48MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo48_HSE + * + * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo48_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8MHZ) + * CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ) + * CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ) + */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_56MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo56_HSE + * + * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo56_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8MHZ) + * CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ) + * CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ) + */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_72MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo72_HSE + * + * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo72_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8MHZ) + * CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ) + * CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ) + */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_96MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo96_HSE + * + * @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo96_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8MHZ) + * CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ) + * CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ) + */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_120MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo120_HSE + * + * @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo120_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if(HSEStatus == (uint32_t)0x01) + { +#if defined (CH32V20x_D8W) + RCC->CFGR0 |= (uint32_t)(3<<22); + /* HCLK = SYSCLK/2 */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2; +#else + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; +#endif + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8MHZ) + * CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 15 = 120 MHz (HSE=32MHZ) + * CH32V20x_D8W-PLL configuration: PLLCLK = HSE/2 * 15 = 240 MHz (HSE=32MHZ) + */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} +#elif defined SYSCLK_FREQ_144MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo144_HSE + * + * @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo144_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if ((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if (HSEStatus == (uint32_t)0x01) + { + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8MHZ) + * CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ) + * CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ) + */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_48MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo48_HSI + * + * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo48_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} + +#elif defined SYSCLK_FREQ_56MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo56_HSI + * + * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo56_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 7 = 48 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} + +#elif defined SYSCLK_FREQ_72MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo72_HSI + * + * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo72_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} + +#elif defined SYSCLK_FREQ_96MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo96_HSI + * + * @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo96_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 12 = 96 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} + +#elif defined SYSCLK_FREQ_120MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo120_HSI + * + * @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo120_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 15 = 120 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} +#elif defined SYSCLK_FREQ_144MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo144_HSI + * + * @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo144_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 18 = 144 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} + +#endif diff --git a/hw/bsp/ch32v20x/system_ch32v20x.h b/hw/bsp/ch32v20x/system_ch32v20x.h new file mode 100644 index 000000000..eec7ccb15 --- /dev/null +++ b/hw/bsp/ch32v20x/system_ch32v20x.h @@ -0,0 +1,29 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : system_ch32v20x.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/06/06 + * Description : CH32V20x Device Peripheral Access Layer System Header File. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#ifndef __SYSTEM_ch32v20x_H +#define __SYSTEM_ch32v20x_H + +#ifdef __cplusplus + extern "C" { +#endif + +extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */ + +/* System_Exported_Functions */ +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /*__CH32V20x_SYSTEM_H */ diff --git a/hw/bsp/ch32v20x/wch-riscv.cfg b/hw/bsp/ch32v20x/wch-riscv.cfg new file mode 100644 index 000000000..56a18d77e --- /dev/null +++ b/hw/bsp/ch32v20x/wch-riscv.cfg @@ -0,0 +1,18 @@ +#interface wlink +adapter driver wlinke +adapter speed 6000 +transport select sdi + +wlink_set_address 0x00000000 +set _CHIPNAME wch_riscv +sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 + +set _TARGETNAME $_CHIPNAME.cpu + +target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1 +set _FLASHNAME $_CHIPNAME.flash + +flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0 + +echo "Ready for Remote Connections" diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 003b90539..7232bfa08 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -4,6 +4,9 @@ # Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack CROSS_COMPILE ?= riscv-none-embed- +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +#CROSS_COMPILE ?= riscv-none-elf- + # Submodules CH32V307_SDK = hw/mcu/wch/ch32v307 @@ -13,6 +16,8 @@ CH32V307_SDK_SRC = $(CH32V307_SDK)/EVT/EXAM/SRC include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= rv32imac-ilp32 +# -march=rv32imac_zicsr + CFLAGS += \ -flto \ -msmall-data-limit=8 \ diff --git a/hw/bsp/fomu/family.mk b/hw/bsp/fomu/family.mk index d4b6eaea6..78f20d7db 100644 --- a/hw/bsp/fomu/family.mk +++ b/hw/bsp/fomu/family.mk @@ -1,6 +1,10 @@ # Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack CROSS_COMPILE = riscv-none-embed- +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +# CROSS_COMPILE = riscv-none-elf- +# -march=rv32i_zicsr + CPU_CORE ?= rv32i-ilp32 CFLAGS += \ diff --git a/hw/bsp/gd32vf103/family.mk b/hw/bsp/gd32vf103/family.mk index 28e48a6b5..646564eae 100644 --- a/hw/bsp/gd32vf103/family.mk +++ b/hw/bsp/gd32vf103/family.mk @@ -7,6 +7,9 @@ # Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack CROSS_COMPILE ?= riscv-none-embed- +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +# CROSS_COMPILE ?= riscv-none-elf- + # Submodules NUCLEI_SDK = hw/mcu/gd/nuclei-sdk @@ -19,6 +22,8 @@ STARTUP_ASM = $(GD32VF103_SDK_SOC)/Common/Source/GCC include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= rv32imac-ilp32 +# -march=rv32imac_zicsr + CFLAGS += \ -mcmodel=medlow \ -mstrict-align \ diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index 4218835aa..974289b69 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -609,7 +609,7 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * tusb_desc_cs_video_fmt_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); tusb_desc_cs_video_frm_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - uint_fast32_t interval, interval_ms; + uint_fast32_t interval, interval_ms = 0; switch (request) { case VIDEO_REQUEST_GET_MAX: { uint_fast32_t min_interval, max_interval; diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 3a7d6ad33..eab112015 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -410,6 +410,10 @@ #elif TU_CHECK_MCU(OPT_MCU_CH32F20X) #define TUP_DCD_ENDPOINT_MAX 16 #define TUP_RHPORT_HIGHSPEED 1 + +#elif TU_CHECK_MCU(OPT_MCU_CH32V20X) + #define TUP_DCD_ENDPOINT_MAX 8 + #endif diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h new file mode 100644 index 000000000..3b8e49ae2 --- /dev/null +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -0,0 +1,77 @@ +#ifndef USB_CH32_USBFS_REG_H +#define USB_CH32_USBFS_REG_H + +#if (CFG_TUSB_MCU == OPT_MCU_CH32V20X) +#include +#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/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c new file mode 100644 index 000000000..256c46696 --- /dev/null +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -0,0 +1,304 @@ +#include "tusb_option.h" + +#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V20X) + +#include +#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: + 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_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]; + xfer->valid = true; + xfer->buffer = buffer; + xfer->len = total_bytes; + xfer->processed_len = 0; + + 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 // CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V20X) diff --git a/src/tusb_option.h b/src/tusb_option.h index 058427e0e..3d04825a4 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -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 diff --git a/tools/get_deps.py b/tools/get_deps.py index 87c1c5ccd..cf15126b3 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -168,6 +168,9 @@ deps_optional = { 'hw/mcu/ti': ['https://github.com/hathach/ti_driver.git', '143ed6cc20a7615d042b03b21e070197d473e6e5', 'msp430 msp432e4 tm4c'], + 'hw/mcu/wch/ch32v20x': ['https://github.com/openwch/ch32v20x.git', + 'de6d68c654340d7f27b00cebbfc9aa2740a1abc2', + 'ch32v20x'], 'hw/mcu/wch/ch32v307': ['https://github.com/openwch/ch32v307.git', '17761f5cf9dbbf2dcf665b7c04934188add20082', 'ch32v307'], diff --git a/tools/iar_template.ipcf b/tools/iar_template.ipcf index e72ec0ce2..33a6ef045 100644 --- a/tools/iar_template.ipcf +++ b/tools/iar_template.ipcf @@ -239,6 +239,7 @@ $TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.h + $TUSB_DIR$/src/portable/wch/dcd_ch32_usbfs.c $TUSB_DIR$/src/portable/wch/dcd_ch32_usbhs.c $TUSB_DIR$/src/portable/wch/ch32_usbhs_reg.h From 2a67ce773dcd68f7f8c4c07fce2e6e4f7947e03d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 May 2024 20:13:00 +0700 Subject: [PATCH 18/48] change default risv-gcc to riscv-none-elf- and add _zicsr extension add cmake for ch32v20x, skip freertos examples for CH32V20X, also skip net webserver due to lack of RAM update to use openocd with wlinke adapter --- .github/workflows/ci_set_matrix.py | 4 +- .idea/cmake.xml | 4 +- .../build_system/cmake/cpu/rv32i-ilp32.cmake | 4 +- .../cmake/cpu/rv32imac-ilp32.cmake | 4 +- .../cmake/toolchain/riscv_gcc.cmake | 19 ++- examples/build_system/make/cpu/rv32i-ilp32.mk | 11 +- .../build_system/make/cpu/rv32imac-ilp32.mk | 10 +- .../audio_4_channel_mic_freertos/skip.txt | 1 + examples/device/audio_test_freertos/skip.txt | 1 + examples/device/net_lwip_webserver/skip.txt | 1 + examples/device/video_capture_2ch/skip.txt | 1 + .../ch32v20x/boards/nanoch32v203/board.cmake | 7 ++ hw/bsp/ch32v20x/family.cmake | 109 ++++++++++++++++++ hw/bsp/ch32v20x/family.mk | 17 ++- hw/bsp/ch32v20x/wch-riscv.cfg | 1 - hw/bsp/ch32v307/family.cmake | 1 - hw/bsp/ch32v307/family.mk | 8 +- hw/bsp/ch32v307/wch-riscv.cfg | 16 +-- hw/bsp/family_support.cmake | 1 + hw/bsp/fomu/family.mk | 6 +- hw/bsp/gd32vf103/family.mk | 7 +- src/portable/wch/dcd_ch32_usbfs.c | 8 ++ 22 files changed, 191 insertions(+), 50 deletions(-) create mode 100644 hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake create mode 100644 hw/bsp/ch32v20x/family.cmake diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 62239c9ad..c6f4e8fe2 100644 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -7,14 +7,14 @@ toolchain_list = { "arm-iar": "", "arm-gcc": "", "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", - "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1/xpack-riscv-none-embed-gcc-10.1.0-1.1-linux-x64.tar.gz", + "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz" } # family: [supported toolchain] family_list = { "broadcom_32bit": ["arm-gcc"], "broadcom_64bit": ["aarch64-gcc"], - "ch32v307 fomu gd32vf103": ["riscv-gcc"], + "ch32v20x ch32v307 fomu gd32vf103": ["riscv-gcc"], "imxrt": ["arm-gcc", "arm-clang"], "kinetis_k kinetis_kl kinetis_k32l2": ["arm-gcc", "arm-clang"], "lpc11 lpc13 lpc15": ["arm-gcc", "arm-clang"], diff --git a/.idea/cmake.xml b/.idea/cmake.xml index bb13a0466..a34f19e1f 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -66,6 +66,7 @@ + @@ -103,6 +104,7 @@ + @@ -120,7 +122,6 @@ - @@ -130,6 +131,7 @@ + \ No newline at end of file diff --git a/examples/build_system/cmake/cpu/rv32i-ilp32.cmake b/examples/build_system/cmake/cpu/rv32i-ilp32.cmake index b4889e6ff..605c40ba1 100644 --- a/examples/build_system/cmake/cpu/rv32i-ilp32.cmake +++ b/examples/build_system/cmake/cpu/rv32i-ilp32.cmake @@ -1,13 +1,13 @@ if (TOOLCHAIN STREQUAL "gcc") set(TOOLCHAIN_COMMON_FLAGS - -march=rv32i + -march=rv32i_zicsr -mabi=ilp32 ) set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "clang") set(TOOLCHAIN_COMMON_FLAGS - -march=rv32i + -march=rv32i_zicsr -mabi=ilp32 ) set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "") diff --git a/examples/build_system/cmake/cpu/rv32imac-ilp32.cmake b/examples/build_system/cmake/cpu/rv32imac-ilp32.cmake index dd1bc0af7..584d90519 100644 --- a/examples/build_system/cmake/cpu/rv32imac-ilp32.cmake +++ b/examples/build_system/cmake/cpu/rv32imac-ilp32.cmake @@ -1,13 +1,13 @@ if (TOOLCHAIN STREQUAL "gcc") set(TOOLCHAIN_COMMON_FLAGS - -march=rv32imac + -march=rv32imac_zicsr -mabi=ilp32 ) set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "clang") set(TOOLCHAIN_COMMON_FLAGS - -march=rv32imac + -march=rv32imac_zicsr -mabi=ilp32 ) set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "") diff --git a/examples/build_system/cmake/toolchain/riscv_gcc.cmake b/examples/build_system/cmake/toolchain/riscv_gcc.cmake index 904b27294..d788df023 100644 --- a/examples/build_system/cmake/toolchain/riscv_gcc.cmake +++ b/examples/build_system/cmake/toolchain/riscv_gcc.cmake @@ -1,15 +1,24 @@ +# default Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +if (NOT DEFINED CROSS_COMPILE) + set(CROSS_COMPILE "riscv-none-elf-") +endif () + if (NOT DEFINED CMAKE_C_COMPILER) - set(CMAKE_C_COMPILER "riscv-none-embed-gcc") + set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc) +endif () + +if (NOT DEFINED CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc) endif () if (NOT DEFINED CMAKE_CXX_COMPILER) - set(CMAKE_CXX_COMPILER "riscv-none-embed-g++") + set(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++) endif () set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) -set(CMAKE_SIZE "riscv-none-embed-size" CACHE FILEPATH "") -set(CMAKE_OBJCOPY "riscv-none-embed-objcopy" CACHE FILEPATH "") -set(CMAKE_OBJDUMP "riscv-none-embed-objdump" CACHE FILEPATH "") +set(CMAKE_SIZE ${CROSS_COMPILE}size CACHE FILEPATH "") +set(CMAKE_OBJCOPY ${CROSS_COMPILE}objcopy CACHE FILEPATH "") +set(CMAKE_OBJDUMP ${CROSS_COMPILE}objdump CACHE FILEPATH "") include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) diff --git a/examples/build_system/make/cpu/rv32i-ilp32.mk b/examples/build_system/make/cpu/rv32i-ilp32.mk index a465baf4c..af764afc5 100644 --- a/examples/build_system/make/cpu/rv32i-ilp32.mk +++ b/examples/build_system/make/cpu/rv32i-ilp32.mk @@ -1,12 +1,15 @@ ifeq ($(TOOLCHAIN),gcc) CFLAGS += \ - -march=rv32i \ + -march=rv32i_zicsr \ + -mabi=ilp32 \ + +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + -march=rv32i_zicsr \ -mabi=ilp32 \ else ifeq ($(TOOLCHAIN),iar) - #CFLAGS += --cpu cortex-a53 - #ASFLAGS += --cpu cortex-a53 - + $(error not support) endif # For freeRTOS port source diff --git a/examples/build_system/make/cpu/rv32imac-ilp32.mk b/examples/build_system/make/cpu/rv32imac-ilp32.mk index 2b6493e48..19c322ebc 100644 --- a/examples/build_system/make/cpu/rv32imac-ilp32.mk +++ b/examples/build_system/make/cpu/rv32imac-ilp32.mk @@ -1,11 +1,15 @@ ifeq ($(TOOLCHAIN),gcc) CFLAGS += \ - -march=rv32imac \ + -march=rv32imac_zicsr \ + -mabi=ilp32 \ + +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + -march=rv32imac_zicsr \ -mabi=ilp32 \ else ifeq ($(TOOLCHAIN),iar) - #CFLAGS += --cpu cortex-a53 - #ASFLAGS += --cpu cortex-a53 + $(error not support) endif diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index 0b689192d..4769af009 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:CH32V307 mcu:CXD56 mcu:F1C100S diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index a6f96b288..6aaa27661 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:CH32V307 mcu:CXD56 mcu:F1C100S diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 43cdab71a..51af58667 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:LPC11UXX mcu:LPC13XX mcu:LPC15XX diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index 86697899b..1786297f9 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -2,6 +2,7 @@ mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 mcu:GD32VF103 +mcu:CH32V20X mcu:CH32V307 mcu:STM32L0 family:espressif diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake b/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake new file mode 100644 index 000000000..2699f3e15 --- /dev/null +++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake @@ -0,0 +1,7 @@ +set(MCU_VARIANT D6) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + CH32V20x_D6 + ) +endfunction() diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake new file mode 100644 index 000000000..fb39e3630 --- /dev/null +++ b/hw/bsp/ch32v20x/family.cmake @@ -0,0 +1,109 @@ +include_guard() + +set(CH32_FAMILY ch32v20x) +set(SDK_DIR ${TOP}/hw/mcu/wch/${CH32_FAMILY}/EVT/EXAM/SRC) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR rv32imac-ilp32 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS CH32V20X CACHE INTERNAL "") +set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif() + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${SDK_DIR}/Ld/Link.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_DIR}/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Core/core_riscv.c + ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c + ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c + ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c + ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Peripheral/inc + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${BOARD_TARGET} PUBLIC + -mcmodel=medany + ) + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported for MSP432E4") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_CH32V20X ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_openocd_wch(${TARGET}) +endfunction() diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index 2d94f19fb..7e290bb18 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -1,3 +1,9 @@ +# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable +#CROSS_COMPILE ?= riscv32-unknown-elf- + +# Toolchain from https://nucleisys.com/download.php +#CROSS_COMPILE ?= riscv-nuclei-elf- + # Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack CROSS_COMPILE ?= riscv-none-elf- @@ -9,23 +15,21 @@ DEPS_SUBMODULES += $(CH32V20X_SDK) CH32V20X_SDK_SRC = $(CH32V20X_SDK)/EVT/EXAM/SRC include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= rv32imac-ilp32 CFLAGS += \ - -march=rv32imac_zicsr \ - -mabi=ilp32 \ -mcmodel=medany \ -ffunction-sections \ -fdata-sections \ -ffat-lto-objects \ -flto \ - -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_CH32V20X \ -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED \ LDFLAGS_GCC += \ -Wl,--gc-sections \ - -specs=nosys.specs \ - -specs=nano.specs \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs \ LD_FILE = $(CH32V20X_SDK_SRC)/Ld/Link.ld @@ -46,5 +50,6 @@ FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V # wch-link is not supported yet in official openOCD yet. We need to either use # 1. download openocd as part of mounriver studio http://www.mounriver.com/download or # 2. compiled from modified source https://github.com/dragonlock2/miscboards/blob/main/wch/SDK/riscv-openocd.tar.xz +OPENOCD ?= $(HOME)/app/riscv-openocd-wch/src/openocd flash: $(BUILD)/$(PROJECT).elf - openocd -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "flash write_image $<" -c reset -c exit + $(OPENOCD) -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "flash write_image $<" -c reset -c exit diff --git a/hw/bsp/ch32v20x/wch-riscv.cfg b/hw/bsp/ch32v20x/wch-riscv.cfg index 56a18d77e..aa35aa9c5 100644 --- a/hw/bsp/ch32v20x/wch-riscv.cfg +++ b/hw/bsp/ch32v20x/wch-riscv.cfg @@ -1,4 +1,3 @@ -#interface wlink adapter driver wlinke adapter speed 6000 transport select sdi diff --git a/hw/bsp/ch32v307/family.cmake b/hw/bsp/ch32v307/family.cmake index 87a0f2eba..fb478d387 100644 --- a/hw/bsp/ch32v307/family.cmake +++ b/hw/bsp/ch32v307/family.cmake @@ -11,7 +11,6 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TO set(FAMILY_MCUS CH32V307 CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") -set(OPENOCD_OPTION2 "-c wlink_reset_resume") #------------------------------------ # BOARD_TARGET diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 7232bfa08..df9ded4a0 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -1,11 +1,11 @@ # https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable #CROSS_COMPILE ?= riscv32-unknown-elf- -# Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack -CROSS_COMPILE ?= riscv-none-embed- +# Toolchain from https://nucleisys.com/download.php +#CROSS_COMPILE ?= riscv-nuclei-elf- # Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack -#CROSS_COMPILE ?= riscv-none-elf- +CROSS_COMPILE ?= riscv-none-elf- # Submodules CH32V307_SDK = hw/mcu/wch/ch32v307 @@ -16,8 +16,6 @@ CH32V307_SDK_SRC = $(CH32V307_SDK)/EVT/EXAM/SRC include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= rv32imac-ilp32 -# -march=rv32imac_zicsr - CFLAGS += \ -flto \ -msmall-data-limit=8 \ diff --git a/hw/bsp/ch32v307/wch-riscv.cfg b/hw/bsp/ch32v307/wch-riscv.cfg index 0d24d16ca..aa35aa9c5 100644 --- a/hw/bsp/ch32v307/wch-riscv.cfg +++ b/hw/bsp/ch32v307/wch-riscv.cfg @@ -1,13 +1,15 @@ -#interface wlink -adapter driver wlink -wlink_set -set _CHIPNAME riscv -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 +adapter driver wlinke +adapter speed 6000 +transport select sdi + +wlink_set_address 0x00000000 +set _CHIPNAME wch_riscv +sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME -$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 +target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0 diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index df4f616ef..6eef5b88b 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -440,6 +440,7 @@ function(family_flash_openocd TARGET) endfunction() # Add flash openocd-wch target +# compiled from https://github.com/hathach/riscv-openocd-wch or https://github.com/dragonlock2/miscboards/blob/main/wch/SDK/riscv-openocd.tar.xz function(family_flash_openocd_wch TARGET) if (NOT DEFINED OPENOCD) set(OPENOCD $ENV{HOME}/app/riscv-openocd-wch/src/openocd) diff --git a/hw/bsp/fomu/family.mk b/hw/bsp/fomu/family.mk index 78f20d7db..69a546964 100644 --- a/hw/bsp/fomu/family.mk +++ b/hw/bsp/fomu/family.mk @@ -1,9 +1,5 @@ -# Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack -CROSS_COMPILE = riscv-none-embed- - # Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack -# CROSS_COMPILE = riscv-none-elf- -# -march=rv32i_zicsr +CROSS_COMPILE = riscv-none-elf- CPU_CORE ?= rv32i-ilp32 diff --git a/hw/bsp/gd32vf103/family.mk b/hw/bsp/gd32vf103/family.mk index 646564eae..48588886c 100644 --- a/hw/bsp/gd32vf103/family.mk +++ b/hw/bsp/gd32vf103/family.mk @@ -4,11 +4,8 @@ # Toolchain from https://nucleisys.com/download.php #CROSS_COMPILE ?= riscv-nuclei-elf- -# Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack -CROSS_COMPILE ?= riscv-none-embed- - # Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack -# CROSS_COMPILE ?= riscv-none-elf- +CROSS_COMPILE ?= riscv-none-elf- # Submodules NUCLEI_SDK = hw/mcu/gd/nuclei-sdk @@ -22,8 +19,6 @@ STARTUP_ASM = $(GD32VF103_SDK_SOC)/Common/Source/GCC include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= rv32imac-ilp32 -# -march=rv32imac_zicsr - CFLAGS += \ -mcmodel=medlow \ -mstrict-align \ diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 256c46696..83f625e21 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -201,6 +201,14 @@ void dcd_disconnect(uint8_t 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 && From d3098747c03fe7f5d5d8b9a45ed4e7134fcaaf9d Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 16 May 2024 11:17:05 -0700 Subject: [PATCH 19/48] Add esp32c2 and esp32h2 for max3421 support --- src/common/tusb_mcu.h | 2 +- src/tusb_option.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 5a567f2d5..f4325e0d8 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -329,7 +329,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" //--------------------------------------------------------------------+ diff --git a/src/tusb_option.h b/src/tusb_option.h index 3ead20ee7..3a5b1e961 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -122,6 +122,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 From ab5f2768773634efe8c79add7e009e2e2ca63279 Mon Sep 17 00:00:00 2001 From: Matthew Tran Date: Fri, 17 May 2024 09:52:06 -0700 Subject: [PATCH 20/48] fix ep0 stall not clearing --- src/portable/wch/dcd_ch32_usbfs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 83f625e21..3af3ff6d7 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -148,6 +148,8 @@ void dcd_int_handler(uint8_t rhport) { case PID_SETUP: data.ep0_tog = true; + dcd_edpt_clear_stall(rhport, tu_edpt_addr(0, TUSB_DIR_IN)); // setup clears stall + dcd_edpt_clear_stall(rhport, tu_edpt_addr(0, TUSB_DIR_OUT)); dcd_event_setup_received(rhport, &data.buffer[0][TUSB_DIR_OUT][0], true); break; } @@ -261,10 +263,12 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to 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); From 5fee292606e4c5502b2172328c02d5df24eb0c7c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 17 May 2024 16:13:59 +0700 Subject: [PATCH 21/48] temp code --- hw/bsp/ch32v307/family.c | 25 +++++++++++++++++++++++++ hw/bsp/ch32v307/family.cmake | 23 ++++++++++++++--------- src/common/tusb_mcu.h | 4 ++-- src/portable/wch/ch32_usbfs_reg.h | 9 ++++++++- src/portable/wch/dcd_ch32_usbfs.c | 2 +- 5 files changed, 50 insertions(+), 13 deletions(-) diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index 245fa5674..50e48e7df 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -46,6 +46,18 @@ __attribute__ ((used)) void USBHS_IRQHandler_impl (void) tud_int_handler(0); } + +void OTG_FS_IRQHandler (void) __attribute__((naked)); +void OTG_FS_IRQHandler (void) +{ + __asm volatile ("call OTG_FS_IRQHandler_impl; mret"); +} + +__attribute__ ((used)) void OTG_FS_IRQHandler_impl (void) +{ + tud_int_handler(0); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ @@ -72,6 +84,7 @@ void board_init(void) { usart_printf_init(115200); + #if 0 RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY); RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE); RCC_USBHSConfig(RCC_USBPLL_Div2); @@ -79,6 +92,18 @@ void board_init(void) { RCC_USBHSPHYPLLALIVEcmd(ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE); + #else + uint8_t otg_div; + switch (SystemCoreClock) { + case 48000000: otg_div = RCC_OTGFSCLKSource_PLLCLK_Div1; break; + case 96000000: otg_div = RCC_OTGFSCLKSource_PLLCLK_Div2; break; + case 144000000: otg_div = RCC_OTGFSCLKSource_PLLCLK_Div3; break; + default: TU_ASSERT(0,); break; + } + RCC_OTGFSCLKConfig(otg_div); + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); + #endif + GPIO_InitTypeDef GPIO_InitStructure = {0}; // LED diff --git a/hw/bsp/ch32v307/family.cmake b/hw/bsp/ch32v307/family.cmake index fb478d387..8a4bd7730 100644 --- a/hw/bsp/ch32v307/family.cmake +++ b/hw/bsp/ch32v307/family.cmake @@ -1,5 +1,6 @@ include_guard() +set(CH32_FAMILY ch32v30x) set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v307/EVT/EXAM/SRC) # include board specific @@ -12,6 +13,8 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TO set(FAMILY_MCUS CH32V307 CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") +# Port0 Fullspeed, Port1 Highspeed + #------------------------------------ # BOARD_TARGET #------------------------------------ @@ -27,18 +30,18 @@ function(add_board_target BOARD_TARGET) set(LD_FILE_Clang ${LD_FILE_GNU}) if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/Startup/startup_ch32v30x_D8C.S) + set(STARTUP_FILE_GNU ${SDK_DIR}/Startup/startup_${CH32_FAMILY}_D8C.S) endif () set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/Core/core_riscv.c - ${SDK_DIR}/Peripheral/src/ch32v30x_gpio.c - ${SDK_DIR}/Peripheral/src/ch32v30x_misc.c - ${SDK_DIR}/Peripheral/src/ch32v30x_rcc.c - ${SDK_DIR}/Peripheral/src/ch32v30x_usart.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ch32v30x_it.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_ch32v30x.c + ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c + ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c + ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c + ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${CH32_FAMILY}_it.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC @@ -46,7 +49,8 @@ function(add_board_target BOARD_TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + #BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED ) update_board(${BOARD_TARGET}) @@ -100,7 +104,8 @@ function(family_configure_example TARGET RTOS) # Add TinyUSB target and port source family_add_tinyusb(${TARGET} OPT_MCU_CH32V307 ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC - ${TOP}/src/portable/wch/dcd_ch32_usbhs.c + #${TOP}/src/portable/wch/dcd_ch32_usbhs.c + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index eab112015..e313fea05 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -404,8 +404,8 @@ //------------- WCH -------------// #elif TU_CHECK_MCU(OPT_MCU_CH32V307) - #define TUP_DCD_ENDPOINT_MAX 16 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 +// #define TUP_RHPORT_HIGHSPEED 1 #elif TU_CHECK_MCU(OPT_MCU_CH32F20X) #define TUP_DCD_ENDPOINT_MAX 16 diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 3b8e49ae2..d5341f3a8 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -1,8 +1,15 @@ #ifndef USB_CH32_USBFS_REG_H #define USB_CH32_USBFS_REG_H -#if (CFG_TUSB_MCU == OPT_MCU_CH32V20X) +#if (CFG_TUSB_MCU == OPT_MCU_CH32V307) +#include +#define USBHD_IRQn OTG_FS_IRQn + +#elif (CFG_TUSB_MCU == OPT_MCU_CH32V20X) #include + +#elif (CFG_TUSB_MCU == OPT_MCU_CH32F20X) +#include #endif // CTRL diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 3af3ff6d7..3e4b6cae5 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -1,6 +1,6 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V20X) +#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V20X || CFG_TUSB_MCU == OPT_MCU_CH32V307) #include #include "device/dcd.h" From 4a5fee503b1e3783301cde9b605ef30052623327 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 May 2024 13:24:24 +0700 Subject: [PATCH 22/48] - update ch203 family to allow to specify flash and ram size. Introduce - add ch32v203_ro_1v0 board - CFG_EXAMPLE_MSC_DUAL_READONLY to build msc_dual_lun for ch32v203 --- examples/device/msc_dual_lun/skip.txt | 1 - .../device/msc_dual_lun/src/msc_disk_dual.c | 85 ++++++++----------- .../boards/ch32v203_r0_1v0/board.cmake | 10 +++ .../ch32v20x/boards/ch32v203_r0_1v0/board.h | 17 ++++ .../ch32v20x/boards/ch32v203_r0_1v0/board.mk | 7 ++ .../ch32v20x/boards/nanoch32v203/board.cmake | 5 +- hw/bsp/ch32v20x/boards/nanoch32v203/board.mk | 10 ++- hw/bsp/ch32v20x/family.cmake | 22 +++-- hw/bsp/ch32v20x/family.mk | 27 +++--- hw/bsp/ch32v20x/linker/ch32v20x.ld | 1 + 10 files changed, 106 insertions(+), 79 deletions(-) create mode 100644 hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.cmake create mode 100644 hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h create mode 100644 hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.mk create mode 100644 hw/bsp/ch32v20x/linker/ch32v20x.ld diff --git a/examples/device/msc_dual_lun/skip.txt b/examples/device/msc_dual_lun/skip.txt index 4d607dc05..a9e3a99b1 100644 --- a/examples/device/msc_dual_lun/skip.txt +++ b/examples/device/msc_dual_lun/skip.txt @@ -1,4 +1,3 @@ -mcu:CH32V20X mcu:SAMD11 mcu:MKL25ZXX family:espressif diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index 4f0f6410f..81f1d3346 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -34,9 +34,13 @@ // Some MCU doesn't have enough 8KB SRAM to store the whole disk // We will use Flash as read-only disk with board that has // CFG_EXAMPLE_MSC_READONLY defined +#if defined(CFG_EXAMPLE_MSC_READONLY) || defined(CFG_EXAMPLE_MSC_DUAL_READONLY) + #define MSC_CONST const +#else + #define MSC_CONST +#endif -enum -{ +enum { DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount DISK_BLOCK_SIZE = 512 }; @@ -51,10 +55,7 @@ If you find any bugs or get any questions, feel free to file an\r\n\ issue at github.com/hathach/tinyusb" -#ifdef CFG_EXAMPLE_MSC_READONLY -const -#endif -uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = +MSC_CONST uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { //------------- Block0: Boot Sector -------------// // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; @@ -132,10 +133,7 @@ uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = If you find any bugs or get any questions, feel free to file an\r\n\ issue at github.com/hathach/tinyusb" -#ifdef CFG_EXAMPLE_MSC_READONLY -const -#endif -uint8_t msc_disk1[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = +MSC_CONST uint8_t msc_disk1[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { //------------- Block0: Boot Sector -------------// // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; @@ -206,15 +204,13 @@ uint8_t msc_disk1[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = }; // Invoked to determine max LUN -uint8_t tud_msc_get_maxlun_cb(void) -{ +uint8_t tud_msc_get_maxlun_cb(void) { return 2; // dual LUN } // Invoked when received SCSI_CMD_INQUIRY // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively -void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) -{ +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) { (void) lun; // use same ID for both LUNs const char vid[] = "TinyUSB"; @@ -228,8 +224,7 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16 // Invoked when received Test Unit Ready command. // return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun) -{ +bool tud_msc_test_unit_ready_cb(uint8_t lun) { if ( lun == 1 && board_button_read() ) return false; return true; // RAM disk is always ready @@ -237,8 +232,7 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size // Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) -{ +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { (void) lun; *block_count = DISK_BLOCK_NUM; @@ -248,18 +242,14 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz // Invoked when received Start Stop Unit command // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage // - Start = 1 : active mode, if load_eject = 1 : load disk storage -bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) -{ +bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) { (void) lun; (void) power_condition; - if ( load_eject ) - { - if (start) - { + if (load_eject) { + if (start) { // load disk storage - }else - { + } else { // unload disk storage } } @@ -269,10 +259,9 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. -int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) -{ +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if (lba >= DISK_BLOCK_NUM) return -1; uint8_t const* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset; memcpy(buffer, addr, bufsize); @@ -280,11 +269,10 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff return (int32_t) bufsize; } -bool tud_msc_is_writable_cb (uint8_t lun) -{ +bool tud_msc_is_writable_cb(uint8_t lun) { (void) lun; -#ifdef CFG_EXAMPLE_MSC_READONLY +#if defined(CFG_EXAMPLE_MSC_READONLY) || defined(CFG_EXAMPLE_MSC_DUAL_READONLY) return false; #else return true; @@ -293,16 +281,18 @@ bool tud_msc_is_writable_cb (uint8_t lun) // Callback invoked when received WRITE10 command. // Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) -{ +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if (lba >= DISK_BLOCK_NUM) return -1; -#ifndef CFG_EXAMPLE_MSC_READONLY +#if defined(CFG_EXAMPLE_MSC_READONLY) || defined(CFG_EXAMPLE_MSC_DUAL_READONLY) + (void) lun; + (void) lba; + (void) offset; + (void) buffer; +#else uint8_t* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset; memcpy(addr, buffer, bufsize); -#else - (void) lun; (void) lba; (void) offset; (void) buffer; #endif return (int32_t) bufsize; @@ -311,8 +301,7 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) -{ +int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { // read10 & write10 has their own callback and MUST not be handled here void const* response = NULL; @@ -321,27 +310,23 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, // most scsi handled is input bool in_xfer = true; - switch (scsi_cmd[0]) - { + switch (scsi_cmd[0]) { default: // Set Sense = Invalid Command Operation tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // negative means error -> tinyusb could stall and/or response with failed status resplen = -1; - break; + break; } // return resplen must not larger than bufsize - if ( resplen > bufsize ) resplen = bufsize; + if (resplen > bufsize) resplen = bufsize; - if ( response && (resplen > 0) ) - { - if(in_xfer) - { + if (response && (resplen > 0)) { + if (in_xfer) { memcpy(buffer, response, (size_t) resplen); - }else - { + } else { // SCSI output } } diff --git a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.cmake b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.cmake new file mode 100644 index 000000000..8d3e0326e --- /dev/null +++ b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.cmake @@ -0,0 +1,10 @@ +set(MCU_VARIANT D6) + +set(LD_FLASH_SIZE 64K) +set(LD_RAM_SIZE 20K) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + CFG_EXAMPLE_MSC_DUAL_READONLY + ) +endfunction() diff --git a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h new file mode 100644 index 000000000..c8d28d90f --- /dev/null +++ b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h @@ -0,0 +1,17 @@ +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LED_PORT GPIOA +#define LED_PIN GPIO_Pin_15 +#define LED_STATE_ON 0 +#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.mk b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.mk new file mode 100644 index 000000000..7d7462312 --- /dev/null +++ b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.mk @@ -0,0 +1,7 @@ +MCU_VARIANT = D6 + +CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY + +LDFLAGS += \ + -Wl,--defsym=__flash_size=64K \ + -Wl,--defsym=__ram_size=20K \ diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake b/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake index 2699f3e15..8d3e0326e 100644 --- a/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake +++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake @@ -1,7 +1,10 @@ set(MCU_VARIANT D6) +set(LD_FLASH_SIZE 64K) +set(LD_RAM_SIZE 20K) + function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC - CH32V20x_D6 + CFG_EXAMPLE_MSC_DUAL_READONLY ) endfunction() diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk b/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk index 75dc05457..7d7462312 100644 --- a/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk +++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk @@ -1,5 +1,7 @@ -CFLAGS += \ - -DCH32V20x_D6 +MCU_VARIANT = D6 -SRC_S += \ - $(CH32V20X_SDK_SRC)/Startup/startup_ch32v20x_D6.S +CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY + +LDFLAGS += \ + -Wl,--defsym=__flash_size=64K \ + -Wl,--defsym=__ram_size=20K \ diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index fb39e3630..80b035fc0 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -1,7 +1,8 @@ include_guard() set(CH32_FAMILY ch32v20x) -set(SDK_DIR ${TOP}/hw/mcu/wch/${CH32_FAMILY}/EVT/EXAM/SRC) +set(SDK_DIR ${TOP}/hw/mcu/wch/${CH32_FAMILY}) +set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC) # include board specific include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) @@ -23,29 +24,30 @@ function(add_board_target BOARD_TARGET) endif() if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/Ld/Link.ld) + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${CH32_FAMILY}.ld) endif () set(LD_FILE_Clang ${LD_FILE_GNU}) if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S) + set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S) endif () set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) add_library(${BOARD_TARGET} STATIC - ${SDK_DIR}/Core/core_riscv.c - ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c - ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c - ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c - ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c + ${SDK_SRC_DIR}/Core/core_riscv.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_DIR}/Peripheral/inc + ${SDK_SRC_DIR}/Peripheral/inc ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ) target_compile_definitions(${BOARD_TARGET} PUBLIC + CH32V20x_${MCU_VARIANT} BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED ) @@ -57,6 +59,8 @@ function(add_board_target BOARD_TARGET) ) target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}" + -Wl,--defsym=__flash_size=${LD_FLASH_SIZE} + -Wl,--defsym=__ram_size=${LD_RAM_SIZE} -nostartfiles --specs=nosys.specs --specs=nano.specs ) diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index 7e290bb18..6b09fdac7 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -7,12 +7,9 @@ # Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack CROSS_COMPILE ?= riscv-none-elf- -# Submodules -CH32V20X_SDK = hw/mcu/wch/ch32v20x -DEPS_SUBMODULES += $(CH32V20X_SDK) - -# WCH-SDK paths -CH32V20X_SDK_SRC = $(CH32V20X_SDK)/EVT/EXAM/SRC +CH32_FAMILY = ch32v20x +SDK_DIR = hw/mcu/wch/ch32v20x +SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= rv32imac-ilp32 @@ -23,27 +20,29 @@ CFLAGS += \ -fdata-sections \ -ffat-lto-objects \ -flto \ + -DCH32V20x_${MCU_VARIANT} \ -DCFG_TUSB_MCU=OPT_MCU_CH32V20X \ -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED \ LDFLAGS_GCC += \ - -Wl,--gc-sections \ -nostdlib -nostartfiles \ --specs=nosys.specs --specs=nano.specs \ -LD_FILE = $(CH32V20X_SDK_SRC)/Ld/Link.ld +LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld SRC_C += \ src/portable/wch/dcd_ch32_usbfs.c \ - $(CH32V20X_SDK_SRC)/Core/core_riscv.c \ - $(CH32V20X_SDK_SRC)/Peripheral/src/ch32v20x_gpio.c \ - $(CH32V20X_SDK_SRC)/Peripheral/src/ch32v20x_misc.c \ - $(CH32V20X_SDK_SRC)/Peripheral/src/ch32v20x_rcc.c \ - $(CH32V20X_SDK_SRC)/Peripheral/src/ch32v20x_usart.c \ + $(SDK_SRC_DIR)/Core/core_riscv.c \ + $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_gpio.c \ + $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_misc.c \ + $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_rcc.c \ + $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_usart.c \ + +SRC_S += $(SDK_SRC_DIR)/Startup/startup_ch32v20x_${MCU_VARIANT}.S INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(CH32V20X_SDK_SRC)/Peripheral/inc \ + $(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \ FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V diff --git a/hw/bsp/ch32v20x/linker/ch32v20x.ld b/hw/bsp/ch32v20x/linker/ch32v20x.ld new file mode 100644 index 000000000..6ee2fa1c7 --- /dev/null +++ b/hw/bsp/ch32v20x/linker/ch32v20x.ld @@ -0,0 +1 @@ +/* Define default values if not already defined */ __FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K; __RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K; MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __FLASH_SIZE RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __RAM_SIZE } ENTRY( _start ) __stack_size = 2048; PROVIDE( _stack_size = __stack_size ); SECTIONS { .init : { _sinit = .; . = ALIGN(4); KEEP(*(SORT_NONE(.init))) . = ALIGN(4); _einit = .; } >FLASH AT>FLASH .vector : { *(.vector); . = ALIGN(64); } >FLASH AT>FLASH .text : { . = ALIGN(4); *(.text) *(.text.*) *(.rodata) *(.rodata*) *(.gnu.linkonce.t.*) . = ALIGN(4); } >FLASH AT>FLASH .fini : { KEEP(*(SORT_NONE(.fini))) . = ALIGN(4); } >FLASH AT>FLASH PROVIDE( _etext = . ); PROVIDE( _eitcm = . ); .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } >FLASH AT>FLASH .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); } >FLASH AT>FLASH .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH AT>FLASH .ctors : { /* gcc uses crtbegin.o to find the start of the constructors, so we make sure it is first. Because this is a wildcard, it doesn't matter if the user does not actually link against crtbegin.o; the linker won't look for a file to match a wildcard. The wildcard also means that it doesn't matter which directory crtbegin.o is in. */ KEEP (*crtbegin.o(.ctors)) KEEP (*crtbegin?.o(.ctors)) /* We don't want to include the .ctor section from the crtend.o file until after the sorted ctors. The .ctor section from the crtend file contains the end of ctors marker and it must be last */ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) } >FLASH AT>FLASH .dtors : { KEEP (*crtbegin.o(.dtors)) KEEP (*crtbegin?.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) } >FLASH AT>FLASH .dalign : { . = ALIGN(4); PROVIDE(_data_vma = .); } >RAM AT>FLASH .dlalign : { . = ALIGN(4); PROVIDE(_data_lma = .); } >FLASH AT>FLASH .data : { *(.gnu.linkonce.r.*) *(.data .data.*) *(.gnu.linkonce.d.*) . = ALIGN(8); PROVIDE( __global_pointer$ = . + 0x800 ); *(.sdata .sdata.*) *(.sdata2.*) *(.gnu.linkonce.s.*) . = ALIGN(8); *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) . = ALIGN(4); PROVIDE( _edata = .); } >RAM AT>FLASH .bss : { . = ALIGN(4); PROVIDE( _sbss = .); *(.sbss*) *(.gnu.linkonce.sb.*) *(.bss*) *(.gnu.linkonce.b.*) *(COMMON*) . = ALIGN(4); PROVIDE( _ebss = .); } >RAM AT>FLASH PROVIDE( _end = _ebss); PROVIDE( end = . ); .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : { PROVIDE( _heap_end = . ); . = ALIGN(4); PROVIDE(_susrstack = . ); . = . + __stack_size; PROVIDE( _eusrstack = .); } >RAM } From b19295c1c15de676e7cebd5bd5b6aa53887c6a56 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 May 2024 17:26:04 +0700 Subject: [PATCH 23/48] use correct wch usbhs, usbfs for ch32v307 using CFG_TUD_MAX_SPEED --- examples/build_system/make/rules.mk | 11 +++++ hw/bsp/ch32v20x/family.mk | 10 +--- hw/bsp/ch32v307/family.c | 77 ++++++++++------------------- hw/bsp/ch32v307/family.cmake | 27 +++++----- hw/bsp/ch32v307/family.mk | 61 ++++++++++------------- src/common/tusb_mcu.h | 16 ++++-- src/portable/wch/ch32_usbhs_reg.h | 4 +- src/portable/wch/dcd_ch32_usbfs.c | 3 +- src/portable/wch/dcd_ch32_usbhs.c | 6 +-- 9 files changed, 98 insertions(+), 117 deletions(-) diff --git a/examples/build_system/make/rules.mk b/examples/build_system/make/rules.mk index 7b6b339ed..102c6db0c 100644 --- a/examples/build_system/make/rules.mk +++ b/examples/build_system/make/rules.mk @@ -134,6 +134,17 @@ OPENOCD_OPTION ?= flash-openocd: $(BUILD)/$(PROJECT).elf openocd $(OPENOCD_OPTION) -c "program $< verify reset exit" +# --------------- openocd-wch ----------------- +# wch-linke is not supported yet in official openOCD yet. We need to either use +# 1. download openocd as part of mounriver studio http://www.mounriver.com/download or +# 2. compiled from https://github.com/hathach/riscv-openocd-wch or +# https://github.com/dragonlock2/miscboards/blob/main/wch/SDK/riscv-openocd.tar.xz +# with ./configure --disable-werror --enable-wlinke --enable-ch347=no +OPENOCD_WCH ?= /home/${USER}/app/riscv-openocd-wch/src/openocd +OPENOCD_WCH_OPTION ?= +flash-openocd-wch: $(BUILD)/$(PROJECT).elf + $(OPENOCD_WCH) $(OPENOCD_WCH_OPTION) -c init -c halt -c "flash write_image $<" -c reset -c exit + # --------------- dfu-util ----------------- DFU_UTIL_OPTION ?= -a 0 flash-dfu-util: $(BUILD)/$(PROJECT).bin diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index 6b09fdac7..5c8b31a1c 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -16,8 +16,6 @@ CPU_CORE ?= rv32imac-ilp32 CFLAGS += \ -mcmodel=medany \ - -ffunction-sections \ - -fdata-sections \ -ffat-lto-objects \ -flto \ -DCH32V20x_${MCU_VARIANT} \ @@ -46,9 +44,5 @@ INC += \ FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V -# wch-link is not supported yet in official openOCD yet. We need to either use -# 1. download openocd as part of mounriver studio http://www.mounriver.com/download or -# 2. compiled from modified source https://github.com/dragonlock2/miscboards/blob/main/wch/SDK/riscv-openocd.tar.xz -OPENOCD ?= $(HOME)/app/riscv-openocd-wch/src/openocd -flash: $(BUILD)/$(PROJECT).elf - $(OPENOCD) -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "flash write_image $<" -c reset -c exit +OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg +flash: flash-openocd-wch diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index 50e48e7df..fe37ea8e3 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -35,41 +35,31 @@ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USBHS_IRQHandler (void) __attribute__((naked)); -void USBHS_IRQHandler (void) -{ - __asm volatile ("call USBHS_IRQHandler_impl; mret"); -} +// TODO maybe having FS as port0, HS as port1 -__attribute__ ((used)) void USBHS_IRQHandler_impl (void) -{ +__attribute__((interrupt)) void USBHS_IRQHandler(void) { + #if CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED tud_int_handler(0); + #endif } - -void OTG_FS_IRQHandler (void) __attribute__((naked)); -void OTG_FS_IRQHandler (void) -{ - __asm volatile ("call OTG_FS_IRQHandler_impl; mret"); -} - -__attribute__ ((used)) void OTG_FS_IRQHandler_impl (void) -{ +__attribute__((interrupt)) void OTG_FS_IRQHandler(void) { + #if CFG_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED tud_int_handler(0); + #endif } //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ -uint32_t SysTick_Config(uint32_t ticks) -{ +uint32_t SysTick_Config(uint32_t ticks) { NVIC_EnableIRQ(SysTicK_IRQn); - SysTick->CTLR=0; - SysTick->SR=0; - SysTick->CNT=0; - SysTick->CMP=ticks-1; - SysTick->CTLR=0xF; + SysTick->CTLR = 0; + SysTick->SR = 0; + SysTick->CNT = 0; + SysTick->CMP = ticks - 1; + SysTick->CTLR = 0xF; return 0; } @@ -82,17 +72,17 @@ void board_init(void) { SysTick_Config(SystemCoreClock / 1000); #endif - usart_printf_init(115200); + usart_printf_init(115200); - #if 0 +#if CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED + // Use Highspeed USB RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY); RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE); RCC_USBHSConfig(RCC_USBPLL_Div2); RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M); RCC_USBHSPHYPLLALIVEcmd(ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE); - - #else +#else uint8_t otg_div; switch (SystemCoreClock) { case 48000000: otg_div = RCC_OTGFSCLKSource_PLLCLK_Div1; break; @@ -102,7 +92,7 @@ void board_init(void) { } RCC_OTGFSCLKConfig(otg_div); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); - #endif +#endif GPIO_InitTypeDef GPIO_InitStructure = {0}; @@ -127,24 +117,14 @@ void board_init(void) { } #if CFG_TUSB_OS == OPT_OS_NONE - volatile uint32_t system_ticks = 0; -/* Small workaround to support HW stack save/restore */ -void SysTick_Handler (void) __attribute__((naked)); -void SysTick_Handler (void) -{ - __asm volatile ("call SysTick_Handler_impl; mret"); -} - -__attribute__((used)) void SysTick_Handler_impl (void) -{ +__attribute__((interrupt)) void SysTick_Handler(void) { SysTick->SR = 0; system_ticks++; } -uint32_t board_millis (void) -{ +uint32_t board_millis(void) { return system_ticks; } @@ -154,36 +134,29 @@ uint32_t board_millis (void) // Board porting API //--------------------------------------------------------------------+ -void board_led_write (bool state) -{ +void board_led_write(bool state) { GPIO_WriteBit(LED_PORT, LED_PIN, state); } -uint32_t board_button_read (void) -{ +uint32_t board_button_read(void) { return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN); } -int board_uart_read (uint8_t *buf, int len) -{ +int board_uart_read(uint8_t* buf, int len) { (void) buf; (void) len; return 0; } -int board_uart_write (void const *buf, int len) -{ +int board_uart_write(void const* buf, int len) { int txsize = len; - while ( txsize-- ) - { + while (txsize--) { uart_write(*(uint8_t const*) buf); buf++; } return len; } - - #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number diff --git a/hw/bsp/ch32v307/family.cmake b/hw/bsp/ch32v307/family.cmake index 8a4bd7730..fd475c987 100644 --- a/hw/bsp/ch32v307/family.cmake +++ b/hw/bsp/ch32v307/family.cmake @@ -1,7 +1,8 @@ include_guard() set(CH32_FAMILY ch32v30x) -set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v307/EVT/EXAM/SRC) +set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v307) +set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC) # include board specific include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) @@ -13,7 +14,10 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TO set(FAMILY_MCUS CH32V307 CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") -# Port0 Fullspeed, Port1 Highspeed +# default to highspeed +if (NOT DEFINED SPEED) + set(SPEED high) +endif() #------------------------------------ # BOARD_TARGET @@ -30,27 +34,26 @@ function(add_board_target BOARD_TARGET) set(LD_FILE_Clang ${LD_FILE_GNU}) if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/Startup/startup_${CH32_FAMILY}_D8C.S) + set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_D8C.S) endif () set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) add_library(${BOARD_TARGET} STATIC - ${SDK_DIR}/Core/core_riscv.c - ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c - ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c - ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c - ${SDK_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c + ${SDK_SRC_DIR}/Core/core_riscv.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${CH32_FAMILY}_it.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_DIR}/Peripheral/inc + ${SDK_SRC_DIR}/Peripheral/inc ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ) target_compile_definitions(${BOARD_TARGET} PUBLIC - #BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED + BOARD_TUD_MAX_SPEED=$,OPT_MODE_HIGH_SPEED,OPT_MODE_FULL_SPEED> ) update_board(${BOARD_TARGET}) @@ -104,7 +107,7 @@ function(family_configure_example TARGET RTOS) # Add TinyUSB target and port source family_add_tinyusb(${TARGET} OPT_MCU_CH32V307 ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC - #${TOP}/src/portable/wch/dcd_ch32_usbhs.c + ${TOP}/src/portable/wch/dcd_ch32_usbhs.c ${TOP}/src/portable/wch/dcd_ch32_usbfs.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index df9ded4a0..2dbe0c46a 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -7,63 +7,54 @@ # Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack CROSS_COMPILE ?= riscv-none-elf- -# Submodules -CH32V307_SDK = hw/mcu/wch/ch32v307 - -# WCH-SDK paths -CH32V307_SDK_SRC = $(CH32V307_SDK)/EVT/EXAM/SRC +CH32_FAMILY = ch32v30x +SDK_DIR = hw/mcu/wch/ch32v307 +SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= rv32imac-ilp32 +# default to use high speed port, unless specified in board.mk or command line +SPEED ?= high + CFLAGS += \ -flto \ -msmall-data-limit=8 \ - -mno-save-restore -Os \ + -mno-save-restore \ -fmessage-length=0 \ -fsigned-char \ - -ffunction-sections \ - -fdata-sections \ -DCFG_TUSB_MCU=OPT_MCU_CH32V307 \ - -Xlinker --gc-sections \ - -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + +ifeq ($(SPEED),high) + CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + $(info "Using USBHS driver for HighSpeed mode") +else + CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED + $(info "Using USBFS driver for FullSpeed mode") +endif LDFLAGS_GCC += \ -nostdlib -nostartfiles \ - --specs=nosys.specs --specs=nano.specs + --specs=nosys.specs --specs=nano.specs \ SRC_C += \ src/portable/wch/dcd_ch32_usbhs.c \ - $(CH32V307_SDK_SRC)/Core/core_riscv.c \ - $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_gpio.c \ - $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_misc.c \ - $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_rcc.c \ - $(CH32V307_SDK_SRC)/Peripheral/src/ch32v30x_usart.c + src/portable/wch/dcd_ch32_usbfs.c \ + $(SDK_SRC_DIR)/Core/core_riscv.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c SRC_S += \ - $(CH32V307_SDK_SRC)/Startup/startup_ch32v30x_D8C.S + $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}_D8C.S INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(CH32V307_SDK_SRC)/Peripheral/inc + $(TOP)/$(SDK_SRC_DIR)/Peripheral/inc # For freeRTOS port source FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V -# wch-link is not supported yet in official openOCD yet. We need to either use -# 1. download openocd as part of mounriver studio http://www.mounriver.com/download or -# 2. compiled from modified source https://github.com/kprasadvnsi/riscv-openocd-wch -# -# Note: For Linux, somehow openocd in mounriver studio does not seem to have wch-link enable, -# therefore we need to compile it from source as follows: -# git clone https://github.com/kprasadvnsi/riscv-openocd-wch -# cd riscv-openocd-wch -# ./bootstrap -# ./configure CFLAGS="-Wno-error" --enable-wlink -# make -# openocd binaries will be generated in riscv-openocd-wch/src - -# flash target ROM bootloader -OPENOCD_WCH = /home/${USER}/app/riscv-openocd-wch/src/openocd -flash: $(BUILD)/$(PROJECT).elf - $(OPENOCD_WCH) -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "program $<" -c wlink_reset_resume -c exit +OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg +flash: flash-openocd-wch diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index e313fea05..d928e44e8 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -404,14 +404,22 @@ //------------- WCH -------------// #elif TU_CHECK_MCU(OPT_MCU_CH32V307) - #define TUP_DCD_ENDPOINT_MAX 8 -// #define TUP_RHPORT_HIGHSPEED 1 + // v307 support both FS and HS + #define TUP_USBIP_WCH_USBHS + #define TUP_USBIP_WCH_USBFS + + #define TUP_RHPORT_HIGHSPEED 1 // default to highspeed + #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED ? 16 : 8) #elif TU_CHECK_MCU(OPT_MCU_CH32F20X) - #define TUP_DCD_ENDPOINT_MAX 16 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_USBIP_WCH_USBHS + #define TUP_USBIP_WCH_USBFS + + #define TUP_RHPORT_HIGHSPEED 1 // default to highspeed + #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED ? 16 : 8) #elif TU_CHECK_MCU(OPT_MCU_CH32V20X) + #define TUP_USBIP_WCH_USBFS #define TUP_DCD_ENDPOINT_MAX 8 #endif diff --git a/src/portable/wch/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h index 9b956231f..6ae91ec71 100644 --- a/src/portable/wch/ch32_usbhs_reg.h +++ b/src/portable/wch/ch32_usbhs_reg.h @@ -2,9 +2,9 @@ #define _USB_CH32_USBHS_REG_H #if (CFG_TUSB_MCU == OPT_MCU_CH32V307) -#include + #include #elif (CFG_TUSB_MCU == OPT_MCU_CH32F20X) -#include + #include #endif /******************* GLOBAL ******************/ diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 3e4b6cae5..413fe92c9 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -1,6 +1,7 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V20X || CFG_TUSB_MCU == OPT_MCU_CH32V307) +// Note: CH32 can have both USB FS and HS, only use this driver if CFG_TUD_MAX_SPEED is full speed +#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBFS) && (CFG_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED) #include #include "device/dcd.h" diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 68e2179e9..9a12fc97f 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -26,11 +26,11 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && ((CFG_TUSB_MCU == OPT_MCU_CH32V307) || (CFG_TUSB_MCU == OPT_MCU_CH32F20X)) -#include "device/dcd.h" - +// Note: CH32 can have both USB FS and HS, only use this driver if CFG_TUD_MAX_SPEED is high speed +#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && (CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) #include "ch32_usbhs_reg.h" +#include "device/dcd.h" // Max number of bi-directional endpoints including EP0 #define EP_MAX 16 From 07d879378f052386699aba1eb41f04d4d32fb865 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 May 2024 17:32:40 +0700 Subject: [PATCH 24/48] code format add missing MIT license --- .idea/cmake.xml | 2 + src/portable/wch/ch32_usbfs_reg.h | 41 ++- src/portable/wch/ch32_usbhs_reg.h | 35 ++- src/portable/wch/dcd_ch32_usbfs.c | 460 ++++++++++++++++-------------- 4 files changed, 311 insertions(+), 227 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index a34f19e1f..d96b46853 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -132,6 +132,8 @@ + + \ No newline at end of file diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index d5341f3a8..0a50a6169 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -1,15 +1,42 @@ +/* + * 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 -#define USBHD_IRQn OTG_FS_IRQn +#if CFG_TUSB_MCU == OPT_MCU_CH32V307 + #include + #define USBHD_IRQn OTG_FS_IRQn -#elif (CFG_TUSB_MCU == OPT_MCU_CH32V20X) -#include +#elif CFG_TUSB_MCU == OPT_MCU_CH32V20X + #include -#elif (CFG_TUSB_MCU == OPT_MCU_CH32F20X) -#include +#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X + #include #endif // CTRL diff --git a/src/portable/wch/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h index 6ae91ec71..a3a41bb6a 100644 --- a/src/portable/wch/ch32_usbhs_reg.h +++ b/src/portable/wch/ch32_usbhs_reg.h @@ -1,9 +1,36 @@ -#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) +#ifndef USB_CH32_USBHS_REG_H +#define USB_CH32_USBHS_REG_H + +#if CFG_TUSB_MCU == OPT_MCU_CH32V307 #include -#elif (CFG_TUSB_MCU == OPT_MCU_CH32F20X) +#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X #include #endif diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 413fe92c9..dafe4414e 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -1,9 +1,35 @@ +/* + * 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" // Note: CH32 can have both USB FS and HS, only use this driver if CFG_TUD_MAX_SPEED is full speed #if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBFS) && (CFG_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED) -#include #include "device/dcd.h" #include "ch32_usbfs_reg.h" @@ -17,301 +43,303 @@ /* private data */ struct usb_xfer { - bool valid; - uint8_t *buffer; - size_t len; - size_t processed_len; - size_t max_size; + 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; + 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; + 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); - } + 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; - } + 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; + // 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; + 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; + // 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; + // 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]; + 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); + 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); + (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; - } + 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_IN: + update_in(rhport, ep, false); + break; - case PID_SETUP: - data.ep0_tog = true; - dcd_edpt_clear_stall(rhport, tu_edpt_addr(0, TUSB_DIR_IN)); // setup clears stall - dcd_edpt_clear_stall(rhport, tu_edpt_addr(0, TUSB_DIR_OUT)); - 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; + case PID_SETUP: + // setup clears stall + EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK; 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; + 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) rhport; + NVIC_EnableIRQ(USBHD_IRQn); } void dcd_int_disable(uint8_t rhport) { - (void) rhport; - NVIC_DisableIRQ(USBHD_IRQn); + (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) dev_addr; + dcd_edpt_xfer(rhport, 0x80, NULL, 0); // zlp status response } void dcd_remote_wakeup(uint8_t rhport) { - (void) rhport; - // TODO optional + (void) rhport; + // TODO optional } void dcd_connect(uint8_t rhport) { - (void) rhport; - USBOTG_FS->BASE_CTRL |= USBFS_CTRL_DEV_PUEN; + (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) rhport; + USBOTG_FS->BASE_CTRL &= ~USBFS_CTRL_DEV_PUEN; } -void dcd_sof_enable(uint8_t rhport, bool en) -{ +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; +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); +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); + 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; - } + 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; + } + return true; } void dcd_edpt_close_all(uint8_t rhport) { - (void) rhport; - // TODO optional + (void) rhport; + // TODO optional } void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - (void) ep_addr; - // TODO optional + (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); +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); + 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; + 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; - } + (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 { - 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; - } + 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; - } + (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 // CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_CH32V20X) +#endif From 3b144be37fc3e146e68f4182bf18a1b460afeba6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 May 2024 18:05:45 +0700 Subject: [PATCH 25/48] try fixing codeql --- examples/device/msc_dual_lun/src/msc_disk_dual.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index 81f1d3346..b44b77c6c 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -300,10 +300,8 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE -// - READ10 and WRITE10 has their own callbacks +// - READ10 and WRITE10 has their own callbacks (MUST not be handled here) int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { - // read10 & write10 has their own callback and MUST not be handled here - void const* response = NULL; int32_t resplen = 0; @@ -316,8 +314,7 @@ int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, u tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // negative means error -> tinyusb could stall and/or response with failed status - resplen = -1; - break; + return -1; } // return resplen must not larger than bufsize From 10b1e38404c044345e9ea0f3e5c678af94eb0f0a Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 20 May 2024 18:30:38 +0700 Subject: [PATCH 26/48] revert unrelated changes to video_device.c --- src/class/video/video_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index 974289b69..4218835aa 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -609,7 +609,7 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * tusb_desc_cs_video_fmt_t const *fmt = _find_desc_format(tu_desc_next(vs), end, fmtnum); tusb_desc_cs_video_frm_t const *frm = _find_desc_frame(tu_desc_next(fmt), end, frmnum); - uint_fast32_t interval, interval_ms = 0; + uint_fast32_t interval, interval_ms; switch (request) { case VIDEO_REQUEST_GET_MAX: { uint_fast32_t min_interval, max_interval; From c2cfb71dce4d514ff79ec98af46984b543c6f49e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 May 2024 12:11:08 +0700 Subject: [PATCH 27/48] circle ci remove deps caching to reduce storage credit --- .circleci/config.yml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2d4532aee..5cbe3a171 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,30 +44,10 @@ commands: family: type: string steps: - - run: - name: Make deps cache key - command: | - python tools/get_deps.py --print > deps_key - - restore_cache: - name: Restore Dependencies Cache - key: deps-{{ checksum "deps_key" }} - paths: - - lib/CMSIS_5 - - lib/FreeRTOS-Kernel - - lib/lwip - - tools/uf2 - run: name: Get Dependencies command: | python tools/get_deps.py << parameters.family >> - - save_cache: - name: Save Dependencies Cache - key: deps-{{ checksum "deps_key" }} - paths: - - lib/CMSIS_5 - - lib/FreeRTOS-Kernel - - lib/lwip - - tools/uf2 jobs: arm-clang: From 4e24ec5e5d19f47748a13d5d4849a56c4ff7ba87 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 May 2024 12:49:57 +0700 Subject: [PATCH 28/48] circle ci skip cache for toolchain action skip cache for toolchain url hosted by github --- .circleci/config.yml | 26 +++++++++---------- .../setup_toolchain/download/action.yml | 3 ++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5cbe3a171..7b36bed7c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,14 +8,14 @@ commands: toolchain_url: type: string steps: - - run: - name: Make toolchain cache key - command: echo "<< parameters.toolchain >>-<< parameters.toolchain_url>>" > toolchain_key - - restore_cache: - name: Restore Toolchain Cache - key: deps-{{ checksum "toolchain_key" }} - paths: - - ~/cache/<< parameters.toolchain >> +# - run: +# name: Make toolchain cache key +# command: echo "<< parameters.toolchain >>-<< parameters.toolchain_url>>" > toolchain_key +# - restore_cache: +# name: Restore Toolchain Cache +# key: deps-{{ checksum "toolchain_key" }} +# paths: +# - ~/cache/<< parameters.toolchain >> - run: name: Install Toolchain command: | @@ -25,11 +25,11 @@ commands: wget << parameters.toolchain_url>> -O toolchain.tar.gz tar -C ~/cache/<< parameters.toolchain >> -xaf toolchain.tar.gz fi - - save_cache: - name: Save Toolchain Cache - key: deps-{{ checksum "toolchain_key" }} - paths: - - ~/cache/<< parameters.toolchain >> +# - save_cache: +# name: Save Toolchain Cache +# key: deps-{{ checksum "toolchain_key" }} +# paths: +# - ~/cache/<< parameters.toolchain >> - run: name: Setup build environment command: | diff --git a/.github/actions/setup_toolchain/download/action.yml b/.github/actions/setup_toolchain/download/action.yml index 0b35bddb1..2af456ef8 100644 --- a/.github/actions/setup_toolchain/download/action.yml +++ b/.github/actions/setup_toolchain/download/action.yml @@ -12,6 +12,7 @@ runs: using: "composite" steps: - name: Cache Toolchain + if: ${{ !startsWith(inputs.toolchain_url, 'https://github.com') }} uses: actions/cache@v4 id: cache-toolchain-download with: @@ -22,7 +23,7 @@ runs: if: steps.cache-toolchain-download.outputs.cache-hit != 'true' run: | mkdir -p ~/cache/${{ inputs.toolchain }} - wget --progress=dot:mega ${{ inputs.toolchain_url }} -O toolchain.tar.gz + wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.tar.gz tar -C ~/cache/${{ inputs.toolchain }} -xaf toolchain.tar.gz shell: bash From 1d7aeb3fb6b53e8b71e7aecc8e99af425f87d174 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 May 2024 13:25:15 +0700 Subject: [PATCH 29/48] try to update cache for esp-idf --- .../setup_toolchain/espressif/action.yml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/actions/setup_toolchain/espressif/action.yml b/.github/actions/setup_toolchain/espressif/action.yml index 494b7910e..46da02911 100644 --- a/.github/actions/setup_toolchain/espressif/action.yml +++ b/.github/actions/setup_toolchain/espressif/action.yml @@ -11,32 +11,31 @@ inputs: runs: using: "composite" steps: - - id: set-docker-image + - name: Set DOCKER_ESP_IDF run: | - DOCKER_IMAGE=$HOME/cache/${{ inputs.toolchain }}/docker_image.tar - echo "DOCKER_IMAGE=$DOCKER_IMAGE" >> $GITHUB_ENV - echo "DOCKER_IMAGE=$DOCKER_IMAGE" >> $GITHUB_OUTPUT + DOCKER_ESP_IDF=$HOME/cache/${{ inputs.toolchain }}/docker_image.tar + echo "DOCKER_ESP_IDF=$DOCKER_ESP_IDF" >> $GITHUB_ENV shell: bash - name: Cache Docker Image uses: actions/cache@v4 id: cache-toolchain-espressif with: - path: ${{ steps.set-docker-image.outputs.DOCKER_IMAGE }} + path: ${{ env.DOCKER_ESP_IDF }} key: ${{ inputs.toolchain }}-${{ inputs.toolchain_url }} - name: Pull and Save Docker Image if: steps.cache-toolchain-espressif.outputs.cache-hit != 'true' run: | docker pull espressif/idf:${{ inputs.toolchain_url }} - mkdir -p ~/cache/${{ inputs.toolchain }} - docker save -o $DOCKER_IMAGE espressif/idf:${{ inputs.toolchain_url }} - du -sh $DOCKER_IMAGE + mkdir -p $(dirname $DOCKER_ESP_IDF) + docker save -o $DOCKER_ESP_IDF espressif/idf:${{ inputs.toolchain_url }} + du -sh $DOCKER_ESP_IDF shell: bash - name: Load Docker Image if: steps.cache-toolchain-espressif.outputs.cache-hit == 'true' run: | - du -sh $DOCKER_IMAGE - docker load --input $DOCKER_IMAGE + du -sh $DOCKER_ESP_IDF + docker load --input $DOCKER_ESP_IDF shell: bash From 869e5e950c545459788cb67d9063f3489f5c5e54 Mon Sep 17 00:00:00 2001 From: dkrasutski Date: Sat, 30 Dec 2023 03:04:43 +0200 Subject: [PATCH 30/48] bugfix(ch32-hs-dcd): fix ch32 DATAx managment and long packet transmission --- src/portable/wch/ch32_usbhs_reg.h | 21 +- src/portable/wch/dcd_ch32_usbhs.c | 379 +++++++++++++++--------------- 2 files changed, 194 insertions(+), 206 deletions(-) diff --git a/src/portable/wch/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h index a3a41bb6a..7428285a5 100644 --- a/src/portable/wch/ch32_usbhs_reg.h +++ b/src/portable/wch/ch32_usbhs_reg.h @@ -99,12 +99,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) @@ -367,10 +371,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_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 9a12fc97f..0313c0a69 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 @@ -33,32 +34,99 @@ #include "device/dcd.h" // Max number of bi-directional endpoints including EP0 -#define EP_MAX 16 +#define EP_MAX 16 +#define CH32_USBHS_EP0_MAX_SIZE (64) 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; + bool is_last_packet; } 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_data_in_out_buffer[CH32_USBHS_EP0_MAX_SIZE]; -volatile uint8_t USBHS_Dev_Endp0_Tog = 0x01; +static void ep_set_response_and_toggle(uint8_t ep_addr, ep_response_list_t response_type) { + uint8_t const ep_num = tu_edpt_number(ep_addr); + if (ep_addr & TUSB_DIR_IN_MASK) { + 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; + } + } + } + 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_addr, xfer_ctl_t *xfer) { + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); + + if (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_data_in_out_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; + } + } 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); + + 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_addr, USBHS_EP_R_RES_ACK); +} void dcd_init(uint8_t rhport) { (void)rhport; @@ -80,29 +148,23 @@ void dcd_init(uint8_t rhport) { 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->UEP0_MAX_LEN = 64; - - USBHSD->UEP0_DMA = (uint32_t)EP0_DatabufHD; - - USBHSD->UEP0_TX_LEN = 0; - USBHSD->UEP0_TX_CTRL = USBHS_EP_T_RES_NAK; - USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK; - - for (int ep = 1; ep < EP_MAX; ep++) { + 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; - EP_RX_MAX_LEN(ep) = 512; + EP_RX_MAX_LEN(ep) = 0; } + USBHSD->UEP0_DMA = (uint32_t)ep0_data_in_out_buffer; + USBHSD->UEP0_MAX_LEN = CH32_USBHS_EP0_MAX_SIZE; + xfer_status[0][TUSB_DIR_OUT].max_size = CH32_USBHS_EP0_MAX_SIZE; + xfer_status[0][TUSB_DIR_IN].max_size = CH32_USBHS_EP0_MAX_SIZE; + USBHSD->DEV_AD = 0; USBHSD->CONTROL |= USBHS_DEV_PU_EN; } @@ -121,6 +183,16 @@ void dcd_int_disable(uint8_t rhport) { void dcd_edpt_close_all(uint8_t 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) { @@ -130,9 +202,8 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { dcd_edpt_xfer(rhport, 0x80, NULL, 0); } -void dcd_remote_wakeup(uint8_t rhport) -{ - (void) rhport; +void dcd_remote_wakeup(uint8_t rhport) { + (void)rhport; } void dcd_sof_enable(uint8_t rhport, bool en) @@ -154,246 +225,164 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *req 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); + uint8_t const ep_num = tu_edpt_number(desc_edpt->bEndpointAddress); + tusb_dir_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT(epnum < EP_MAX); + TU_ASSERT(ep_num < EP_MAX); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + if (ep_num == 0) { + return true; + } + + xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, 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; + bool 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 (is_iso == true) { + USBHSD->ENDP_TYPE |= (USBHS_EP0_R_TYP << ep_num); } + EP_RX_MAX_LEN(ep_num) = xfer->max_size; + } else { + USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); + if (is_iso == true) { + USBHSD->ENDP_TYPE |= (USBHS_EP0_T_TYP << ep_num); + } + 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; } return true; } -int usbd_ep_close(const uint8_t ep) { - (void)ep; +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; - return 0; + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); + + 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); + } } + 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); + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); - 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; - } + if (dir == TUSB_DIR_OUT) { + EP_RX_CTRL(ep_num) = USBHS_EP_R_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; - } + 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; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_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 { - } + if (dir == TUSB_DIR_OUT) { + EP_RX_CTRL(ep_num) = USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK; } 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; - } + EP_TX_CTRL(ep_num) = USBHS_EP_T_AUTOTOG | USBHS_EP_R_RES_NAK; } } 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); + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, 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; + xfer->is_last_packet = false; - // uint16_t num_packets = (total_bytes / xfer->max_size); - uint16_t short_packet_size = total_bytes % (xfer->max_size + 1); + xfer_data_packet(ep_addr, xfer); - // Zero-size packet is special case. - if (short_packet_size == 0 || (total_bytes == 0)) { - xfer->short_packet = true; - } - - 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); - - 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; - - 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); - - 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; } - -static void receive_packet(xfer_ctl_t *xfer, uint16_t xfer_size) { - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - 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; - } - - if (to_recv_size) { - } - - xfer->queued_len += xfer_size; - - // 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); -} - void dcd_int_handler(uint8_t rhport) { (void)rhport; - uint32_t end_num, rx_token; - uint8_t intflag = 0; + uint8_t int_flag = USBHSD->INT_FG; + uint8_t int_status = USBHSD->INT_ST; - intflag = USBHSD->INT_FG; + if (int_flag & USBHS_TRANSFER_FLAG) { - if (intflag & USBHS_TRANSFER_FLAG) { + uint8_t ep_num = int_status & MASK_UIS_ENDP; + uint8_t rx_token = int_status & MASK_UIS_TOKEN; - end_num = (USBHSD->INT_ST) & MASK_UIS_ENDP; - rx_token = (((USBHSD->INT_ST) & MASK_UIS_TOKEN) >> 4) & 0x03; + uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; - uint8_t endp = end_num | (rx_token == PID_IN ? TUSB_DIR_IN_MASK : 0); + xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); - 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) { + if (rx_token == USBHS_TOKEN_PID_OUT) { uint16_t rx_len = USBHSD->RX_LEN; - receive_packet(xfer, rx_len); - - if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - - dcd_event_xfer_complete(0, endp, xfer->queued_len, XFER_RESULT_SUCCESS, true); + if (ep_num == 0) { + memcpy(&xfer->buffer[xfer->queued_len], ep0_data_in_out_buffer, rx_len); } - if (end_num == 0) { - USBHSD->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0; + xfer->queued_len += rx_len; + if (rx_len < xfer->max_size) { + xfer->is_last_packet = true; } - } 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); + } else if (rx_token == USBHS_TOKEN_PID_IN) { + // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet + // Common processing below + } - EP_TX_CTRL(end_num) = (EP_TX_CTRL(end_num) & ~(USBHS_EP_T_RES_MASK)) | USBHS_EP_T_RES_NAK; - - if (end_num == 0) { - } - } else { - dcd_edpt_xfer(0, endp, xfer->buffer + xfer->queued_len, xfer->total_len - xfer->queued_len); - } + if (xfer->is_last_packet == true) { + ep_set_response_and_toggle(ep_addr, 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_addr, xfer); } 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); + } else if (int_flag & USBHS_SETUP_FLAG) { + ep_set_response_and_toggle(0x80, EP_RESPONSE_NAK); + ep_set_response_and_toggle(0x00, EP_RESPONSE_NAK); + dcd_event_setup_received(0, ep0_data_in_out_buffer, true); USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */ - } else if (intflag & USBHS_DETECT_FLAG) { - USBHS_Dev_Endp0_Tog = 1; - - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; + } else if (int_flag & USBHS_DETECT_FLAG) { 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; + 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) { + } else if (int_flag & USBHS_SUSPEND_FLAG) { dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SUSPEND }; dcd_event_handler(&event, true); From 3e604d1d5498cace44179026fe3ca017920704fe Mon Sep 17 00:00:00 2001 From: Denis Krasutski Date: Thu, 4 Jan 2024 12:22:11 +0200 Subject: [PATCH 31/48] fix(ch32, iso): fix iso IN transfers for CH32 --- src/portable/wch/dcd_ch32_usbhs.c | 76 +++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 0313c0a69..42b15bf06 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -43,6 +43,7 @@ typedef struct { uint16_t queued_len; uint16_t max_size; bool is_last_packet; + bool is_iso; } xfer_ctl_t; typedef enum { @@ -77,7 +78,11 @@ static void ep_set_response_and_toggle(uint8_t ep_addr, ep_response_list_t respo } } } - EP_TX_CTRL(ep_num) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | response; + 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) { @@ -112,6 +117,10 @@ static void xfer_data_packet(uint8_t ep_addr, xfer_ctl_t *xfer) { 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); @@ -146,7 +155,7 @@ void dcd_init(uint8_t rhport) { #endif USBHSD->INT_EN = 0; - USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_DETECT_EN | USBHS_SUSPEND_EN; + USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_DETECT_EN | USBHS_SUSPEND_EN | USBHS_ISO_ACT_EN; USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN; USBHSD->ENDP_TYPE = 0x00; @@ -244,18 +253,20 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) { xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, dir); xfer->max_size = tu_edpt_packet_size(desc_edpt); - bool is_iso = (desc_edpt->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); + 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 (is_iso == true) { + if (xfer->is_iso == true) { USBHSD->ENDP_TYPE |= (USBHS_EP0_R_TYP << ep_num); } EP_RX_MAX_LEN(ep_num) = xfer->max_size; } else { - USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); - if (is_iso == true) { + if (xfer->is_iso == true) { USBHSD->ENDP_TYPE |= (USBHS_EP0_T_TYP << ep_num); + } else { + /* Enable all types except Isochronous to avoid ISO_ACT interrupt generation */ + USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); } 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; @@ -275,7 +286,7 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { 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 + } 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); @@ -332,30 +343,24 @@ void dcd_int_handler(uint8_t rhport) { uint8_t int_flag = USBHSD->INT_FG; uint8_t int_status = USBHSD->INT_ST; - if (int_flag & USBHS_TRANSFER_FLAG) { - + if (int_flag & USBHS_ISO_ACT_FLAG) { uint8_t ep_num = int_status & MASK_UIS_ENDP; uint8_t rx_token = int_status & MASK_UIS_TOKEN; - uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; - xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); if (rx_token == USBHS_TOKEN_PID_OUT) { uint16_t rx_len = USBHSD->RX_LEN; - if (ep_num == 0) { - memcpy(&xfer->buffer[xfer->queued_len], ep0_data_in_out_buffer, rx_len); - } - xfer->queued_len += rx_len; if (rx_len < xfer->max_size) { xfer->is_last_packet = true; } - } else if (rx_token == USBHS_TOKEN_PID_IN) { - // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet - // Common processing below + if (xfer->is_last_packet == true) { + /* Disable EP to avoid ISO_ACT interrupt generation */ + USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num); + } } if (xfer->is_last_packet == true) { @@ -366,6 +371,41 @@ void dcd_int_handler(uint8_t rhport) { xfer_data_packet(ep_addr, xfer); } + USBHSD->INT_FG = USBHS_ISO_ACT_FLAG; /* Clear flag */ + } else if (int_flag & USBHS_TRANSFER_FLAG) { + + uint8_t ep_num = int_status & MASK_UIS_ENDP; + uint8_t rx_token = int_status & MASK_UIS_TOKEN; + uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; + xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); + + if (xfer->is_iso == false) { + if (rx_token == USBHS_TOKEN_PID_OUT) { + uint16_t rx_len = USBHSD->RX_LEN; + + if (ep_num == 0) { + memcpy(&xfer->buffer[xfer->queued_len], ep0_data_in_out_buffer, rx_len); + } + + xfer->queued_len += rx_len; + if (rx_len < xfer->max_size) { + xfer->is_last_packet = true; + } + + } else if (rx_token == USBHS_TOKEN_PID_IN) { + // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet + // Common processing below + } + + if (xfer->is_last_packet == true) { + ep_set_response_and_toggle(ep_addr, 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_addr, xfer); + } + } + USBHSD->INT_FG = USBHS_TRANSFER_FLAG; /* Clear flag */ } else if (int_flag & USBHS_SETUP_FLAG) { ep_set_response_and_toggle(0x80, EP_RESPONSE_NAK); From 4bd72da5cdce4b3ab8f5a9960234a97934672f1c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 May 2024 15:41:59 +0700 Subject: [PATCH 32/48] use CFG_TUD_ENDPOINT0_SIZE, rename ep0_data_in_out_buffer to simply ep0_buffer reformat indent to 2 spaces --- src/portable/wch/dcd_ch32_usbhs.c | 576 +++++++++++++++--------------- 1 file changed, 286 insertions(+), 290 deletions(-) diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 42b15bf06..dbcf19a7b 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -34,21 +34,20 @@ #include "device/dcd.h" // Max number of bi-directional endpoints including EP0 -#define EP_MAX 16 -#define CH32_USBHS_EP0_MAX_SIZE (64) +#define EP_MAX 16 typedef struct { - uint8_t *buffer; - uint16_t total_len; - uint16_t queued_len; - uint16_t max_size; - bool is_last_packet; - bool is_iso; + 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_ACK, + EP_RESPONSE_NAK, } ep_response_list_t; #define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] @@ -63,371 +62,368 @@ static xfer_ctl_t xfer_status[EP_MAX][2]; #define EP_RX_DMA_ADDR(ep) *(volatile uint32_t *)((volatile uint32_t *)&(USBHSD->UEP1_RX_DMA) + (ep - 1)) /* Endpoint Buffer */ -TU_ATTR_ALIGNED(4) static uint8_t ep0_data_in_out_buffer[CH32_USBHS_EP0_MAX_SIZE]; +TU_ATTR_ALIGNED(4) static uint8_t ep0_buffer[CFG_TUD_ENDPOINT0_SIZE]; static void ep_set_response_and_toggle(uint8_t ep_addr, ep_response_list_t response_type) { - uint8_t const ep_num = tu_edpt_number(ep_addr); - if (ep_addr & TUSB_DIR_IN_MASK) { - 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; + uint8_t const ep_num = tu_edpt_number(ep_addr); + if (ep_addr & TUSB_DIR_IN_MASK) { + 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) = (EP_TX_CTRL(ep_num) & ~(USBHS_EP_T_RES_MASK)) | response; + EP_TX_CTRL(ep_num) ^= USBHS_EP_T_TOG_1; } - } 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; + } } + 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_addr, xfer_ctl_t *xfer) { - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); +static void xfer_data_packet(uint8_t ep_addr, xfer_ctl_t* xfer) { + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); - if (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 (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_data_in_out_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); - - 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; - } + 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_set_response_and_toggle(ep_addr, USBHS_EP_R_RES_ACK); + + 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); + + 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_addr, 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 | USBHS_ISO_ACT_EN; + USBHSD->INT_EN = 0; + USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_DETECT_EN | USBHS_SUSPEND_EN | USBHS_ISO_ACT_EN; - USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN; - USBHSD->ENDP_TYPE = 0x00; - USBHSD->BUF_MODE = 0x00; + USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN; + USBHSD->ENDP_TYPE = 0x00; + USBHSD->BUF_MODE = 0x00; - 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; + 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; - EP_RX_MAX_LEN(ep) = 0; - } + EP_RX_MAX_LEN(ep) = 0; + } - USBHSD->UEP0_DMA = (uint32_t)ep0_data_in_out_buffer; - USBHSD->UEP0_MAX_LEN = CH32_USBHS_EP0_MAX_SIZE; - xfer_status[0][TUSB_DIR_OUT].max_size = CH32_USBHS_EP0_MAX_SIZE; - xfer_status[0][TUSB_DIR_IN].max_size = CH32_USBHS_EP0_MAX_SIZE; + 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; - 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; + 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; - } + EP_RX_MAX_LEN(ep) = 0; + } - USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN; + 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)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 | USBHS_EP_T_TOG_0; - EP_RX_CTRL(0) = USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0; + 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; +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { + (void) rhport; - uint8_t const ep_num = tu_edpt_number(desc_edpt->bEndpointAddress); - tusb_dir_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + uint8_t const ep_num = tu_edpt_number(desc_edpt->bEndpointAddress); + tusb_dir_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - TU_ASSERT(ep_num < EP_MAX); - - if (ep_num == 0) { - return true; - } - - xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, dir); - xfer->max_size = tu_edpt_packet_size(desc_edpt); - - 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); - } - 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 { - /* Enable all types except Isochronous to avoid ISO_ACT interrupt generation */ - USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); - } - 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; - } + TU_ASSERT(ep_num < EP_MAX); + if (ep_num == 0) { return true; + } + + xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, dir); + xfer->max_size = tu_edpt_packet_size(desc_edpt); + + 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); + } + 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 { + /* Enable all types except Isochronous to avoid ISO_ACT interrupt generation */ + USBHSD->ENDP_CONFIG |= (USBHS_EP0_T_EN << ep_num); + } + 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; + } + + return true; } void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void)rhport; + (void) rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); - 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); - } + 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); + } } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - (void)rhport; + (void) rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); - 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; - } + 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; + (void) rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); - 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 (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; + } } -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); +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); - 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_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_data_packet(ep_addr, xfer); + xfer_data_packet(ep_addr, xfer); - return true; + return true; } void dcd_int_handler(uint8_t rhport) { - (void)rhport; + (void) rhport; - uint8_t int_flag = USBHSD->INT_FG; - uint8_t int_status = USBHSD->INT_ST; + uint8_t int_flag = USBHSD->INT_FG; + uint8_t int_status = USBHSD->INT_ST; - if (int_flag & USBHS_ISO_ACT_FLAG) { - uint8_t ep_num = int_status & MASK_UIS_ENDP; - uint8_t rx_token = int_status & MASK_UIS_TOKEN; - uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; - xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); + if (int_flag & USBHS_ISO_ACT_FLAG) { + uint8_t ep_num = int_status & MASK_UIS_ENDP; + uint8_t rx_token = int_status & MASK_UIS_TOKEN; + uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; + xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); - if (rx_token == USBHS_TOKEN_PID_OUT) { - uint16_t rx_len = USBHSD->RX_LEN; + if (rx_token == USBHS_TOKEN_PID_OUT) { + uint16_t rx_len = USBHSD->RX_LEN; - xfer->queued_len += rx_len; - if (rx_len < xfer->max_size) { - xfer->is_last_packet = true; - } - } else if (rx_token == USBHS_TOKEN_PID_IN) { - if (xfer->is_last_packet == true) { - /* Disable EP to avoid ISO_ACT interrupt generation */ - USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num); - } - } - - if (xfer->is_last_packet == true) { - ep_set_response_and_toggle(ep_addr, 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_addr, xfer); - } - - USBHSD->INT_FG = USBHS_ISO_ACT_FLAG; /* Clear flag */ - } else if (int_flag & USBHS_TRANSFER_FLAG) { - - uint8_t ep_num = int_status & MASK_UIS_ENDP; - uint8_t rx_token = int_status & MASK_UIS_TOKEN; - uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; - xfer_ctl_t *xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); - - if (xfer->is_iso == false) { - if (rx_token == USBHS_TOKEN_PID_OUT) { - uint16_t rx_len = USBHSD->RX_LEN; - - if (ep_num == 0) { - memcpy(&xfer->buffer[xfer->queued_len], ep0_data_in_out_buffer, rx_len); - } - - xfer->queued_len += rx_len; - if (rx_len < xfer->max_size) { - xfer->is_last_packet = true; - } - - } else if (rx_token == USBHS_TOKEN_PID_IN) { - // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet - // Common processing below - } - - if (xfer->is_last_packet == true) { - ep_set_response_and_toggle(ep_addr, 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_addr, xfer); - } - } - - USBHSD->INT_FG = USBHS_TRANSFER_FLAG; /* Clear flag */ - } else if (int_flag & USBHS_SETUP_FLAG) { - ep_set_response_and_toggle(0x80, EP_RESPONSE_NAK); - ep_set_response_and_toggle(0x00, EP_RESPONSE_NAK); - dcd_event_setup_received(0, ep0_data_in_out_buffer, true); - - USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */ - } else if (int_flag & USBHS_DETECT_FLAG) { - - dcd_event_bus_reset(0, TUSB_SPEED_HIGH, true); - - 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 (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 */ + xfer->queued_len += rx_len; + if (rx_len < xfer->max_size) { + xfer->is_last_packet = true; + } + } else if (rx_token == USBHS_TOKEN_PID_IN) { + if (xfer->is_last_packet == true) { + /* Disable EP to avoid ISO_ACT interrupt generation */ + USBHSD->ENDP_CONFIG &= ~(USBHS_EP0_T_EN << ep_num); + } } + + if (xfer->is_last_packet == true) { + ep_set_response_and_toggle(ep_addr, 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_addr, xfer); + } + + USBHSD->INT_FG = USBHS_ISO_ACT_FLAG; /* Clear flag */ + } else if (int_flag & USBHS_TRANSFER_FLAG) { + + uint8_t ep_num = int_status & MASK_UIS_ENDP; + uint8_t rx_token = int_status & MASK_UIS_TOKEN; + uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; + xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); + + if (xfer->is_iso == false) { + if (rx_token == USBHS_TOKEN_PID_OUT) { + uint16_t rx_len = USBHSD->RX_LEN; + + if (ep_num == 0) { + memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, rx_len); + } + + xfer->queued_len += rx_len; + if (rx_len < xfer->max_size) { + xfer->is_last_packet = true; + } + + } else if (rx_token == USBHS_TOKEN_PID_IN) { + // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet + // Common processing below + } + + if (xfer->is_last_packet == true) { + ep_set_response_and_toggle(ep_addr, 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_addr, xfer); + } + } + + USBHSD->INT_FG = USBHS_TRANSFER_FLAG; /* Clear flag */ + } else if (int_flag & USBHS_SETUP_FLAG) { + ep_set_response_and_toggle(0x80, EP_RESPONSE_NAK); + ep_set_response_and_toggle(0x00, EP_RESPONSE_NAK); + dcd_event_setup_received(0, ep0_buffer, true); + + USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */ + } else if (int_flag & USBHS_DETECT_FLAG) { + + dcd_event_bus_reset(0, TUSB_SPEED_HIGH, true); + + 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 (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 */ + } } #endif From 953e3bd6344812c910f714952b4dda47ffe53107 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 May 2024 16:08:27 +0700 Subject: [PATCH 33/48] - minor update to ep_set_response_and_toggle/xfer_data_packet - merge USBHS_ISO_ACT_FLAG, USBHS_TRANSFER_FLAG handler since they are similar - improve uart output - add note for link speed in bus reset --- hw/bsp/ch32v307/debug_uart.c | 2 +- hw/bsp/ch32v307/family.c | 7 +- src/portable/wch/ch32_usbhs_reg.h | 5 +- src/portable/wch/dcd_ch32_usbhs.c | 104 +++++++++++++----------------- 4 files changed, 54 insertions(+), 64 deletions(-) diff --git a/hw/bsp/ch32v307/debug_uart.c b/hw/bsp/ch32v307/debug_uart.c index db3551ca7..fbabeeadc 100644 --- a/hw/bsp/ch32v307/debug_uart.c +++ b/hw/bsp/ch32v307/debug_uart.c @@ -28,7 +28,7 @@ #include -#define UART_RINGBUFFER_SIZE_TX 64 +#define UART_RINGBUFFER_SIZE_TX 128 #define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1) static char tx_buf[UART_RINGBUFFER_SIZE_TX]; diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index fe37ea8e3..94578b416 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -72,7 +72,7 @@ void board_init(void) { SysTick_Config(SystemCoreClock / 1000); #endif - usart_printf_init(115200); + usart_printf_init(CFG_BOARD_UART_BAUDRATE); #if CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED // Use Highspeed USB @@ -150,10 +150,11 @@ int board_uart_read(uint8_t* buf, int len) { int board_uart_write(void const* buf, int len) { int txsize = len; + const char* bufc = (const char*) buf; while (txsize--) { - uart_write(*(uint8_t const*) buf); - buf++; + uart_write(*bufc++); } + uart_sync(); return len; } diff --git a/src/portable/wch/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h index 7428285a5..1c2ed9893 100644 --- a/src/portable/wch/ch32_usbhs_reg.h +++ b/src/portable/wch/ch32_usbhs_reg.h @@ -74,7 +74,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 diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index dbcf19a7b..8879db98d 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -64,9 +64,8 @@ static xfer_ctl_t xfer_status[EP_MAX][2]; /* Endpoint Buffer */ TU_ATTR_ALIGNED(4) static uint8_t ep0_buffer[CFG_TUD_ENDPOINT0_SIZE]; -static void ep_set_response_and_toggle(uint8_t ep_addr, ep_response_list_t response_type) { - uint8_t const ep_num = tu_edpt_number(ep_addr); - if (ep_addr & TUSB_DIR_IN_MASK) { +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) { @@ -97,11 +96,8 @@ static void ep_set_response_and_toggle(uint8_t ep_addr, ep_response_list_t respo } } -static void xfer_data_packet(uint8_t ep_addr, xfer_ctl_t* xfer) { - uint8_t const ep_num = tu_edpt_number(ep_addr); - tusb_dir_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { +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); @@ -133,7 +129,7 @@ static void xfer_data_packet(uint8_t ep_addr, xfer_ctl_t* xfer) { EP_RX_MAX_LEN(ep_num) = max_possible_rx_size; } } - ep_set_response_and_toggle(ep_addr, USBHS_EP_R_RES_ACK); + ep_set_response_and_toggle(ep_num, ep_dir, USBHS_EP_R_RES_ACK); } void dcd_init(uint8_t rhport) { @@ -154,7 +150,7 @@ void dcd_init(uint8_t rhport) { #endif USBHSD->INT_EN = 0; - USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_DETECT_EN | USBHS_SUSPEND_EN | USBHS_ISO_ACT_EN; + USBHSD->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_BUS_RST_EN | USBHS_SUSPEND_EN | USBHS_ISO_ACT_EN; USBHSD->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN; USBHSD->ENDP_TYPE = 0x00; @@ -328,7 +324,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer->queued_len = 0; xfer->is_last_packet = false; - xfer_data_packet(ep_addr, xfer); + xfer_data_packet(ep_num, dir, xfer); return true; } @@ -339,77 +335,67 @@ void dcd_int_handler(uint8_t rhport) { uint8_t int_flag = USBHSD->INT_FG; uint8_t int_status = USBHSD->INT_ST; - if (int_flag & USBHS_ISO_ACT_FLAG) { - uint8_t ep_num = int_status & MASK_UIS_ENDP; - uint8_t rx_token = int_status & MASK_UIS_TOKEN; - uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; - xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); + if (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)) { + uint8_t const rx_token = int_status & MASK_UIS_TOKEN; + uint8_t const ep_num = int_status & MASK_UIS_ENDP; + tusb_dir_t const ep_dir = (rx_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); if (rx_token == USBHS_TOKEN_PID_OUT) { uint16_t rx_len = USBHSD->RX_LEN; + if (ep_num == 0) { + memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, rx_len); + } + xfer->queued_len += rx_len; if (rx_len < xfer->max_size) { xfer->is_last_packet = true; } } else if (rx_token == USBHS_TOKEN_PID_IN) { - if (xfer->is_last_packet == true) { + 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 } } if (xfer->is_last_packet == true) { - ep_set_response_and_toggle(ep_addr, EP_RESPONSE_NAK); + 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_addr, xfer); + xfer_data_packet(ep_num, ep_dir, xfer); } - USBHSD->INT_FG = USBHS_ISO_ACT_FLAG; /* Clear flag */ - } else if (int_flag & USBHS_TRANSFER_FLAG) { - - uint8_t ep_num = int_status & MASK_UIS_ENDP; - uint8_t rx_token = int_status & MASK_UIS_TOKEN; - uint8_t ep_addr = (rx_token == USBHS_TOKEN_PID_IN) ? (TUSB_DIR_IN_MASK | ep_num) : ep_num; - xfer_ctl_t* xfer = XFER_CTL_BASE(ep_num, tu_edpt_dir(ep_addr)); - - if (xfer->is_iso == false) { - if (rx_token == USBHS_TOKEN_PID_OUT) { - uint16_t rx_len = USBHSD->RX_LEN; - - if (ep_num == 0) { - memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, rx_len); - } - - xfer->queued_len += rx_len; - if (rx_len < xfer->max_size) { - xfer->is_last_packet = true; - } - - } else if (rx_token == USBHS_TOKEN_PID_IN) { - // Do nothing, no need to update xfer->is_last_packet, it is already updated in xfer_data_packet - // Common processing below - } - - if (xfer->is_last_packet == true) { - ep_set_response_and_toggle(ep_addr, 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_addr, xfer); - } - } - - USBHSD->INT_FG = USBHS_TRANSFER_FLAG; /* Clear flag */ + 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(0x80, EP_RESPONSE_NAK); - ep_set_response_and_toggle(0x00, EP_RESPONSE_NAK); + 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); USBHSD->INT_FG = USBHS_SETUP_FLAG; /* Clear flag */ - } else if (int_flag & USBHS_DETECT_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); @@ -417,7 +403,7 @@ void dcd_int_handler(uint8_t rhport) { 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 */ + 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); From 4a5b190a2209958b875416641b67a4076f14c9e2 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 21 May 2024 18:34:25 +0700 Subject: [PATCH 34/48] re-add sof event --- src/portable/wch/ch32_usbhs_reg.h | 5 +++ src/portable/wch/dcd_ch32_usbhs.c | 60 +++++++++++++++++-------------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/portable/wch/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h index 1c2ed9893..130e4f223 100644 --- a/src/portable/wch/ch32_usbhs_reg.h +++ b/src/portable/wch/ch32_usbhs_reg.h @@ -63,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) diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 8879db98d..b36c7dd50 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -336,38 +336,44 @@ void dcd_int_handler(uint8_t rhport) { uint8_t int_status = USBHSD->INT_ST; if (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)) { - uint8_t const rx_token = int_status & MASK_UIS_TOKEN; - uint8_t const ep_num = int_status & MASK_UIS_ENDP; - tusb_dir_t const ep_dir = (rx_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); + uint8_t const token = int_status & MASK_UIS_TOKEN; - if (rx_token == USBHS_TOKEN_PID_OUT) { - uint16_t rx_len = USBHSD->RX_LEN; + 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); - if (ep_num == 0) { - memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, rx_len); + if (token == USBHS_TOKEN_PID_OUT) { + uint16_t rx_len = USBHSD->RX_LEN; + + if (ep_num == 0) { + memcpy(&xfer->buffer[xfer->queued_len], ep0_buffer, rx_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 + } } - xfer->queued_len += rx_len; - if (rx_len < xfer->max_size) { - xfer->is_last_packet = 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); } - } else if (rx_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 - } - } - - 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 = (int_flag & (USBHS_ISO_ACT_FLAG | USBHS_TRANSFER_FLAG)); /* Clear flag */ From 927015baae9b2d265d1daaa0fc2ffca1aa4f9e91 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 May 2024 11:38:44 +0700 Subject: [PATCH 35/48] wch usbfs/usbhs need to specify which driver to use. for v307 default to highspeed --- hw/bsp/ch32v307/family.c | 13 ++++--- hw/bsp/ch32v307/family.cmake | 15 ++++++-- hw/bsp/ch32v307/family.mk | 4 +- src/common/tusb_mcu.h | 52 ++++++++++++++++++++------ src/device/usbd.c | 2 +- src/portable/synopsys/dwc2/dwc2_type.h | 33 ++++++++++++---- src/portable/wch/dcd_ch32_usbfs.c | 3 +- src/portable/wch/dcd_ch32_usbhs.c | 3 +- src/tusb_option.h | 47 +++++++++++++---------- 9 files changed, 115 insertions(+), 57 deletions(-) diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index 94578b416..0846b10a9 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -38,13 +38,13 @@ // TODO maybe having FS as port0, HS as port1 __attribute__((interrupt)) void USBHS_IRQHandler(void) { - #if CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED + #if CFG_TUD_WCH_USBIP_USBHS tud_int_handler(0); #endif } __attribute__((interrupt)) void OTG_FS_IRQHandler(void) { - #if CFG_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED + #if CFG_TUD_WCH_USBIP_USBFS tud_int_handler(0); #endif } @@ -74,15 +74,17 @@ void board_init(void) { usart_printf_init(CFG_BOARD_UART_BAUDRATE); -#if CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED - // Use Highspeed USB +#ifdef CH32V30x_D8C + // v305/v307: Highspeed USB RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY); RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE); RCC_USBHSConfig(RCC_USBPLL_Div2); RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M); RCC_USBHSPHYPLLALIVEcmd(ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE); -#else +#endif + + // Fullspeed USB uint8_t otg_div; switch (SystemCoreClock) { case 48000000: otg_div = RCC_OTGFSCLKSource_PLLCLK_Div1; break; @@ -92,7 +94,6 @@ void board_init(void) { } RCC_OTGFSCLKConfig(otg_div); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); -#endif GPIO_InitTypeDef GPIO_InitStructure = {0}; diff --git a/hw/bsp/ch32v307/family.cmake b/hw/bsp/ch32v307/family.cmake index fd475c987..af26bfc31 100644 --- a/hw/bsp/ch32v307/family.cmake +++ b/hw/bsp/ch32v307/family.cmake @@ -14,7 +14,7 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TO set(FAMILY_MCUS CH32V307 CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") -# default to highspeed +# default to highspeed, used to select USBFS / USBHS driver if (NOT DEFINED SPEED) set(SPEED high) endif() @@ -52,9 +52,16 @@ function(add_board_target BOARD_TARGET) ${SDK_SRC_DIR}/Peripheral/inc ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=$,OPT_MODE_HIGH_SPEED,OPT_MODE_FULL_SPEED> - ) + if (SPEED STREQUAL high) + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_TUD_WCH_USBIP_USBHS=1 +# BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + ) + else () + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_TUD_WCH_USBIP_USBFS=1 + ) + endif () update_board(${BOARD_TARGET}) diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 2dbe0c46a..30a070a9b 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -26,11 +26,11 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_CH32V307 \ ifeq ($(SPEED),high) - CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED $(info "Using USBHS driver for HighSpeed mode") + CFLAGS += -DCFG_TUD_WCH_USBIP_USBHS=1 else - CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED $(info "Using USBFS driver for FullSpeed mode") + CFLAGS += -DCFG_TUD_WCH_USBIP_USBFS=1 endif LDFLAGS_GCC += \ diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index abfed2835..af11ecb9b 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -402,29 +402,57 @@ #elif TU_CHECK_MCU(OPT_MCU_F1C100S) #define TUP_DCD_ENDPOINT_MAX 4 -//------------- WCH -------------// -#elif TU_CHECK_MCU(OPT_MCU_CH32V307) - // v307 support both FS and HS - #define TUP_USBIP_WCH_USBHS - #define TUP_USBIP_WCH_USBFS - - #define TUP_RHPORT_HIGHSPEED 1 // default to highspeed - #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED ? 16 : 8) - +//--------------------------------------------------------------------+ +// WCH +//--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_CH32F20X) #define TUP_USBIP_WCH_USBHS #define TUP_USBIP_WCH_USBFS - #define TUP_RHPORT_HIGHSPEED 1 // default to highspeed - #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED ? 16 : 8) + #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_DCD_ENDPOINT_MAX 8 + #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_FSDEV) + #define CFG_TUD_WCH_USBIP_FSDEV (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) + #endif + +#elif TU_CHECK_MCU(OPT_MCU_CH32V307) + // v307 support both FS and HS, default to HS + #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) #endif - //--------------------------------------------------------------------+ // External USB controller //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 25d890dc7..9a6afd0d1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -407,7 +407,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)); 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 - * - *

© 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. + * + */ +/**

© Copyright (c) 2019 STMicroelectronics. * All rights reserved.

* * 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/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index dafe4414e..9ed370b40 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -27,8 +27,7 @@ #include "tusb_option.h" -// Note: CH32 can have both USB FS and HS, only use this driver if CFG_TUD_MAX_SPEED is full speed -#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBFS) && (CFG_TUD_MAX_SPEED == OPT_MODE_FULL_SPEED) +#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBFS) && CFG_TUD_WCH_USBIP_USBFS #include "device/dcd.h" #include "ch32_usbfs_reg.h" diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index b36c7dd50..622f9c508 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -27,8 +27,7 @@ #include "tusb_option.h" -// Note: CH32 can have both USB FS and HS, only use this driver if CFG_TUD_MAX_SPEED is high speed -#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && (CFG_TUD_MAX_SPEED == OPT_MODE_HIGH_SPEED) +#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && CFG_TUD_WCH_USBIP_USBHS #include "ch32_usbhs_reg.h" #include "device/dcd.h" diff --git a/src/tusb_option.h b/src/tusb_option.h index 318a4c7bd..d74510b60 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -207,19 +207,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 @@ -233,7 +223,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) @@ -261,7 +268,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) @@ -467,26 +474,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 @@ -496,8 +503,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 */ \ From 4ce439a75a6f7aa995c74e7ac32e70ab8216c771 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 May 2024 13:58:44 +0700 Subject: [PATCH 36/48] add ch32 support for fsdev driver. v20x can select fsdev or usbfs with make/cmake PORT=0/1. default to fsdev --- .../ch32v20x/boards/ch32v203_r0_1v0/board.h | 1 - hw/bsp/ch32v20x/family.c | 147 ++++++--- hw/bsp/ch32v20x/family.cmake | 20 +- hw/bsp/ch32v20x/family.mk | 15 +- hw/bsp/ch32v20x/linker/ch32v20x.ld | 166 +++++++++- src/common/tusb_compiler.h | 1 + src/common/tusb_mcu.h | 5 +- src/device/dcd.h | 7 +- src/device/usbd.c | 23 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 214 ++----------- src/portable/st/stm32_fsdev/fsdev_ch32.h | 232 ++++++++++++++ .../{dcd_stm32_fsdev.h => fsdev_common.h} | 248 +++------------ src/portable/st/stm32_fsdev/fsdev_stm32.h | 292 ++++++++++++++++++ src/tusb_option.h | 9 + 14 files changed, 932 insertions(+), 448 deletions(-) create mode 100644 src/portable/st/stm32_fsdev/fsdev_ch32.h rename src/portable/st/stm32_fsdev/{dcd_stm32_fsdev.h => fsdev_common.h} (58%) create mode 100644 src/portable/st/stm32_fsdev/fsdev_stm32.h diff --git a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h index c8d28d90f..3ed2aef04 100644 --- a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h +++ b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h @@ -8,7 +8,6 @@ extern "C" { #define LED_PORT GPIOA #define LED_PIN GPIO_Pin_15 #define LED_STATE_ON 0 -#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE) #ifdef __cplusplus } diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 247dacde6..a0a8c3f50 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -1,82 +1,153 @@ #include #include "ch32v20x.h" + #include "bsp/board_api.h" #include "board.h" -__attribute__((interrupt)) +/* CH32v203 depending on variants can support 2 USB IPs: FSDEV and USBFS. + * By default, we use FSDEV, but you can explicitly select by define: + * - CFG_TUD_WCH_USBIP_FSDEV + * - CFG_TUD_WCH_USBIP_USBFS + */ + +// USBFS +__attribute__((interrupt)) __attribute__((used)) void USBHD_IRQHandler(void) { - tud_int_handler(0); + #if CFG_TUD_WCH_USBIP_USBFS + tud_int_handler(0); + #endif } +__attribute__((interrupt)) __attribute__((used)) +void USBHDWakeUp_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_USBFS + tud_int_handler(0); + #endif +} + +// USBD (fsdev) +__attribute__((interrupt)) __attribute__((used)) +void USB_LP_CAN1_RX0_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV + tud_int_handler(0); + #endif +} + +__attribute__((interrupt)) __attribute__((used)) +void USB_HP_CAN1_TX_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV + tud_int_handler(0); + #endif + +} + +__attribute__((interrupt)) __attribute__((used)) +void USBWakeUp_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV + tud_int_handler(0); + #endif +} + + #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; __attribute__((interrupt)) void SysTick_Handler(void) { - SysTick->SR = 0; - system_ticks++; + SysTick->SR = 0; + system_ticks++; } uint32_t SysTick_Config(uint32_t ticks) { - NVIC_EnableIRQ(SysTicK_IRQn); - SysTick->CTLR = 0; - SysTick->SR = 0; - SysTick->CNT = 0; - SysTick->CMP = ticks-1; - SysTick->CTLR = 0xF; - return 0; + NVIC_EnableIRQ(SysTicK_IRQn); + SysTick->CTLR = 0; + SysTick->SR = 0; + SysTick->CNT = 0; + SysTick->CMP = ticks - 1; + SysTick->CTLR = 0xF; + return 0; } uint32_t board_millis(void) { - return system_ticks; + return system_ticks; } #endif void board_init(void) { - __disable_irq(); + __disable_irq(); #if CFG_TUSB_OS == OPT_OS_NONE - SysTick_Config(SystemCoreClock / 1000); + SysTick_Config(SystemCoreClock / 1000); #endif - switch (SystemCoreClock) { - case 48000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1); break; - case 96000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2); break; - case 144000000: RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div3); break; - default: TU_ASSERT(0,); break; - } - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); - LED_CLOCK_EN(); - GPIO_InitTypeDef GPIO_InitStructure = { - .GPIO_Pin = LED_PIN, - .GPIO_Mode = GPIO_Mode_Out_OD, - .GPIO_Speed = GPIO_Speed_50MHz, - }; - GPIO_Init(LED_PORT, &GPIO_InitStructure); + uint8_t usb_div; + switch (SystemCoreClock) { + case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break; + case 96000000: usb_div = RCC_USBCLKSource_PLLCLK_Div2; break; + case 144000000: usb_div = RCC_USBCLKSource_PLLCLK_Div3; break; + default: TU_ASSERT(0,); break; + } + RCC_USBCLKConfig(usb_div); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); // FSDEV + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); // USB FS - __enable_irq(); - board_delay(2); + GPIO_InitTypeDef GPIO_InitStructure = { + .GPIO_Pin = LED_PIN, + .GPIO_Mode = GPIO_Mode_Out_OD, + .GPIO_Speed = GPIO_Speed_50MHz, + }; + GPIO_Init(LED_PORT, &GPIO_InitStructure); + + // UART TX is PA9 + RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); + GPIO_InitTypeDef usart_init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }; + GPIO_Init(GPIOA, &usart_init); + + USART_InitTypeDef usart = { + .USART_BaudRate = 115200, + .USART_WordLength = USART_WordLength_8b, + .USART_StopBits = USART_StopBits_1, + .USART_Parity = USART_Parity_No, + .USART_Mode = USART_Mode_Tx, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + }; + USART_Init(USART1, &usart); + USART_Cmd(USART1, ENABLE); + + __enable_irq(); + board_delay(2); + + printf("SystemCoreClock = %ld\r\n", SystemCoreClock); } void board_led_write(bool state) { - GPIO_WriteBit(LED_PORT, LED_PIN, state); + GPIO_WriteBit(LED_PORT, LED_PIN, state); } uint32_t board_button_read(void) { - return false; + return false; } int board_uart_read(uint8_t *buf, int len) { - (void) buf; - (void) len; - return 0; + (void) buf; + (void) len; + return 0; } int board_uart_write(void const *buf, int len) { - (void) buf; - (void) len; - return len; + const char *bufc = (const char *) buf; + for (int i = 0; i < len; i++) { + while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); + USART_SendData(USART1, *bufc++); + } + + return len; } diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index 80b035fc0..3fb1c0e79 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -14,6 +14,11 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TO set(FAMILY_MCUS CH32V20X CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") +# Port0 use FSDev, Port1 use USBFS +if (NOT DEFINED PORT) + set(PORT 0) +endif() + #------------------------------------ # BOARD_TARGET #------------------------------------ @@ -48,9 +53,20 @@ function(add_board_target BOARD_TARGET) ) target_compile_definitions(${BOARD_TARGET} PUBLIC CH32V20x_${MCU_VARIANT} - BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED ) + if (PORT EQUAL 0) + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_TUD_WCH_USBIP_FSDEV=1 + ) + elseif (PORT EQUAL 1) + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_TUD_WCH_USBIP_USBFS=1 + ) + else() + message(FATAL_ERROR "Invalid PORT ${PORT}") + endif() + update_board(${BOARD_TARGET}) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") @@ -99,8 +115,10 @@ function(family_configure_example TARGET RTOS) # Add TinyUSB target and port source family_add_tinyusb(${TARGET} OPT_MCU_CH32V20X ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index 5c8b31a1c..49d4d2feb 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -14,13 +14,23 @@ SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= rv32imac-ilp32 +# Port0 use FSDev, Port1 use USBFS +PORT ?= 0 + CFLAGS += \ -mcmodel=medany \ -ffat-lto-objects \ -flto \ -DCH32V20x_${MCU_VARIANT} \ - -DCFG_TUSB_MCU=OPT_MCU_CH32V20X \ - -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED \ + -DCFG_TUSB_MCU=OPT_MCU_CH32V20X + +ifeq ($(PORT),0) + $(info "Using FSDEV driver") + CFLAGS += -DCFG_TUD_WCH_USBIP_FSDEV=1 +else + $(info "Using USBFS driver") + CFLAGS += -DCFG_TUD_WCH_USBIP_USBFS=1 +endif LDFLAGS_GCC += \ -nostdlib -nostartfiles \ @@ -30,6 +40,7 @@ LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld SRC_C += \ src/portable/wch/dcd_ch32_usbfs.c \ + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ $(SDK_SRC_DIR)/Core/core_riscv.c \ $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_gpio.c \ $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_misc.c \ diff --git a/hw/bsp/ch32v20x/linker/ch32v20x.ld b/hw/bsp/ch32v20x/linker/ch32v20x.ld index 6ee2fa1c7..cd5c8dc17 100644 --- a/hw/bsp/ch32v20x/linker/ch32v20x.ld +++ b/hw/bsp/ch32v20x/linker/ch32v20x.ld @@ -1 +1,165 @@ -/* Define default values if not already defined */ __FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K; __RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K; MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __FLASH_SIZE RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __RAM_SIZE } ENTRY( _start ) __stack_size = 2048; PROVIDE( _stack_size = __stack_size ); SECTIONS { .init : { _sinit = .; . = ALIGN(4); KEEP(*(SORT_NONE(.init))) . = ALIGN(4); _einit = .; } >FLASH AT>FLASH .vector : { *(.vector); . = ALIGN(64); } >FLASH AT>FLASH .text : { . = ALIGN(4); *(.text) *(.text.*) *(.rodata) *(.rodata*) *(.gnu.linkonce.t.*) . = ALIGN(4); } >FLASH AT>FLASH .fini : { KEEP(*(SORT_NONE(.fini))) . = ALIGN(4); } >FLASH AT>FLASH PROVIDE( _etext = . ); PROVIDE( _eitcm = . ); .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } >FLASH AT>FLASH .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); } >FLASH AT>FLASH .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH AT>FLASH .ctors : { /* gcc uses crtbegin.o to find the start of the constructors, so we make sure it is first. Because this is a wildcard, it doesn't matter if the user does not actually link against crtbegin.o; the linker won't look for a file to match a wildcard. The wildcard also means that it doesn't matter which directory crtbegin.o is in. */ KEEP (*crtbegin.o(.ctors)) KEEP (*crtbegin?.o(.ctors)) /* We don't want to include the .ctor section from the crtend.o file until after the sorted ctors. The .ctor section from the crtend file contains the end of ctors marker and it must be last */ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) } >FLASH AT>FLASH .dtors : { KEEP (*crtbegin.o(.dtors)) KEEP (*crtbegin?.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) } >FLASH AT>FLASH .dalign : { . = ALIGN(4); PROVIDE(_data_vma = .); } >RAM AT>FLASH .dlalign : { . = ALIGN(4); PROVIDE(_data_lma = .); } >FLASH AT>FLASH .data : { *(.gnu.linkonce.r.*) *(.data .data.*) *(.gnu.linkonce.d.*) . = ALIGN(8); PROVIDE( __global_pointer$ = . + 0x800 ); *(.sdata .sdata.*) *(.sdata2.*) *(.gnu.linkonce.s.*) . = ALIGN(8); *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) . = ALIGN(4); PROVIDE( _edata = .); } >RAM AT>FLASH .bss : { . = ALIGN(4); PROVIDE( _sbss = .); *(.sbss*) *(.gnu.linkonce.sb.*) *(.bss*) *(.gnu.linkonce.b.*) *(COMMON*) . = ALIGN(4); PROVIDE( _ebss = .); } >RAM AT>FLASH PROVIDE( _end = _ebss); PROVIDE( end = . ); .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : { PROVIDE( _heap_end = . ); . = ALIGN(4); PROVIDE(_susrstack = . ); . = . + __stack_size; PROVIDE( _eusrstack = .); } >RAM } +/* Define default values if not already defined */ +__FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K; +__RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K; + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __FLASH_SIZE + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __RAM_SIZE +} + +ENTRY( _start ) + +__stack_size = 2048; + +PROVIDE( _stack_size = __stack_size ); + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + + .vector : + { + *(.vector); + . = ALIGN(64); + } >FLASH AT>FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dalign : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + } >RAM AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.sdata2.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = ALIGN(4); + PROVIDE(_susrstack = . ); + . = . + __stack_size; + PROVIDE( _eusrstack = .); + } >RAM + +} 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 af11ecb9b..c66996c4f 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -423,7 +423,6 @@ #elif TU_CHECK_MCU(OPT_MCU_CH32V20X) // v20x support both FSDEV (USBD) and USBFS, default to FSDEV #define TUP_USBIP_WCH_USBFS - #define TUP_DCD_ENDPOINT_MAX 8 #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_CH32 @@ -431,10 +430,12 @@ #define CFG_TUD_WCH_USBIP_USBFS 0 #endif - #if !defined(CFG_TUD_WCH_FSDEV) + #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) // v307 support both FS and HS, default to HS #define TUP_USBIP_WCH_USBHS diff --git a/src/device/dcd.h b/src/device/dcd.h index 9447d6d9d..2d3dafa4c 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -39,9 +39,6 @@ // Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUD_ENDPPOINT_MAX - #define CFG_TUD_ENDPPOINT_MAX TUP_DCD_ENDPOINT_MAX -#endif //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES @@ -149,10 +146,10 @@ 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); diff --git a/src/device/usbd.c b/src/device/usbd.c index 9a6afd0d1..88183fad0 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 //--------------------------------------------------------------------+ @@ -379,19 +387,16 @@ 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) -{ +bool tud_sof_cb_enable(bool en) { usbd_sof_enable(_usbd_rhport, SOF_CONSUMER_USER, en); return true; } 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. + * + */ +/**

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * 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 + +#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X + #include +#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 similarity index 58% rename from src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h rename to 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) * - * 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. + * 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: * - * 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 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. */ -// 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/tusb_option.h b/src/tusb_option.h index d74510b60..674c05e54 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -374,6 +374,15 @@ #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 From 937b2eac3605e33887beb3604db72a0069b4fa93 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 May 2024 14:00:02 +0700 Subject: [PATCH 37/48] change default clock to 144mhz --- .idea/cmake.xml | 5 +++-- hw/bsp/ch32v20x/system_ch32v20x.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index d96b46853..1502831cd 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -128,12 +128,13 @@ - + - + + \ No newline at end of file diff --git a/hw/bsp/ch32v20x/system_ch32v20x.c b/hw/bsp/ch32v20x/system_ch32v20x.c index 588f3165a..bdc0d498f 100644 --- a/hw/bsp/ch32v20x/system_ch32v20x.c +++ b/hw/bsp/ch32v20x/system_ch32v20x.c @@ -22,9 +22,9 @@ //#define SYSCLK_FREQ_48MHz_HSE 48000000 //#define SYSCLK_FREQ_56MHz_HSE 56000000 //#define SYSCLK_FREQ_72MHz_HSE 72000000 -#define SYSCLK_FREQ_96MHz_HSE 96000000 +// #define SYSCLK_FREQ_96MHz_HSE 96000000 //#define SYSCLK_FREQ_120MHz_HSE 120000000 -//#define SYSCLK_FREQ_144MHz_HSE 144000000 +#define SYSCLK_FREQ_144MHz_HSE 144000000 //#define SYSCLK_FREQ_HSI HSI_VALUE //#define SYSCLK_FREQ_48MHz_HSI 48000000 //#define SYSCLK_FREQ_56MHz_HSI 56000000 From daffb24111c03e3630edf6496ff5bb65c2cf8c28 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 May 2024 14:06:25 +0700 Subject: [PATCH 38/48] minor clean up --- .idea/cmake.xml | 4 ++-- src/device/dcd.h | 11 +++-------- src/device/usbd.h | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 1502831cd..24d4eafe9 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -128,13 +128,13 @@ - - + + \ No newline at end of file diff --git a/src/device/dcd.h b/src/device/dcd.h index 2d3dafa4c..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" @@ -35,11 +35,6 @@ extern "C" { #endif -//--------------------------------------------------------------------+ -// Configuration -//--------------------------------------------------------------------+ - - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ @@ -251,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.h b/src/device/usbd.h index cba94fdae..e676006ab 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 From 2c880012f7904cc19c73e4e246214b75e61a44df Mon Sep 17 00:00:00 2001 From: Rbb666 Date: Thu, 23 May 2024 15:48:21 +0800 Subject: [PATCH 39/48] [osal]Add usb-device and host macro controls. --- lib/rt-thread/SConscript | 2 ++ lib/rt-thread/tusb_config.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/rt-thread/SConscript b/lib/rt-thread/SConscript index 482f6d7b2..34399fd45 100644 --- a/lib/rt-thread/SConscript +++ b/lib/rt-thread/SConscript @@ -34,6 +34,8 @@ if GetDepend(["PKG_TINYUSB_DEVICE_ENABLE"]): src += ["../../src/class/cdc/cdc_device.c"] if GetDepend(["PKG_TINYUSB_DEVICE_MSC"]): src += ["../../src/class/msc/msc_device.c", "port/msc_device_port.c"] + if GetDepend(["PKG_TINYUSB_DEVICE_HID"]): + src += ["../../src/class/hid/hid_device.c"] # for host stack if GetDepend(["PKG_TINYUSB_HOST_ENABLE"]): diff --git a/lib/rt-thread/tusb_config.h b/lib/rt-thread/tusb_config.h index b3c3bf43f..11dc21983 100644 --- a/lib/rt-thread/tusb_config.h +++ b/lib/rt-thread/tusb_config.h @@ -152,12 +152,12 @@ extern "C" { #define CFG_TUH_ENABLED (0) #endif -#if (PKG_TINYUSB_HOST_PORT == 0) +#if (PKG_TINYUSB_HOST_PORT == 0) && defined(PKG_TINYUSB_HOST_ENABLE) #undef CFG_TUSB_RHPORT0_MODE #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | PKG_TINYUSB_HOST_PORT_SPEED) #endif -#if (PKG_TINYUSB_HOST_PORT == 1) +#if (PKG_TINYUSB_HOST_PORT == 1) && defined(PKG_TINYUSB_HOST_ENABLE) #undef CFG_TUSB_RHPORT1_MODE #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_HOST | PKG_TINYUSB_HOST_PORT_SPEED) #endif From afbb07b472924c3d60431f0949b08a0aff0c02a5 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 May 2024 17:36:17 +0700 Subject: [PATCH 40/48] test README.rst --- README.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index dbe75adc8..043095887 100644 --- a/README.rst +++ b/README.rst @@ -122,10 +122,9 @@ Following CPUs are supported, check out `Supported Devices`_ for comprehensive l | GigaDevice | GD32VF103 | +--------------+------------------------------------------------------------+ | Infineon | XMC4500 | -+--------------+-----+------------------------------------------------------+ -| MicroChip | SAM | D11, D21, D51, E5x, G55, L2x, E7x, S7x, V7x | -| +-----+------------------------------------------------------+ -| | PIC | 24, 32mm, 32mk, 32mx, 32mz, dsPIC33 | ++--------------+------------------------------------------------------------+ +| MicroChip | - SAM: D11, D21, D51, E5x, G55, L2x, E7x, S7x, V7x | +| | - PIC: 24, 32mm, 32mk, 32mx, 32mz, dsPIC33 | +--------------+-----+------------------------------------------------------+ | Mind Montion | mm32 | +--------------+------------------------------------------------------------+ From 3175aaa0eb32e334b3b55824e93b647da3b69a44 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 May 2024 20:17:53 +0700 Subject: [PATCH 41/48] increase version as pre-releases, still need more clean up before actual relesae --- README.rst | 38 ++++++++++--------- docs/info/changelog.rst | 66 +++++++++++++++++++++++++++++++++ docs/reference/dependencies.rst | 32 ++++++++-------- hw/bsp/ch32v20x/family.c | 2 - src/tusb_option.h | 8 ++-- tools/gen_doc.py | 4 +- tools/make_release.py | 3 ++ 7 files changed, 112 insertions(+), 41 deletions(-) diff --git a/README.rst b/README.rst index 043095887..b5f9fc149 100644 --- a/README.rst +++ b/README.rst @@ -123,40 +123,44 @@ Following CPUs are supported, check out `Supported Devices`_ for comprehensive l +--------------+------------------------------------------------------------+ | Infineon | XMC4500 | +--------------+------------------------------------------------------------+ -| MicroChip | - SAM: D11, D21, D51, E5x, G55, L2x, E7x, S7x, V7x | -| | - PIC: 24, 32mm, 32mk, 32mx, 32mz, dsPIC33 | -+--------------+-----+------------------------------------------------------+ +| | SAM: D11, D21, D51, E5x, G55, L2x, E7x, S7x, V7x | +| MicroChip | | +| | PIC: 24, 32mm, 32mk, 32mx, 32mz, dsPIC33 | ++--------------+------------------------------------------------------------+ | Mind Montion | mm32 | +--------------+------------------------------------------------------------+ | NordicSemi | nRF52833, nRF52840, nRF5340 | +--------------+------------------------------------------------------------+ | Nuvoton | NUC 120, 121, 125, 126, 505 | -+--------------+---------+--------------------------------------------------+ -| NXP | iMXRT | RT10xx, RT11xx | -| +---------+--------------------------------------------------+ -| | Kinetis | KL, K32L2 | -| +---------+--------------------------------------------------+ -| | LPC | 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 | -| +---------+--------------------------------------------------+ -| | MCX | A15, N9 | -+--------------+---------+--------------------------------------------------+ ++--------------+------------------------------------------------------------+ +| NXP | iMXRT: RT10xx, RT11xx | +| | | +| | Kinetis: KL, K32L2 | +| | | +| | LPC: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 | +| | | +| | MCX: A15, N9 | ++--------------+------------------------------------------------------------+ | Raspberry Pi | RP2040 | +--------------+-----+------------------------------------------------------+ -| Renesas | RX | 63N, 65N, 72N | -+--------------+-----+------------------------------------------------------+ -| | RA | 4M1, 4M3, 6M1, 6M5 | +| Renesas | RA: 4M1, 4M3, 6M1, 6M5 | +| | | +| | RX: 63N, 65N, 72N | +--------------+-----+------------------------------------------------------+ | Silabs | EFM32GG12 | +--------------+------------------------------------------------------------+ | Sony | CXD56 | +--------------+------------------------------------------------------------+ -| ST STM32 | F0, F1, F2, F3, F4, F7, H7, G0, G4, L0, L1, L4, L4+ U5, WB | +| ST STM32 | F0, F1, F2, F3, F4, F7, H5, H7, G0, G4, L0, L1, L4, L4+, | +| | U5, WB | +--------------+------------------------------------------------------------+ | TI | MSP430, MSP432E4, TM4C123 | +--------------+------------------------------------------------------------+ | ValentyUSB | eptri | +--------------+------------------------------------------------------------+ -| WCH | CH32F20x, CH32V20x, CH32V307 | +| WCH | CH32F: F20x | +| | | +| | CH32V: V20x, V307 | +--------------+------------------------------------------------------------+ License diff --git a/docs/info/changelog.rst b/docs/info/changelog.rst index b359ebb44..f7ccb39b9 100644 --- a/docs/info/changelog.rst +++ b/docs/info/changelog.rst @@ -2,6 +2,72 @@ Changelog ********* +0.17.0 (WIP) +============ + +General +------- + +- Improved continuous integration: build both cmake and make. Make use of circleci to build arm-clang + + +Controller Driver (DCD & HCD) +----------------------------- + +- WCH CH32 + + - Added support for USB OTG/FS and FSDev Driver. Update CH32V307 to allow manual select FS or HS driver. + - Fixed various bugs in CH32v307 usbhs driver: endpoint handling and data transfer management. + +- Fixed race conditions and other bugs in dcd_nrf5x and other drivers. +- Implemented hcd abort transfer for Max3421 and rp2040 +- Added DWC2 Test Mode support. +- stm32 fsdev: ISO EP buffer allocation improvements, implement dcd_edpt_close_all() +- Added support for STM32G4 and STM32U5 microcontrollers. + +Device Stack +------------ + +- Added tud_deinit() to deinitialize TinyUSB device stack. +- Added support for generic SOF callback. + +- Audio + + - Add audio_test_freertos & audio_4_channel_mic_freertos + - Improved support for Audio Class 2.0 (UAC2) with various bug fixes. + +- HID + + - Added missing key codes for keypad + - Added HID Lighting and Illumination functionality + +- Vendor: Added empty transfers for tud_vendor_n_write() +- MSC: Added support for SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL + +- CDC + + - Add option to make CDC TX buffer persistent + - Add missing capability bit for CDC ACM serial break support + +- Net + + - Rewrite of NCM device driver + - removed obsolete tud_network_link_state_cb() + +- Enhanced CDC class with better handling of large data transmissions. +- Fixed issues in the HID class for more reliable device enumeration. +- Video Added support for USB Video Class (UVC) with MJPEG. +- USBTMC Added notification support + +Host Stack +---------- + +- Added tuh_deinit() to deinitialize TinyUSB host stack. +- Added support for new USB mass storage class APIs. +- Enhanced stability of CDC-ACM devices during enumeration. +- Improved error handling and retry mechanisms for unstable devices. +- Added support for multiple interfaces in UVC. + 0.16.0 ====== diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index 3a98594ff..fd895519e 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -4,21 +4,21 @@ Dependencies MCU low-level peripheral driver and external libraries for building TinyUSB examples -======================================== ============================================================== ======================================== ======================================================================================================================================================================================================= +======================================== ============================================================== ======================================== ========================================================================================================================================================================================================================================================================================================================== Local Path Repo Commit Required by -======================================== ============================================================== ======================================== ======================================================================================================================================================================================================= +======================================== ============================================================== ======================================== ========================================================================================================================================================================================================================================================================================================================== hw/mcu/allwinner https://github.com/hathach/allwinner_driver.git 8e5e89e8e132c0fd90e72d5422e5d3d68232b756 fc100s hw/mcu/bridgetek/ft9xx/ft90x-sdk https://github.com/BRTSG-FOSS/ft90x-sdk.git 91060164afe239fcb394122e8bf9eb24d3194eb1 brtmm90x hw/mcu/broadcom https://github.com/adafruit/broadcom-peripherals.git 08370086080759ed54ac1136d62d2ad24c6fa267 broadcom_32bit broadcom_64bit hw/mcu/gd/nuclei-sdk https://github.com/Nuclei-Software/nuclei-sdk.git 7eb7bfa9ea4fbeacfafe1d5f77d5a0e6ed3922e7 gd32vf103 hw/mcu/infineon/mtb-xmclib-cat3 https://github.com/Infineon/mtb-xmclib-cat3.git daf5500d03cba23e68c2f241c30af79cd9d63880 xmc4000 -hw/mcu/microchip https://github.com/hathach/microchip_driver.git 9e8b37e307d8404033bb881623a113931e1edf27 sam3x samd11 samd21 samd51 same5x same7x saml2x samg -hw/mcu/mindmotion/mm32sdk https://github.com/hathach/mm32sdk.git 0b79559eb411149d36e073c1635c620e576308d4 mm32 -hw/mcu/nordic/nrfx https://github.com/NordicSemiconductor/nrfx.git 2527e3c8449cfd38aee41598e8af8492f410ed15 nrf +hw/mcu/microchip https://github.com/hathach/microchip_driver.git 9e8b37e307d8404033bb881623a113931e1edf27 sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg +hw/mcu/mindmotion/mm32sdk https://github.com/hathach/mm32sdk.git b93e856211060ae825216c6a1d6aa347ec758843 mm32 +hw/mcu/nordic/nrfx https://github.com/NordicSemiconductor/nrfx.git 7c47cc0a56ce44658e6da2458e86cd8783ccc4a2 nrf hw/mcu/nuvoton https://github.com/majbthrd/nuc_driver.git 2204191ec76283371419fbcec207da02e1bc22fa nuc -hw/mcu/nxp/lpcopen https://github.com/hathach/nxp_lpcopen.git 84e0bd3e43910aaf71eefd62075cf57495418312 lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 -hw/mcu/nxp/mcux-sdk https://github.com/hathach/mcux-sdk.git 950819b7de9b32f92c3edf396bc5ffb8d66e7009 kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt -hw/mcu/raspberry_pi/Pico-PIO-USB https://github.com/sekigon-gonnoc/Pico-PIO-USB.git d00a10a8c425d0d40f81b87169102944b01f3bb3 rp2040 +hw/mcu/nxp/lpcopen https://github.com/hathach/nxp_lpcopen.git 04bfe7a5f6ee74a89a28ad618d3367dcfcfb7d83 lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 +hw/mcu/nxp/mcux-sdk https://github.com/hathach/mcux-sdk.git 144f1eb7ea8c06512e12f12b27383601c0272410 kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt +hw/mcu/raspberry_pi/Pico-PIO-USB https://github.com/sekigon-gonnoc/Pico-PIO-USB.git 0f747aaa0c16f750bdfa2ba37ec25d6c8e1bc117 rp2040 hw/mcu/renesas/fsp https://github.com/renesas/fsp.git d52e5a6a59b7c638da860c2bb309b6e78e752ff8 ra hw/mcu/renesas/rx https://github.com/kkitayam/rx_device.git 706b4e0cf485605c32351e2f90f5698267996023 rx hw/mcu/silabs/cmsis-dfp-efm32gg12b https://github.com/cmsis-packs/cmsis-dfp-efm32gg12b.git f1c31b7887669cb230b3ea63f9b56769078960bc efm32 @@ -28,15 +28,16 @@ hw/mcu/st/cmsis_device_f1 https://github.com/STMicroelectronics/ hw/mcu/st/cmsis_device_f2 https://github.com/STMicroelectronics/cmsis_device_f2.git 182fcb3681ce116816feb41b7764f1b019ce796f stm32f2 hw/mcu/st/cmsis_device_f3 https://github.com/STMicroelectronics/cmsis_device_f3.git 5e4ee5ed7a7b6c85176bb70a9fd3c72d6eb99f1b stm32f3 hw/mcu/st/cmsis_device_f4 https://github.com/STMicroelectronics/cmsis_device_f4.git 2615e866fa48fe1ff1af9e31c348813f2b19e7ec stm32f4 -hw/mcu/st/cmsis_device_f7 https://github.com/STMicroelectronics/cmsis_device_f7.git fc676ef1ad177eb874eaa06444d3d75395fc51f4 stm32f7 +hw/mcu/st/cmsis_device_f7 https://github.com/STMicroelectronics/cmsis_device_f7.git 25b0463439303b7a38f0d27b161f7d2f3c096e79 stm32f7 hw/mcu/st/cmsis_device_g0 https://github.com/STMicroelectronics/cmsis_device_g0.git 3a23e1224417f3f2d00300ecd620495e363f2094 stm32g0 hw/mcu/st/cmsis_device_g4 https://github.com/STMicroelectronics/cmsis_device_g4.git ce822adb1dc552b3aedd13621edbc7fdae124878 stm32g4 +hw/mcu/st/cmsis_device_h5 https://github.com/STMicroelectronics/cmsis_device_h5.git cd2d1d579743de57b88ccaf61a968b9c05848ffc stm32h5 hw/mcu/st/cmsis_device_h7 https://github.com/STMicroelectronics/cmsis_device_h7.git 60dc2c913203dc8629dc233d4384dcc41c91e77f stm32h7 -hw/mcu/st/cmsis_device_l0 https://github.com/STMicroelectronics/cmsis_device_l0.git 06748ca1f93827befdb8b794402320d94d02004f stm32l0 +hw/mcu/st/cmsis_device_l0 https://github.com/STMicroelectronics/cmsis_device_l0.git 69cd5999fd40ae6e546d4905b21635c6ca1bcb92 stm32l0 hw/mcu/st/cmsis_device_l1 https://github.com/STMicroelectronics/cmsis_device_l1.git 7f16ec0a1c4c063f84160b4cc6bf88ad554a823e stm32l1 hw/mcu/st/cmsis_device_l4 https://github.com/STMicroelectronics/cmsis_device_l4.git 6ca7312fa6a5a460b5a5a63d66da527fdd8359a6 stm32l4 hw/mcu/st/cmsis_device_l5 https://github.com/STMicroelectronics/cmsis_device_l5.git d922865fc0326a102c26211c44b8e42f52c1e53d stm32l5 -hw/mcu/st/cmsis_device_u5 https://github.com/STMicroelectronics/cmsis_device_u5.git 06d7edade7167b0eafdd550bf77cfc4fa98eae2e stm32u5 +hw/mcu/st/cmsis_device_u5 https://github.com/STMicroelectronics/cmsis_device_u5.git 5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309 stm32u5 hw/mcu/st/cmsis_device_wb https://github.com/STMicroelectronics/cmsis_device_wb.git 9c5d1920dd9fabbe2548e10561d63db829bb744f stm32wb hw/mcu/st/stm32f0xx_hal_driver https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git 0e95cd88657030f640a11e690a8a5186c7712ea5 stm32f0 hw/mcu/st/stm32f1xx_hal_driver https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git 1dd9d3662fb7eb2a7f7d3bc0a4c1dc7537915a29 stm32f1 @@ -46,6 +47,7 @@ hw/mcu/st/stm32f4xx_hal_driver https://github.com/STMicroelectronics/ hw/mcu/st/stm32f7xx_hal_driver https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git f7ffdf6bf72110e58b42c632b0a051df5997e4ee stm32f7 hw/mcu/st/stm32g0xx_hal_driver https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git e911b12c7f67084d7f6b76157a4c0d4e2ec3779c stm32g0 hw/mcu/st/stm32g4xx_hal_driver https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git 8b4518417706d42eef5c14e56a650005abf478a8 stm32g4 +hw/mcu/st/stm32h5xx_hal_driver https://github.com/STMicroelectronics/stm32h5xx_hal_driver.git 2cf77de584196d619cec1b4586c3b9e2820a254e stm32h5 hw/mcu/st/stm32h7xx_hal_driver https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git d8461b980b59b1625207d8c4f2ce0a9c2a7a3b04 stm32h7 hw/mcu/st/stm32l0xx_hal_driver https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git fbdacaf6f8c82a4e1eb9bd74ba650b491e97e17b stm32l0 hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git 44efc446fa69ed8344e7fd966e68ed11043b35d9 stm32l1 @@ -53,13 +55,13 @@ hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/ hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 675c32a75df37f39d50d61f51cb0dcf53f07e1cb stm32l5 hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 4d93097a67928e9377e655ddd14622adc31b9770 stm32u5 hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git 2c5f06638be516c1b772f768456ba637f077bac8 stm32wb -hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c123 +hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.git 77c4095087e5ed2c548ec9058e655d0b8757663b ch32f20x hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git de6d68c654340d7f27b00cebbfc9aa2740a1abc2 ch32v20x hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 17761f5cf9dbbf2dcf665b7c04934188add20082 ch32v307 -lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 20285262657d1b482d132d20d755c8c330d55c1f imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2xstm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb -lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git 4ff01a7a4a51f53b44496aefee1e3c0071b7b173 all +lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 20285262657d1b482d132d20d755c8c330d55c1f imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2xlpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wbsam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samgtm4c +lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git cc0e0707c0c748713485b870bb980852b210877f all lib/lwip https://github.com/lwip-tcpip/lwip.git 159e31b689577dbf69cf0683bbaffbd71fa5ee10 all lib/sct_neopixel https://github.com/gsteiert/sct_neopixel.git e73e04ca63495672d955f9268e003cffe168fcd8 lpc55 tools/uf2 https://github.com/microsoft/uf2.git 19615407727073e36d81bf239c52108ba92e7660 all -======================================== ============================================================== ======================================== ======================================================================================================================================================================================================= +======================================== ============================================================== ======================================== ========================================================================================================================================================================================================================================================================================================================== diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index a0a8c3f50..be654e543 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -124,8 +124,6 @@ void board_init(void) { __enable_irq(); board_delay(2); - - printf("SystemCoreClock = %ld\r\n", SystemCoreClock); } void board_led_write(bool state) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 674c05e54..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) //--------------------------------------------------------------------+ diff --git a/tools/gen_doc.py b/tools/gen_doc.py index c63294588..668c77ef6 100644 --- a/tools/gen_doc.py +++ b/tools/gen_doc.py @@ -7,9 +7,9 @@ from get_deps import deps_all TOP = Path(__file__).parent.parent.resolve() -########################################### +# ----------------------------------------- # Dependencies -########################################### +# ----------------------------------------- def gen_deps_doc(): deps_rst = Path(TOP) / "docs/reference/dependencies.rst" diff --git a/tools/make_release.py b/tools/make_release.py index 256ca8f21..126e07292 100644 --- a/tools/make_release.py +++ b/tools/make_release.py @@ -1,4 +1,5 @@ import re +import gen_doc version = '0.16.0' @@ -46,4 +47,6 @@ with open(f_library_json, 'w') as f: # docs/info/changelog.rst ################### +gen_doc.gen_deps_doc() + print("Update docs/info/changelog.rst") From a2e5ea1882f130ee22eedbb68296b4b5ce561f77 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 15 May 2024 21:23:39 +1000 Subject: [PATCH 42/48] chipidea/mimxrt: Add support for dcd_sof_enable(). --- src/portable/chipidea/ci_hs/dcd_ci_hs.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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); } } From e229270a1c3d542cdf9924313f585dd43c607de8 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 16 May 2024 14:12:22 +1000 Subject: [PATCH 43/48] microchip samd: Add support for dcd_sof_enable(). --- src/portable/microchip/samd/dcd_samd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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. From 160cd79fdb9fee70894c4d9bfe908af38b88dc46 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 16 May 2024 16:05:36 +1000 Subject: [PATCH 44/48] nrf5x: Add support for dcd_sof_enable(). --- src/portable/nordic/nrf5x/dcd_nrf5x.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index bb07063d2..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; /*------------------------------------------------------------------*/ @@ -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) { From 087fe79e2cd8558f62442d530ef23d249112d389 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Sun, 19 May 2024 13:43:30 +1000 Subject: [PATCH 45/48] renesas: Add support for dcd_sof_enable(). --- src/portable/renesas/rusb2/dcd_rusb2.c | 40 ++++++++++++++------------ 1 file changed, 21 insertions(+), 19 deletions(-) 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; } From 8f0459c89e61dfb50a2da73dd6935f6e317b50ac Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 18 May 2024 23:09:13 +0200 Subject: [PATCH 46/48] Fix frame count in tud_sof_cb(). --- src/device/usbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 25d890dc7..0fb0aed4e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1189,7 +1189,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; From a9745c9818da85a0b31ef04c556530a3bef18ec1 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 18 May 2024 23:10:55 +0200 Subject: [PATCH 47/48] Fix tud_sof_cb_enable() return type. --- src/device/usbd.c | 3 +-- src/device/usbd.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 0fb0aed4e..922faf112 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -390,10 +390,9 @@ bool tud_connect(void) { 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; } //--------------------------------------------------------------------+ diff --git a/src/device/usbd.h b/src/device/usbd.h index cba94fdae..e439dd961 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -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 From 8767d1ab7d2a7d3870d9bc6b6624b5f580f63e9d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 May 2024 15:19:59 +0700 Subject: [PATCH 48/48] fix xtensa_api.h include --- src/portable/espressif/esp32sx/dcd_esp32sx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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"