summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZixun LI <[email protected]>2025-09-12 21:19:46 +0200
committerGitHub <[email protected]>2025-09-12 21:19:46 +0200
commit841cac6dbeab6fa69c57bd5b2751b57308667085 (patch)
tree675174d31cb346a87694a132b14ce3d23f32dc5f /src
parent2027ac246791caa9f1dc03e9727b60d90bee0f2d (diff)
parent8515e47ad9980f8ad380913bda72425b1bb83648 (diff)
Merge pull request #3152 from Milek7/sb-ep
stm32_fsdev: Allow configuring single-buffered isochronous endpoints.
Diffstat (limited to 'src')
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c47
-rw-r--r--src/portable/st/stm32_fsdev/fsdev_ch32.h5
-rw-r--r--src/portable/st/stm32_fsdev/fsdev_stm32.h45
3 files changed, 89 insertions, 8 deletions
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index 5d6033a66..3b9825e25 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -333,8 +333,13 @@ static void handle_ctr_rx(uint32_t ep_id) {
xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT);
uint8_t buf_id;
- if (is_iso) {
- buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; // ISO are double buffered
+#if FSDEV_USE_SBUF_ISO == 0
+ bool const dbl_buf = is_iso;
+#else
+ bool const dbl_buf = false;
+#endif
+ if (dbl_buf) {
+ buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1;
} else {
buf_id = BTABLE_BUF_RX;
}
@@ -529,10 +534,16 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type)
return i;
}
+#if FSDEV_USE_SBUF_ISO == 0
+ bool const dbl_buf = ep_type == TUSB_XFER_ISOCHRONOUS;
+#else
+ bool const dbl_buf = false;
+#endif
+
// If EP of current direction is not allocated
- // Except for ISO endpoint, both direction should be free
+ // For double-buffered mode both directions needs to be free
if (!ep_alloc_status[i].allocated[dir] &&
- (ep_type != TUSB_XFER_ISOCHRONOUS || !ep_alloc_status[i].allocated[dir ^ 1])) {
+ (!dbl_buf || !ep_alloc_status[i].allocated[dir ^ 1])) {
// Check if EP number is the same
if (ep_alloc_status[i].ep_num == 0xFF || ep_alloc_status[i].ep_num == epnum) {
// One EP pair has to be the same type
@@ -654,9 +665,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet
uint8_t const dir = tu_edpt_dir(ep_addr);
uint8_t const ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS);
- /* Create a packet memory buffer area. Enable double buffering for devices with 2048 bytes PMA,
- for smaller devices double buffering occupy too much space. */
-#if FSDEV_PMA_SIZE > 1024u
+#if CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP != 0
uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true);
uint16_t pma_addr2 = pma_addr >> 16;
#else
@@ -664,8 +673,12 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet
uint16_t pma_addr2 = pma_addr;
#endif
+#if FSDEV_USE_SBUF_ISO == 0
btable_set_addr(ep_idx, 0, pma_addr);
btable_set_addr(ep_idx, 1, pma_addr2);
+#else
+ btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr);
+#endif
xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir);
xfer->ep_idx = ep_idx;
@@ -686,10 +699,23 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep)
uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK;
ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_TX | USB_EP_CTR_RX;
+#if FSDEV_USE_SBUF_ISO != 0
+ ep_reg |= USB_EP_KIND;
+
+ ep_change_status(&ep_reg, dir, EP_STAT_DISABLED);
+ ep_change_dtog(&ep_reg, dir, 0);
+
+ if (dir == TUSB_DIR_IN) {
+ ep_reg &= ~(USB_EPRX_STAT | USB_EP_DTOG_RX);
+ } else {
+ ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX);
+ }
+#else
ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED);
ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED);
ep_change_dtog(&ep_reg, dir, 0);
ep_change_dtog(&ep_reg, (tusb_dir_t)(1 - dir), 1);
+#endif
ep_write(ep_idx, ep_reg, true);
@@ -704,7 +730,12 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) {
bool const is_iso = ep_is_iso(ep_reg);
uint8_t buf_id;
- if (is_iso) {
+#if FSDEV_USE_SBUF_ISO == 0
+ bool const dbl_buf = is_iso;
+#else
+ bool const dbl_buf = false;
+#endif
+ if (dbl_buf) {
buf_id = (ep_reg & USB_EP_DTOG_TX) ? 1 : 0;
} else {
buf_id = BTABLE_BUF_TX;
diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h
index 518197c47..ceebb6dab 100644
--- a/src/portable/st/stm32_fsdev/fsdev_ch32.h
+++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h
@@ -54,9 +54,14 @@
#endif
#define FSDEV_PMA_SIZE (512u)
+#define FSDEV_USE_SBUF_ISO 0
#define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL)
#define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL)
+#ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP
+ #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 0
+#endif
+
/**************************** 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) */
diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h
index ccf31e035..95f40269a 100644
--- a/src/portable/st/stm32_fsdev/fsdev_stm32.h
+++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h
@@ -36,6 +36,7 @@
#include "stm32f0xx.h"
#define FSDEV_PMA_SIZE (1024u)
#define FSDEV_REG_BASE USB_BASE
+ #define FSDEV_HAS_SBUF_ISO 0
// F0x2 models are crystal-less
// All have internal D+ pull-up
// 070RB: 2 x 16 bits/word memory LPM Support, BCD Support
@@ -44,6 +45,7 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
#include "stm32f1xx.h"
#define FSDEV_PMA_SIZE (512u)
+ #define FSDEV_HAS_SBUF_ISO 0
// NO internal Pull-ups
// *B, and *C: 2 x 16 bits/word
@@ -55,6 +57,7 @@
defined(STM32F373xC)
#include "stm32f3xx.h"
#define FSDEV_PMA_SIZE (512u)
+ #define FSDEV_HAS_SBUF_ISO 0
// NO internal Pull-ups
// *B, and *C: 1 x 16 bits/word
// PMA dedicated to USB (no sharing with CAN)
@@ -64,6 +67,7 @@
defined(STM32F303xD) || defined(STM32F303xE)
#include "stm32f3xx.h"
#define FSDEV_PMA_SIZE (1024u)
+ #define FSDEV_HAS_SBUF_ISO 0
// 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.
@@ -71,18 +75,22 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32L0
#include "stm32l0xx.h"
#define FSDEV_PMA_SIZE (1024u)
+ #define FSDEV_HAS_SBUF_ISO 0
#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
#include "stm32l1xx.h"
#define FSDEV_PMA_SIZE (512u)
+ #define FSDEV_HAS_SBUF_ISO 0
#elif CFG_TUSB_MCU == OPT_MCU_STM32G4
#include "stm32g4xx.h"
#define FSDEV_PMA_SIZE (1024u)
+ #define FSDEV_HAS_SBUF_ISO 0
#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
#include "stm32g0xx.h"
#define FSDEV_PMA_SIZE (2048u)
+ #define FSDEV_HAS_SBUF_ISO 1
#define USB USB_DRD_FS
#define USB_EP_CTR_RX USB_EP_VTRX
@@ -107,6 +115,7 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32C0
#include "stm32c0xx.h"
#define FSDEV_PMA_SIZE (2048u)
+ #define FSDEV_HAS_SBUF_ISO 1
#define USB USB_DRD_FS
#define USB_EP_CTR_RX USB_CHEP_VTRX
#define USB_EP_CTR_TX USB_CHEP_VTTX
@@ -121,6 +130,7 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32H5
#include "stm32h5xx.h"
#define FSDEV_PMA_SIZE (2048u)
+ #define FSDEV_HAS_SBUF_ISO 1
#define USB USB_DRD_FS
#define USB_EP_CTR_RX USB_EP_VTRX
@@ -145,16 +155,19 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
#include "stm32wbxx.h"
#define FSDEV_PMA_SIZE (1024u)
+ #define FSDEV_HAS_SBUF_ISO 0
/* ST provided header has incorrect value of USB_PMAADDR */
#define FSDEV_PMA_BASE USB1_PMAADDR
#elif CFG_TUSB_MCU == OPT_MCU_STM32L4
#include "stm32l4xx.h"
#define FSDEV_PMA_SIZE (1024u)
+ #define FSDEV_HAS_SBUF_ISO 0
#elif CFG_TUSB_MCU == OPT_MCU_STM32L5
#include "stm32l5xx.h"
#define FSDEV_PMA_SIZE (1024u)
+ #define FSDEV_HAS_SBUF_ISO 0
#ifndef USB_PMAADDR
#define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS))
@@ -163,6 +176,7 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32U5
#include "stm32u5xx.h"
#define FSDEV_PMA_SIZE (2048u)
+ #define FSDEV_HAS_SBUF_ISO 1
#define USB USB_DRD_FS
#define USB_EP_CTR_RX USB_EP_VTRX
@@ -187,6 +201,7 @@
#elif CFG_TUSB_MCU == OPT_MCU_STM32U0
#include "stm32u0xx.h"
#define FSDEV_PMA_SIZE (2048u)
+ #define FSDEV_HAS_SBUF_ISO 1
#define USB USB_DRD_FS
#define USB_EP_CTR_RX USB_EP_VTRX
@@ -248,6 +263,36 @@
#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 )
+#ifndef FSDEV_HAS_SBUF_ISO
+ #error "FSDEV_HAS_SBUF_ISO not defined"
+#endif
+
+#ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP
+ // Default configuration for double-buffered isochronous endpoints:
+ // - Enable double buffering on devices with >1KB Packet Memory Area (PMA)
+ // to improve isochronous transfer reliability and performance
+ // - Disable on devices with limited PMA to conserve memory space
+ #if FSDEV_PMA_SIZE > 1024u
+ #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 1
+ #else
+ #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 0
+ #endif
+#endif
+
+#if FSDEV_HAS_SBUF_ISO != 0 && CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP == 0
+ // SBUF_ISO configuration:
+ // - Some STM32 devices have special hardware support for single-buffered isochronous endpoints
+ // - When SBUF_ISO bit is available and double buffering is disabled:
+ // Enable SBUF_ISO to optimize endpoint register usage (one half of endpoint pair register)
+ #define FSDEV_USE_SBUF_ISO 1
+#else
+ // When either:
+ // - Hardware doesn't support SBUF_ISO feature, or
+ // - Double buffering is enabled for isochronous endpoints
+ // We must use the entire endpoint pair register
+ #define FSDEV_USE_SBUF_ISO 0
+#endif
+
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+