summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2025-12-13 18:48:07 +0700
committerGitHub <[email protected]>2025-12-13 18:48:07 +0700
commit54857210e6541b1e41970ab70f19d3cdf434011c (patch)
treeab4a1222fc804fa8b13ac836cc592c66af66ef73 /src
parent20b03bbc081353295f7a491038bd3efbc9c3a75a (diff)
parent85354377fd855480f4be99fb67e5805fe88d059d (diff)
Merge pull request #3358 from hathach/dwc2_cfg
Add dcd_configure for dwc2 FIFO config
Diffstat (limited to 'src')
-rw-r--r--src/device/dcd.h3
-rw-r--r--src/device/usbd.c15
-rw-r--r--src/device/usbd.h20
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c31
4 files changed, 58 insertions, 11 deletions
diff --git a/src/device/dcd.h b/src/device/dcd.h
index 8a074ab47..850c37bc2 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -107,6 +107,9 @@ bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size);
// Controller API
//--------------------------------------------------------------------+
+// optional dcd configuration, called by tud_configure()
+bool dcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);
+
// Initialize controller to device mode
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init);
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 6c2ff2f62..e337a5000 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -425,6 +425,11 @@ TU_ATTR_WEAK bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t
return false;
}
+TU_ATTR_WEAK bool dcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
+ (void) rhport; (void) cfg_id; (void) cfg_param;
+ return false;
+}
+
//--------------------------------------------------------------------+
// Debug
//--------------------------------------------------------------------+
@@ -494,13 +499,14 @@ void tud_sof_cb_enable(bool en) {
usbd_sof_enable(_usbd_rhport, SOF_CONSUMER_USER, en);
}
-//--------------------------------------------------------------------+
-// USBD Task
-//--------------------------------------------------------------------+
bool tud_inited(void) {
return _usbd_rhport != RHPORT_INVALID;
}
+bool tud_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
+ return dcd_configure(rhport, cfg_id, cfg_param);
+}
+
bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
if (tud_inited()) {
return true; // skip if already initialized
@@ -624,6 +630,9 @@ bool tud_task_event_ready(void) {
return !osal_queue_empty(_usbd_q);
}
+//--------------------------------------------------------------------+
+// USBD Task
+//--------------------------------------------------------------------+
/* USB Device Driver task
* This top level thread manages all device controller event and delegates events to class-specific drivers.
* This should be called periodically within the mainloop or rtos thread.
diff --git a/src/device/usbd.h b/src/device/usbd.h
index c446638c3..efde9377f 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -33,10 +33,30 @@
extern "C" {
#endif
+// ConfigID for tud_configure()
+enum {
+ TUD_CFGID_INVALID = 0,
+ TUD_CFGID_DWC2 = 100,
+};
+
+typedef struct {
+ uint16_t bm_double_buffered; // bitmap of IN endpoints to be double buffered, only effective for bulk endpoints
+} tud_configure_dwc2_t;
+
+typedef union {
+ tud_configure_dwc2_t dwc2;
+} tud_configure_param_t;
+
//--------------------------------------------------------------------+
// Application API
//--------------------------------------------------------------------+
+// Configure device stack behavior with dynamic or port-specific parameters.
+// Should be called before initialization of the device stack
+// - cfg_id : configure ID from TUD_CFGID_* enum values
+// - cfg_param: configure data, structure depends on the ID
+bool tud_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);
+
// New API to replace tud_init() to init device stack on specific roothub port
bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init);
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index 00e81217b..ba40498e6 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -39,6 +39,7 @@
#define DWC2_DEBUG 2
#include "device/dcd.h"
+#include "device/usbd.h"
#include "device/usbd_pvt.h"
#include "dwc2_common.h"
@@ -76,6 +77,10 @@ CFG_TUD_MEM_SECTION static struct {
TUD_EPBUF_DEF(setup_packet, 8);
} _dcd_usbbuf;
+static tud_configure_dwc2_t _tud_cfg = {
+ .bm_double_buffered = 0
+};
+
TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) {
#if TU_CHECK_MCU(OPT_MCU_GD32VF103)
(void) dwc2;
@@ -186,7 +191,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t larges
return 13 + 1 + 2 * ((largest_ep_size / 4) + 1) + 2 * ep_count;
}
-static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
+static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size, bool is_bulk) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport];
const uint8_t ep_count = dwc2_controller->ep_count;
@@ -212,8 +217,9 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
_dcd_data.allocated_epin_count++;
}
- // If The TXFELVL is configured as half empty, the fifo must be twice the max_size.
- if ((dwc2->gahbcfg & GAHBCFG_TX_FIFO_EPMTY_LVL) == 0) {
+ // Enable double buffering if configured, only effective for non-periodic endpoints
+ // Since we queue only 1 control transfer at a time, it's only applicable for bulk IN endpoints
+ if (((_tud_cfg.bm_double_buffered & (1 << epnum)) != 0) && epnum > 0 && is_bulk) {
fifo_size *= 2;
}
@@ -248,7 +254,7 @@ static void dfifo_device_init(uint8_t rhport) {
dwc2->gdfifocfg = ((uint32_t) _dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top;
// Allocate FIFO for EP0 IN
- (void) dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE);
+ (void) dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE, false);
}
@@ -446,6 +452,16 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
//--------------------------------------------------------------------
// Controller API
//--------------------------------------------------------------------
+// optional dcd configuration, called by tud_configure()
+bool dcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
+ (void) rhport;
+ TU_VERIFY(cfg_id == TUD_CFGID_DWC2 && cfg_param != NULL);
+
+ const tud_configure_param_t* const cfg = (const tud_configure_param_t*) cfg_param;
+ _tud_cfg = cfg->dwc2;
+ return true;
+}
+
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
(void) rh_init;
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
@@ -492,9 +508,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
// Enable required interrupts
dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
- // TX FIFO empty level for interrupt is complete empty
uint32_t gahbcfg = dwc2->gahbcfg;
- gahbcfg |= GAHBCFG_TX_FIFO_EPMTY_LVL;
gahbcfg |= GAHBCFG_GINT; // Enable global interrupt
dwc2->gahbcfg = gahbcfg;
@@ -590,7 +604,8 @@ void dcd_sof_enable(uint8_t rhport, bool en) {
*------------------------------------------------------------------*/
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) {
- TU_ASSERT(dfifo_alloc(rhport, desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt)));
+ TU_ASSERT(dfifo_alloc(rhport, desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt),
+ desc_edpt->bmAttributes.xfer == TUSB_XFER_BULK));
edpt_activate(rhport, desc_edpt);
return true;
}
@@ -625,7 +640,7 @@ void dcd_edpt_close_all(uint8_t rhport) {
}
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
- TU_ASSERT(dfifo_alloc(rhport, ep_addr, largest_packet_size));
+ TU_ASSERT(dfifo_alloc(rhport, ep_addr, largest_packet_size, false));
return true;
}