diff options
| author | hathach <[email protected]> | 2024-05-24 13:58:44 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2024-05-24 13:58:44 +0700 |
| commit | 4ce439a75a6f7aa995c74e7ac32e70ab8216c771 (patch) | |
| tree | a1bed9351159f79f09de0c9a906c0dfb915686c5 /src | |
| parent | 927015baae9b2d265d1daaa0fc2ffca1aa4f9e91 (diff) | |
add ch32 support for fsdev driver. v20x can select fsdev or usbfs with make/cmake PORT=0/1. default to fsdev
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/tusb_compiler.h | 1 | ||||
| -rw-r--r-- | src/common/tusb_mcu.h | 5 | ||||
| -rw-r--r-- | src/device/dcd.h | 7 | ||||
| -rw-r--r-- | src/device/usbd.c | 23 | ||||
| -rw-r--r-- | src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 214 | ||||
| -rw-r--r-- | src/portable/st/stm32_fsdev/fsdev_ch32.h | 232 | ||||
| -rw-r--r-- | src/portable/st/stm32_fsdev/fsdev_common.h (renamed from src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h) | 248 | ||||
| -rw-r--r-- | src/portable/st/stm32_fsdev/fsdev_stm32.h | 292 | ||||
| -rw-r--r-- | src/tusb_option.h | 9 |
9 files changed, 626 insertions, 405 deletions
diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 0d5570b1c..ce5566ffe 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -128,6 +128,7 @@ #define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name))) #define TU_ATTR_PACKED __attribute__ ((packed)) #define TU_ATTR_WEAK __attribute__ ((weak)) + // #define TU_ATTR_WEAK_ALIAS(f) __attribute__ ((weak, alias(#f)) #ifndef TU_ATTR_ALWAYS_INLINE // allow to override for debug #define TU_ATTR_ALWAYS_INLINE __attribute__ ((always_inline)) #endif diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 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. + * + */ +/** <h2><center>© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.</center></h2> + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + */ + +#ifndef TUSB_FSDEV_CH32_H +#define TUSB_FSDEV_CH32_H + +#include "common/tusb_compiler.h" + +#if CFG_TUSB_MCU == OPT_MCU_CH32V20X + #include <ch32v20x.h> + +#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X + #include <ch32f20x.h> +#endif + +#define FSDEV_PMA_SIZE (512u) + +// volatile 32-bit aligned +#define _va32 volatile TU_ATTR_ALIGNED(4) + +typedef struct { + _va32 uint16_t EP0R; // 00: USB Endpoint 0 register + _va32 uint16_t EP1R; // 04: USB Endpoint 1 register + _va32 uint16_t EP2R; // 08: USB Endpoint 2 register + _va32 uint16_t EP3R; // 0C: USB Endpoint 3 register + _va32 uint16_t EP4R; // 10: USB Endpoint 4 register + _va32 uint16_t EP5R; // 14: USB Endpoint 5 register + _va32 uint16_t EP6R; // 18: USB Endpoint 6 register + _va32 uint16_t EP7R; // 1C: USB Endpoint 7 register + _va32 uint16_t RESERVED7[16]; // Reserved + _va32 uint16_t CNTR; // 40: Control register + _va32 uint16_t ISTR; // 44: Interrupt status register + _va32 uint16_t FNR; // 48: Frame number register + _va32 uint16_t DADDR; // 4C: Device address register + _va32 uint16_t BTABLE; // 50: Buffer Table address register +} USB_TypeDef; + +TU_VERIFY_STATIC(sizeof(USB_TypeDef) == 0x54, "Size is not correct"); +TU_VERIFY_STATIC(offsetof(USB_TypeDef, CNTR) == 0x40, "Wrong offset"); + +#define USB_BASE (APB1PERIPH_BASE + 0x00005C00UL) /*!< USB_IP Peripheral Registers base address */ +#define USB_PMAADDR (APB1PERIPH_BASE + 0x00006000UL) /*!< USB_IP Packet Memory Area base address */ +#define USB ((USB_TypeDef *)USB_BASE) + +/******************************************************************************/ +/* */ +/* USB Device General registers */ +/* */ +/******************************************************************************/ +#define USB_CNTR (USB_BASE + 0x40U) /*!< Control register */ +#define USB_ISTR (USB_BASE + 0x44U) /*!< Interrupt status register */ +#define USB_FNR (USB_BASE + 0x48U) /*!< Frame number register */ +#define USB_DADDR (USB_BASE + 0x4CU) /*!< Device address register */ +#define USB_BTABLE (USB_BASE + 0x50U) /*!< Buffer Table address register */ + +/**************************** ISTR interrupt events *************************/ +#define USB_ISTR_CTR ((uint16_t)0x8000U) /*!< Correct TRansfer (clear-only bit) */ +#define USB_ISTR_PMAOVR ((uint16_t)0x4000U) /*!< DMA OVeR/underrun (clear-only bit) */ +#define USB_ISTR_ERR ((uint16_t)0x2000U) /*!< ERRor (clear-only bit) */ +#define USB_ISTR_WKUP ((uint16_t)0x1000U) /*!< WaKe UP (clear-only bit) */ +#define USB_ISTR_SUSP ((uint16_t)0x0800U) /*!< SUSPend (clear-only bit) */ +#define USB_ISTR_RESET ((uint16_t)0x0400U) /*!< RESET (clear-only bit) */ +#define USB_ISTR_SOF ((uint16_t)0x0200U) /*!< Start Of Frame (clear-only bit) */ +#define USB_ISTR_ESOF ((uint16_t)0x0100U) /*!< Expected Start Of Frame (clear-only bit) */ +#define USB_ISTR_DIR ((uint16_t)0x0010U) /*!< DIRection of transaction (read-only bit) */ +#define USB_ISTR_EP_ID ((uint16_t)0x000FU) /*!< EndPoint IDentifier (read-only bit) */ + +/* Legacy defines */ +#define USB_ISTR_PMAOVRM USB_ISTR_PMAOVR + +#define USB_CLR_CTR (~USB_ISTR_CTR) /*!< clear Correct TRansfer bit */ +#define USB_CLR_PMAOVR (~USB_ISTR_PMAOVR) /*!< clear DMA OVeR/underrun bit*/ +#define USB_CLR_ERR (~USB_ISTR_ERR) /*!< clear ERRor bit */ +#define USB_CLR_WKUP (~USB_ISTR_WKUP) /*!< clear WaKe UP bit */ +#define USB_CLR_SUSP (~USB_ISTR_SUSP) /*!< clear SUSPend bit */ +#define USB_CLR_RESET (~USB_ISTR_RESET) /*!< clear RESET bit */ +#define USB_CLR_SOF (~USB_ISTR_SOF) /*!< clear Start Of Frame bit */ +#define USB_CLR_ESOF (~USB_ISTR_ESOF) /*!< clear Expected Start Of Frame bit */ + +/* Legacy defines */ +#define USB_CLR_PMAOVRM USB_CLR_PMAOVR + +/************************* CNTR control register bits definitions ***********/ +#define USB_CNTR_CTRM ((uint16_t)0x8000U) /*!< Correct TRansfer Mask */ +#define USB_CNTR_PMAOVR ((uint16_t)0x4000U) /*!< DMA OVeR/underrun Mask */ +#define USB_CNTR_ERRM ((uint16_t)0x2000U) /*!< ERRor Mask */ +#define USB_CNTR_WKUPM ((uint16_t)0x1000U) /*!< WaKe UP Mask */ +#define USB_CNTR_SUSPM ((uint16_t)0x0800U) /*!< SUSPend Mask */ +#define USB_CNTR_RESETM ((uint16_t)0x0400U) /*!< RESET Mask */ +#define USB_CNTR_SOFM ((uint16_t)0x0200U) /*!< Start Of Frame Mask */ +#define USB_CNTR_ESOFM ((uint16_t)0x0100U) /*!< Expected Start Of Frame Mask */ +#define USB_CNTR_RESUME ((uint16_t)0x0010U) /*!< RESUME request */ +#define USB_CNTR_FSUSP ((uint16_t)0x0008U) /*!< Force SUSPend */ +#define USB_CNTR_LPMODE ((uint16_t)0x0004U) /*!< Low-power MODE */ +#define USB_CNTR_PDWN ((uint16_t)0x0002U) /*!< Power DoWN */ +#define USB_CNTR_FRES ((uint16_t)0x0001U) /*!< Force USB RESet */ + +/* Legacy defines */ +#define USB_CNTR_PMAOVRM USB_CNTR_PMAOVR +#define USB_CNTR_LP_MODE USB_CNTR_LPMODE + +/******************** FNR Frame Number Register bit definitions ************/ +#define USB_FNR_RXDP ((uint16_t)0x8000U) /*!< status of D+ data line */ +#define USB_FNR_RXDM ((uint16_t)0x4000U) /*!< status of D- data line */ +#define USB_FNR_LCK ((uint16_t)0x2000U) /*!< LoCKed */ +#define USB_FNR_LSOF ((uint16_t)0x1800U) /*!< Lost SOF */ +#define USB_FNR_FN ((uint16_t)0x07FFU) /*!< Frame Number */ + +/******************** DADDR Device ADDRess bit definitions ****************/ +#define USB_DADDR_EF ((uint8_t)0x80U) /*!< USB device address Enable Function */ +#define USB_DADDR_ADD ((uint8_t)0x7FU) /*!< USB device address */ + +/****************************** Endpoint register *************************/ +#define USB_EP0R USB_BASE /*!< endpoint 0 register address */ +#define USB_EP1R (USB_BASE + 0x04U) /*!< endpoint 1 register address */ +#define USB_EP2R (USB_BASE + 0x08U) /*!< endpoint 2 register address */ +#define USB_EP3R (USB_BASE + 0x0CU) /*!< endpoint 3 register address */ +#define USB_EP4R (USB_BASE + 0x10U) /*!< endpoint 4 register address */ +#define USB_EP5R (USB_BASE + 0x14U) /*!< endpoint 5 register address */ +#define USB_EP6R (USB_BASE + 0x18U) /*!< endpoint 6 register address */ +#define USB_EP7R (USB_BASE + 0x1CU) /*!< endpoint 7 register address */ +/* bit positions */ +#define USB_EP_CTR_RX ((uint16_t)0x8000U) /*!< EndPoint Correct TRansfer RX */ +#define USB_EP_DTOG_RX ((uint16_t)0x4000U) /*!< EndPoint Data TOGGLE RX */ +#define USB_EPRX_STAT ((uint16_t)0x3000U) /*!< EndPoint RX STATus bit field */ +#define USB_EP_SETUP ((uint16_t)0x0800U) /*!< EndPoint SETUP */ +#define USB_EP_T_FIELD ((uint16_t)0x0600U) /*!< EndPoint TYPE */ +#define USB_EP_KIND ((uint16_t)0x0100U) /*!< EndPoint KIND */ +#define USB_EP_CTR_TX ((uint16_t)0x0080U) /*!< EndPoint Correct TRansfer TX */ +#define USB_EP_DTOG_TX ((uint16_t)0x0040U) /*!< EndPoint Data TOGGLE TX */ +#define USB_EPTX_STAT ((uint16_t)0x0030U) /*!< EndPoint TX STATus bit field */ +#define USB_EPADDR_FIELD ((uint16_t)0x000FU) /*!< EndPoint ADDRess FIELD */ + +/* EndPoint REGister MASK (no toggle fields) */ +#define USB_EPREG_MASK (USB_EP_CTR_RX|USB_EP_SETUP|USB_EP_T_FIELD|USB_EP_KIND|USB_EP_CTR_TX|USB_EPADDR_FIELD) + /*!< EP_TYPE[1:0] EndPoint TYPE */ +#define USB_EP_TYPE_MASK ((uint16_t)0x0600U) /*!< EndPoint TYPE Mask */ +#define USB_EP_BULK ((uint16_t)0x0000U) /*!< EndPoint BULK */ +#define USB_EP_CONTROL ((uint16_t)0x0200U) /*!< EndPoint CONTROL */ +#define USB_EP_ISOCHRONOUS ((uint16_t)0x0400U) /*!< EndPoint ISOCHRONOUS */ +#define USB_EP_INTERRUPT ((uint16_t)0x0600U) /*!< EndPoint INTERRUPT */ +#define USB_EP_T_MASK ((uint16_t) ~USB_EP_T_FIELD & USB_EPREG_MASK) + +#define USB_EPKIND_MASK ((uint16_t) ~USB_EP_KIND & USB_EPREG_MASK) /*!< EP_KIND EndPoint KIND */ + /*!< STAT_TX[1:0] STATus for TX transfer */ +#define USB_EP_TX_DIS ((uint16_t)0x0000U) /*!< EndPoint TX DISabled */ +#define USB_EP_TX_STALL ((uint16_t)0x0010U) /*!< EndPoint TX STALLed */ +#define USB_EP_TX_NAK ((uint16_t)0x0020U) /*!< EndPoint TX NAKed */ +#define USB_EP_TX_VALID ((uint16_t)0x0030U) /*!< EndPoint TX VALID */ +#define USB_EPTX_DTOG1 ((uint16_t)0x0010U) /*!< EndPoint TX Data TOGgle bit1 */ +#define USB_EPTX_DTOG2 ((uint16_t)0x0020U) /*!< EndPoint TX Data TOGgle bit2 */ +#define USB_EPTX_DTOGMASK (USB_EPTX_STAT|USB_EPREG_MASK) + /*!< STAT_RX[1:0] STATus for RX transfer */ +#define USB_EP_RX_DIS ((uint16_t)0x0000U) /*!< EndPoint RX DISabled */ +#define USB_EP_RX_STALL ((uint16_t)0x1000U) /*!< EndPoint RX STALLed */ +#define USB_EP_RX_NAK ((uint16_t)0x2000U) /*!< EndPoint RX NAKed */ +#define USB_EP_RX_VALID ((uint16_t)0x3000U) /*!< EndPoint RX VALID */ +#define USB_EPRX_DTOG1 ((uint16_t)0x1000U) /*!< EndPoint RX Data TOGgle bit1 */ +#define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ +#define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) + + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +#if CFG_TUSB_MCU == OPT_MCU_CH32V20X +static const IRQn_Type fsdev_irq[] = { + USB_HP_CAN1_TX_IRQn, + USB_LP_CAN1_RX0_IRQn, + USBWakeUp_IRQn +}; +enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; +#else + #error "Unsupported MCU" +#endif + +void dcd_int_enable(uint8_t rhport) { + (void)rhport; + for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { + NVIC_EnableIRQ(fsdev_irq[i]); + } +} + +void dcd_int_disable(uint8_t rhport) { + (void)rhport; + for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { + NVIC_DisableIRQ(fsdev_irq[i]); + } +} + +void dcd_disconnect(uint8_t rhport) { + (void) rhport; + EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN; +} + +void dcd_connect(uint8_t rhport) { + (void) rhport; + EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN; +} + +#endif diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 7992f34a1..af5d8afab 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -1,174 +1,43 @@ /* + * The MIT License (MIT) + * * Copyright(c) 2016 STMicroelectronics * Copyright(c) N Conrad - * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2024, hathach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. * - * This file is part of the TinyUSB stack. */ -// This file contains source copied from ST's HAL, and thus should have their copyright statement. +#ifndef TUSB_FSDEV_COMMON_H +#define TUSB_FSDEV_COMMON_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "stdint.h" // FSDEV_PMA_SIZE is PMA buffer size in bytes. // On 512-byte devices, access with a stride of two words (use every other 16-bit address) // On 1024-byte devices, access with a stride of one word (use every 16-bit address) -#ifndef PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ -#define PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ - -#if CFG_TUSB_MCU == OPT_MCU_STM32F0 - #include "stm32f0xx.h" - #define FSDEV_PMA_SIZE (1024u) - // F0x2 models are crystal-less - // All have internal D+ pull-up - // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support - // PMA dedicated to USB (no sharing with CAN) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - #define FSDEV_PMA_SIZE (512u) - // NO internal Pull-ups - // *B, and *C: 2 x 16 bits/word - - // F1 names this differently from the rest - #define USB_CNTR_LPMODE USB_CNTR_LP_MODE - -#elif defined(STM32F302xB) || defined(STM32F302xC) || \ - defined(STM32F303xB) || defined(STM32F303xC) || \ - defined(STM32F373xC) - #include "stm32f3xx.h" - #define FSDEV_PMA_SIZE (512u) - // NO internal Pull-ups - // *B, and *C: 1 x 16 bits/word - // PMA dedicated to USB (no sharing with CAN) - -#elif defined(STM32F302x6) || defined(STM32F302x8) || \ - defined(STM32F302xD) || defined(STM32F302xE) || \ - defined(STM32F303xD) || defined(STM32F303xE) - #include "stm32f3xx.h" - #define FSDEV_PMA_SIZE (1024u) - // NO internal Pull-ups - // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support - // When CAN clock is enabled, USB can use first 768 bytes ONLY. - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 - #include "stm32l0xx.h" - #define FSDEV_PMA_SIZE (1024u) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 - #include "stm32l1xx.h" - #define FSDEV_PMA_SIZE (512u) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 - #include "stm32g4xx.h" - #define FSDEV_PMA_SIZE (1024u) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #include "stm32g0xx.h" - #define FSDEV_BUS_32BIT - #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 - #include "stm32h5xx.h" - #define FSDEV_BUS_32BIT - - #if !defined(USB_DRD_BASE) && defined(USB_DRD_FS_BASE) - #define USB_DRD_BASE USB_DRD_FS_BASE - #endif - - #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R - #define USB_EP_CTR_RX USB_EP_VTRX - #define USB_EP_CTR_TX USB_EP_VTTX - #define USB_EP_T_FIELD USB_CHEP_UTYPE - #define USB_EPREG_MASK USB_CHEP_REG_MASK - #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK - #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK - #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 - #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 - #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 - #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 - #define USB_EPRX_STAT USB_CH_RX_VALID - #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS - #define USB_CNTR_FRES USB_CNTR_USBRST - #define USB_CNTR_RESUME USB_CNTR_L2RES - #define USB_ISTR_EP_ID USB_ISTR_IDN - #define USB_EPADDR_FIELD USB_CHEP_ADDR - #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY - #define USB_CNTR_FSUSP USB_CNTR_SUSPEN - -#elif CFG_TUSB_MCU == OPT_MCU_STM32WB - #include "stm32wbxx.h" - #define FSDEV_PMA_SIZE (1024u) - /* ST provided header has incorrect value */ - #undef USB_PMAADDR - #define USB_PMAADDR USB1_PMAADDR - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - #define FSDEV_PMA_SIZE (1024u) - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L5 - #include "stm32l5xx.h" - #define FSDEV_PMA_SIZE (1024u) - - #ifndef USB_PMAADDR - #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) - #endif - -#else - #error You are using an untested or unimplemented STM32 variant. Please update the driver. - // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 -#endif - // For purposes of accessing the packet #if ((FSDEV_PMA_SIZE) == 512u) #define FSDEV_PMA_STRIDE (2u) @@ -181,24 +50,24 @@ // The compiler should warn us if we cast it to a non-volatile type? #ifdef FSDEV_BUS_32BIT typedef uint32_t fsdev_bus_t; -static __IO uint32_t * const pma32 = (__IO uint32_t*)USB_PMAADDR; +static volatile uint32_t * const pma32 = (volatile uint32_t*)USB_PMAADDR; #else typedef uint16_t fsdev_bus_t; // Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) -static __IO uint16_t * const pma = (__IO uint16_t*)USB_PMAADDR; +static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR; -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) { +TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) { size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; total_word_offset *= FSDEV_PMA_STRIDE; return &(pma[total_word_offset]); } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { +TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u); } -TU_ATTR_ALWAYS_INLINE static inline __IO uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { +TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); } #endif @@ -218,10 +87,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t si TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { #ifdef FSDEV_BUS_32BIT (void) USBx; - __O uint32_t *reg = (__O uint32_t *)(USB_DRD_BASE + bEpIdx*4); + volatile uint32_t *reg = (volatile uint32_t *)(USB_DRD_BASE + bEpIdx*4); *reg = wRegValue; #else - __O uint16_t *reg = (__O uint16_t *)((&USBx->EP0R) + bEpIdx*2u); + volatile uint16_t *reg = (volatile uint16_t *)((&USBx->EP0R) + bEpIdx*2u); *reg = (uint16_t)wRegValue; #endif } @@ -229,9 +98,9 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, ui TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { #ifdef FSDEV_BUS_32BIT (void) USBx; - __I uint32_t *reg = (__I uint32_t *)(USB_DRD_BASE + bEpIdx*4); + volatile const uint32_t *reg = (volatile const uint32_t *)(USB_DRD_BASE + bEpIdx*4); #else - __I uint16_t *reg = (__I uint16_t *)((&USBx->EP0R) + bEpIdx*2u); + volatile const uint16_t *reg = (volatile const uint16_t *)((&USBx->EP0R) + bEpIdx*2u); #endif return *reg; } @@ -283,7 +152,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USB (void) USBx; return (pma32[2*bEpIdx] & 0x03FF0000) >> 16; #else - __I uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); + volatile const uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); return *regPtr & 0x3ffU; #endif } @@ -293,7 +162,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USB (void) USBx; return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; #else - __I uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); + volatile const uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); return *regPtr & 0x3ffU; #endif } @@ -363,7 +232,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, u (void) USBx; pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); #else - __IO uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); + volatile uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); #endif } @@ -375,7 +244,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_dbuf1_cnt(USB_TypeDef * U (void) USBx; pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); #else - __IO uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); + volatile uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); #endif } @@ -387,7 +256,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDe (void) USBx; pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26); #else - __IO uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u); + volatile uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u); *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); #endif } @@ -472,13 +341,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * return (regVal & USB_EPRX_STAT) >> (12u); } - -/** - * @brief Toggles DTOG_RX / DTOG_TX bit in the endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval None - */ TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; @@ -493,12 +355,6 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32 pcd_set_endpoint(USBx, bEpIdx, regVal); } -/** - * @brief Clears DTOG_RX / DTOG_TX bit in the endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval None - */ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); if((regVal & USB_EP_DTOG_RX) != 0) { @@ -513,12 +369,6 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, } } -/** - * @brief set & clear EP_KIND bit. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval None - */ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal |= USB_EP_KIND; @@ -534,18 +384,8 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, u pcd_set_endpoint(USBx, bEpIdx, regVal); } -// This checks if the device has "LPM" -#if defined(USB_ISTR_L1REQ) -#define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ) -#else -#define USB_ISTR_L1REQ_FORCED ((uint16_t)0x0000U) +#ifdef __cplusplus + } #endif -#define USB_ISTR_ALL_EVENTS (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | \ - USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ_FORCED ) - -// Number of endpoints in hardware -// TODO should use TUP_DCD_ENDPOINT_MAX -#define STFSDEV_EP_COUNT (8u) - -#endif /* PORTABLE_ST_STM32F0_DCD_STM32F0_FSDEV_PVT_ST_H_ */ +#endif diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h new file mode 100644 index 000000000..b3fa11b88 --- /dev/null +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -0,0 +1,292 @@ +/* + * The MIT License (MIT) + * + * Copyright(c) N Conrad + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_FSDEV_STM32_H +#define TUSB_FSDEV_STM32_H + +#if CFG_TUSB_MCU == OPT_MCU_STM32F0 + #include "stm32f0xx.h" + #define FSDEV_PMA_SIZE (1024u) + // F0x2 models are crystal-less + // All have internal D+ pull-up + // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support + // PMA dedicated to USB (no sharing with CAN) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 + #include "stm32f1xx.h" + #define FSDEV_PMA_SIZE (512u) + // NO internal Pull-ups + // *B, and *C: 2 x 16 bits/word + + // F1 names this differently from the rest + #define USB_CNTR_LPMODE USB_CNTR_LP_MODE + +#elif defined(STM32F302xB) || defined(STM32F302xC) || \ + defined(STM32F303xB) || defined(STM32F303xC) || \ + defined(STM32F373xC) + #include "stm32f3xx.h" + #define FSDEV_PMA_SIZE (512u) + // NO internal Pull-ups + // *B, and *C: 1 x 16 bits/word + // PMA dedicated to USB (no sharing with CAN) + +#elif defined(STM32F302x6) || defined(STM32F302x8) || \ + defined(STM32F302xD) || defined(STM32F302xE) || \ + defined(STM32F303xD) || defined(STM32F303xE) + #include "stm32f3xx.h" + #define FSDEV_PMA_SIZE (1024u) + // NO internal Pull-ups + // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support + // When CAN clock is enabled, USB can use first 768 bytes ONLY. + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 + #include "stm32l0xx.h" + #define FSDEV_PMA_SIZE (1024u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 + #include "stm32l1xx.h" + #define FSDEV_PMA_SIZE (512u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 + #include "stm32g4xx.h" + #define FSDEV_PMA_SIZE (1024u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #include "stm32g0xx.h" + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + #include "stm32h5xx.h" + #define FSDEV_BUS_32BIT + + #if !defined(USB_DRD_BASE) && defined(USB_DRD_FS_BASE) + #define USB_DRD_BASE USB_DRD_FS_BASE + #endif + + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32WB + #include "stm32wbxx.h" + #define FSDEV_PMA_SIZE (1024u) + /* ST provided header has incorrect value */ + #undef USB_PMAADDR + #define USB_PMAADDR USB1_PMAADDR + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 + #include "stm32l4xx.h" + #define FSDEV_PMA_SIZE (1024u) + +#elif CFG_TUSB_MCU == OPT_MCU_STM32L5 + #include "stm32l5xx.h" + #define FSDEV_PMA_SIZE (1024u) + + #ifndef USB_PMAADDR + #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) + #endif + +#else + #error You are using an untested or unimplemented STM32 variant. Please update the driver. + // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 +#endif + +// This checks if the device has "LPM" +#if defined(USB_ISTR_L1REQ) +#define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ) +#else +#define USB_ISTR_L1REQ_FORCED ((uint16_t)0x0000U) +#endif + +#define USB_ISTR_ALL_EVENTS (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | \ + USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ_FORCED ) + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +#if TU_CHECK_MCU(OPT_MCU_STM32L1) && !defined(USBWakeUp_IRQn) + #define USBWakeUp_IRQn USB_FS_WKUP_IRQn +#endif + +static const IRQn_Type fsdev_irq[] = { + #if TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32L0, OPT_MCU_STM32L4) + USB_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 + USB_HP_CAN1_TX_IRQn, + USB_LP_CAN1_RX0_IRQn, + USBWakeUp_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32F3 + // USB remap handles dcd functions + USB_HP_CAN_TX_IRQn, + USB_LP_CAN_RX0_IRQn, + USBWakeUp_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 + #ifdef STM32G0B0xx + USB_IRQn, + #else + USB_UCPD1_2_IRQn, + #endif + #elif TU_CHECK_MCU(OPT_MCU_STM32G4, OPT_MCU_STM32L1) + USB_HP_IRQn, + USB_LP_IRQn, + USBWakeUp_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32H5 + USB_DRD_FS_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32L5 + USB_FS_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32WB + USB_HP_IRQn, + USB_LP_IRQn, + #else + #error Unknown arch in USB driver + #endif +}; +enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; + +void dcd_int_enable(uint8_t rhport) { + (void)rhport; + + // forces write to RAM before allowing ISR to execute + __DSB(); __ISB(); + + #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP) + // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from + // shared USB/CAN IRQs to separate CAN and USB IRQs. + // This dynamically checks if this remap is active to enable the right IRQs. + if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) { + NVIC_EnableIRQ(USB_HP_IRQn); + NVIC_EnableIRQ(USB_LP_IRQn); + NVIC_EnableIRQ(USBWakeUp_RMP_IRQn); + } else + #endif + { + for (uint8_t i = 0; i < FSDEV_IRQ_NUM; i++) { + NVIC_EnableIRQ(fsdev_irq[i]); + } + } +} + +void dcd_int_disable(uint8_t rhport) { + (void)rhport; + + #if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP) + // Some STM32F302/F303 devices allow to remap the USB interrupt vectors from + // shared USB/CAN IRQs to separate CAN and USB IRQs. + // This dynamically checks if this remap is active to enable the right IRQs. + if (SYSCFG->CFGR1 & SYSCFG_CFGR1_USB_IT_RMP) { + NVIC_DisableIRQ(USB_HP_IRQn); + NVIC_DisableIRQ(USB_LP_IRQn); + NVIC_DisableIRQ(USBWakeUp_RMP_IRQn); + } else + #endif + { + for (uint8_t i = 0; i < FSDEV_IRQ_NUM; i++) { + NVIC_DisableIRQ(fsdev_irq[i]); + } + } + + // CMSIS has a membar after disabling interrupts +} + +// Define only on MCU with internal pull-up. BSP can define on MCU without internal PU. +#if defined(USB_BCDR_DPPU) + +void dcd_disconnect(uint8_t rhport) { + (void)rhport; + USB->BCDR &= ~(USB_BCDR_DPPU); +} + +void dcd_connect(uint8_t rhport) { + (void)rhport; + USB->BCDR |= USB_BCDR_DPPU; +} + +#elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151 + +void dcd_disconnect(uint8_t rhport) { + (void)rhport; + SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU); +} + +void dcd_connect(uint8_t rhport) { + (void)rhport; + SYSCFG->PMC |= SYSCFG_PMC_USB_PU; +} +#endif + + +#endif /* TUSB_FSDEV_STM32_H */ diff --git a/src/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 |
