summaryrefslogtreecommitdiff
path: root/src/portable/st/stm32_fsdev/fsdev_common.h
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-03-16 18:01:02 +0700
committerhathach <[email protected]>2026-03-16 18:01:02 +0700
commit9b2f6f4f0cb0d7c1227c87093382a7fb9eea35c9 (patch)
treeb9cf8a9b7453a77c7fb8997f4a05c9345446600b /src/portable/st/stm32_fsdev/fsdev_common.h
parent3da88d755dd0438570f254a43eea18b84fc1bb83 (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.h232
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)));
}
//--------------------------------------------------------------------+