diff options
| author | hathach <[email protected]> | 2026-03-16 18:01:02 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-03-16 18:01:02 +0700 |
| commit | 9b2f6f4f0cb0d7c1227c87093382a7fb9eea35c9 (patch) | |
| tree | b9cf8a9b7453a77c7fb8997f4a05c9345446600b /src/portable/st/stm32_fsdev/fsdev_common.h | |
| parent | 3da88d755dd0438570f254a43eea18b84fc1bb83 (diff) | |
Consolidate USB FSDEV register definitions for STM32, CH32, and AT32 microcontrollers. Replace vendor-specific macros with unified `U_`-prefixed equivalents, ensuring consistency and reducing duplication across all platforms.
Diffstat (limited to 'src/portable/st/stm32_fsdev/fsdev_common.h')
| -rw-r--r-- | src/portable/st/stm32_fsdev/fsdev_common.h | 232 |
1 files changed, 194 insertions, 38 deletions
diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index b749a92ff..36df4809d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -39,6 +39,172 @@ #include "host/hcd.h" #endif +//--------------------------------------------------------------------+ +// FSDEV Register Bit Definitions +// Vendor-independent definitions with U_ prefix to avoid conflicts. +// Based on the common USB FSDEV IP block register layout. +// Lower 16 bits are shared across all variants (STM32, CH32, AT32). +// Upper 16 bits (DRD extensions) only exist on 32-bit DRD MCUs. +//--------------------------------------------------------------------+ + +// EPnR / CHEPnR - Endpoint/Channel Register +// DTOG and STAT bits are toggle-on-write-1. CTR bits are clear-on-write-0. +// +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// CTR_RX DTOG_RX STAT_RX[1:0] SETUP EP_TYPE[1:0] KIND CTR_TX DTOG_TX STAT_TX[1:0] EA[3:0] +// +// DRD 32-bit only (C0, G0, H5, U0, U5): +// 31:27 26 25 24 23 22 21 20 19 18 17 16 +// Rsvd ERR_RX ERR_TX LSEP NAK DEVADDR[6:0] +#define U_EP_CTR_RX 0x8000u +#define U_EP_DTOG_RX 0x4000u +#define U_EPRX_STAT 0x3000u +#define U_EP_SETUP 0x0800u +#define U_EP_T_FIELD 0x0600u +#define U_EP_KIND 0x0100u +#define U_EP_CTR_TX 0x0080u +#define U_EP_DTOG_TX 0x0040u +#define U_EPTX_STAT 0x0030u +#define U_EPADDR_FIELD 0x000Fu + +// DRD 32-bit upper bits +#define U_EP_ERRRX 0x04000000u +#define U_EP_ERRTX 0x02000000u +#define U_EP_LSEP 0x01000000u +#define U_EP_NAK 0x00800000u +#define U_EP_DEVADDR 0x007F0000u +#define U_EP_DEVADDR_Pos 16u + +// Endpoint types (EP_TYPE field values) +#define U_EP_BULK 0x0000u +#define U_EP_CONTROL 0x0200u +#define U_EP_ISOCHRONOUS 0x0400u +#define U_EP_INTERRUPT 0x0600u +#define U_EP_TYPE_MASK (U_EP_T_FIELD) + +// EP register mask components (non-toggle bits preserved during read-modify-write) +// Excludes DTOG_RX, STAT_RX, DTOG_TX, STAT_TX (toggle-on-write-1) +#define U_EPREG_MASK_16 (U_EP_CTR_RX | U_EP_SETUP | U_EP_T_FIELD | U_EP_KIND | U_EP_CTR_TX | U_EPADDR_FIELD) +#define U_EPREG_MASK_32 (U_EP_ERRRX | U_EP_ERRTX | U_EP_LSEP | U_EP_NAK | U_EP_DEVADDR | U_EPREG_MASK_16) + +// EP register mask selection based on bus width +#ifdef FSDEV_BUS_32BIT + #define U_EPREG_MASK U_EPREG_MASK_32 +#else + #define U_EPREG_MASK U_EPREG_MASK_16 +#endif + +#define U_EPKIND_MASK ((uint32_t)(~U_EP_KIND) & U_EPREG_MASK) +#define U_EPTX_DTOGMASK (U_EPTX_STAT | U_EPREG_MASK) +#define U_EPRX_DTOGMASK (U_EPRX_STAT | U_EPREG_MASK) + +// Bit positions +#define U_EPTX_STAT_Pos 4u +#define U_EP_DTOG_TX_Pos 6u +#define U_EP_CTR_TX_Pos 7u + +// Data toggle helpers +#define U_EPTX_DTOG1 0x0010u +#define U_EPTX_DTOG2 0x0020u +#define U_EPRX_DTOG1 0x1000u +#define U_EPRX_DTOG2 0x2000u + +// CNTR - Control Register +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// CTRM PMAOVRM ERRM WKUPM SUSPM RESETM SOFM ESOFM Rsvd Rsvd Rsvd RESUME FSUSP LPMODE PDWN FRES +// +// DRD 32-bit only: +// 31 30:16 +// HOST Rsvd +#define U_CNTR_CTRM 0x8000u +#define U_CNTR_PMAOVRM 0x4000u +#define U_CNTR_ERRM 0x2000u +#define U_CNTR_WKUPM 0x1000u +#define U_CNTR_SUSPM 0x0800u +#define U_CNTR_RESETM 0x0400u +#define U_CNTR_SOFM 0x0200u +#define U_CNTR_ESOFM 0x0100u +#define U_CNTR_RESUME 0x0010u +#define U_CNTR_FSUSP 0x0008u +#define U_CNTR_LPMODE 0x0004u +#define U_CNTR_PDWN 0x0002u +#define U_CNTR_FRES 0x0001u + +#define U_CNTR_HOST 0x80000000u // DRD: enable host mode +#define U_CNTR_DCON 0x0400u // DRD host: same bit as RESETM + +// ISTR - Interrupt Status Register +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// CTR PMAOVR ERR WKUP SUSP RESET SOF ESOF Rsvd Rsvd Rsvd DIR EP_ID[3:0] +// +// DRD 32-bit only: +// 31 30 29 28:16 +// Rsvd LS_DCONN DCON_STAT Rsvd +#define U_ISTR_CTR 0x8000u +#define U_ISTR_PMAOVR 0x4000u +#define U_ISTR_ERR 0x2000u +#define U_ISTR_WKUP 0x1000u +#define U_ISTR_SUSP 0x0800u +#define U_ISTR_RESET 0x0400u +#define U_ISTR_SOF 0x0200u +#define U_ISTR_ESOF 0x0100u +#define U_ISTR_DIR 0x0010u +#define U_ISTR_EP_ID 0x000Fu + +#define U_ISTR_LS_DCONN 0x40000000u // DRD: low-speed device connected +#define U_ISTR_DCON_STAT 0x20000000u // DRD: device connection status +#define U_ISTR_DCON 0x0400u // DRD host: same bit as RESET + +// FNR - Frame Number Register (read-only) +// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// RXDP RXDM LCK[2:0] FN[10:0] +#define U_FNR_RXDP 0x8000u +#define U_FNR_RXDM 0x4000u +#define U_FNR_FN 0x07FFu + +// DADDR - Device Address Register +// 15:8 7 6 5 4 3 2 1 0 +// Rsvd EF ADD[6:0] +#define U_DADDR_EF 0x80u + +// LPMCSR - LPM Control and Status Register +// Supported: STM32 F0, L0, L4, G0, G4, C0, H5, U0, WB. Not on: F1, F3, AT32, CH32. +// 15:8 7 6 5 4 3 2 1 0 +// Rsvd BESL[3:0] Rsvd REMWAKE Rsvd LPMACK LMPEN +#define U_LPMCSR_LMPEN 0x0001u +#define U_LPMCSR_LPMACK 0x0002u +#define U_LPMCSR_REMWAKE 0x0008u +#define U_LPMCSR_BESL 0x00F0u + +// BCDR - Battery Charging Detector Register +// Supported: STM32 F0, L0, L4, G0, G4, C0, H5, U0, WB. Not on: F1, F3, AT32, CH32. +// 15 14:8 7 6 5 4 3 2 1 0 +// DPPU Rsvd PS2DET SDET PDET DCDET SDEN PDEN DCDEN BCDEN +#define U_BCDR_BCDEN 0x0001u +#define U_BCDR_DCDEN 0x0002u +#define U_BCDR_PDEN 0x0004u +#define U_BCDR_SDEN 0x0008u +#define U_BCDR_DCDET 0x0010u +#define U_BCDR_PDET 0x0020u +#define U_BCDR_SDET 0x0040u +#define U_BCDR_PS2DET 0x0080u +#define U_BCDR_DPPU 0x8000u + +// Channel status (DRD host mode, reuses STAT_TX/STAT_RX bit positions) +#define U_CH_TX_STTX 0x0030u +#define U_CH_TX_ACK_SBUF 0x0000u +#define U_CH_TX_STALL 0x0010u +#define U_CH_TX_NAK 0x0020u + +#define U_CH_RX_STRX 0x3000u +#define U_CH_RX_ACK_SBUF 0x0000u +#define U_CH_RX_STALL 0x1000u +#define U_CH_RX_NAK 0x2000u +#define U_CH_RX_VALID 0x3000u + +//--------------------------------------------------------------------+ +// Vendor-specific includes (after U_ definitions so they can use them) +//--------------------------------------------------------------------+ #if defined(TUP_USBIP_FSDEV_STM32) #include "fsdev_stm32.h" #elif defined(TUP_USBIP_FSDEV_CH32) @@ -49,6 +215,16 @@ #error "Unknown USB IP" #endif +// LPM support - detect from vendor header (L1REQ bit position varies) +#if defined(USB_ISTR_L1REQ) + #define U_ISTR_L1REQ USB_ISTR_L1REQ +#else + #define U_ISTR_L1REQ 0x0000u +#endif + +#define U_ISTR_ALL_EVENTS (U_ISTR_PMAOVR | U_ISTR_ERR | U_ISTR_WKUP | U_ISTR_SUSP | \ + U_ISTR_RESET | U_ISTR_SOF | U_ISTR_ESOF | U_ISTR_L1REQ) + #ifdef __cplusplus extern "C" { #endif @@ -146,9 +322,9 @@ typedef struct { _va32 fsdev_bus_t ISTR; // 44: Interrupt status register _va32 fsdev_bus_t FNR; // 48: Frame number register _va32 fsdev_bus_t DADDR; // 4C: Device address register - _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) - _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) - _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status (not on F1, F3, AT32, CH32) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector (not on F1, F3, AT32, CH32) } fsdev_regs_t; TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); @@ -157,26 +333,6 @@ TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); #define FSDEV_REG ((fsdev_regs_t *)FSDEV_REG_BASE) -#ifndef USB_EPTX_STAT - #define USB_EPTX_STAT 0x0030U -#endif - -#ifndef USB_EPRX_STAT - #define USB_EPRX_STAT 0x3000U -#endif - -#ifndef USB_EPTX_STAT_Pos - #define USB_EPTX_STAT_Pos 4u -#endif - -#ifndef USB_EP_DTOG_TX_Pos - #define USB_EP_DTOG_TX_Pos 6u -#endif - -#ifndef USB_EP_CTR_TX_Pos - #define USB_EP_CTR_TX_Pos 7u -#endif - typedef enum { EP_STAT_DISABLED = 0, EP_STAT_STALL = 1, @@ -184,11 +340,11 @@ typedef enum { EP_STAT_VALID = 3 } ep_stat_t; -#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_STAT_MASK(_dir) (3u << (U_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_DTOG_MASK(_dir) (1u << (U_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) -#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_STAT_MASK(_dir) (3u << (U_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) +#define CH_DTOG_MASK(_dir) (1u << (U_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0))) //--------------------------------------------------------------------+ // Endpoint Helper @@ -214,22 +370,22 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) { uint32_t reg = FSDEV_REG->ep[ep_id].reg; - reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; - reg &= USB_EPREG_MASK; - reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + reg |= U_EP_CTR_TX | U_EP_CTR_RX; + reg &= U_EPREG_MASK; + reg &= ~(1 << (U_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); ep_write(ep_id, reg, false); } TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state) { - *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + *reg ^= (state << (U_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state) { - *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + *reg ^= (state << (U_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { - return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; + return (reg & U_EP_TYPE_MASK) == U_EP_ISOCHRONOUS; } //--------------------------------------------------------------------+ @@ -247,18 +403,18 @@ TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) { uint32_t reg = FSDEV_REG->ep[ch_id].reg; - reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; - reg &= USB_EPREG_MASK; - reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + reg |= U_EP_CTR_TX | U_EP_CTR_RX; + reg &= U_EPREG_MASK; + reg &= ~(1 << (U_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); ep_write(ch_id, reg, false); } TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t *reg, tusb_dir_t dir, ep_stat_t state) { - *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + *reg ^= (state << (U_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); } TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t *reg, tusb_dir_t dir, uint8_t state) { - *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); + *reg ^= (state << (U_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0))); } //--------------------------------------------------------------------+ |
