Merge pull request #3396 from hathach/hwfifo_post

HWFIFO post fixup
This commit is contained in:
Ha Thach
2025-12-10 18:51:02 +07:00
committed by GitHub
5 changed files with 71 additions and 95 deletions

View File

@ -65,40 +65,6 @@
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
// Use ring buffer if it's available, some MCUs need extra RAM requirements
// For DWC2 enable ring buffer will disable DMA (if available)
#ifndef TUD_AUDIO_PREFER_RING_BUFFER
#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX || \
defined(TUP_USBIP_DWC2)
#define TUD_AUDIO_PREFER_RING_BUFFER 0
#else
#define TUD_AUDIO_PREFER_RING_BUFFER 1
#endif
#endif
// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer
// is available or driver is would need to be changed dramatically
// Only STM32 and ChipIdea HS use non-linear buffer for now
// Ring buffer is incompatible with dcache, since neither address nor size is aligned to cache line
#if defined(TUP_USBIP_DWC2) || \
defined(TUP_USBIP_FSDEV) || \
CFG_TUSB_MCU == OPT_MCU_RX63X || \
CFG_TUSB_MCU == OPT_MCU_RX65X || \
CFG_TUSB_MCU == OPT_MCU_RX72N || \
CFG_TUSB_MCU == OPT_MCU_LPC18XX || \
CFG_TUSB_MCU == OPT_MCU_LPC43XX || \
CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX || \
CFG_TUSB_MCU == OPT_MCU_MSP432E4
#if TUD_AUDIO_PREFER_RING_BUFFER && !CFG_TUD_MEM_DCACHE_ENABLE
#define USE_LINEAR_BUFFER 0
#else
#define USE_LINEAR_BUFFER 1
#endif
#else
#define USE_LINEAR_BUFFER 1
#endif
// Declaration of buffers
// Check for maximum supported numbers
@ -107,12 +73,12 @@
#endif
// Put swap buffer in USB section only if necessary
#if USE_LINEAR_BUFFER
#if !CFG_TUD_EDPT_DEDICATED_HWFIFO
#define IN_SW_BUF_MEM_ATTR TU_ATTR_ALIGNED(4)
#else
#define IN_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN
#endif
#if USE_LINEAR_BUFFER
#if !CFG_TUD_EDPT_DEDICATED_HWFIFO
#define OUT_SW_BUF_MEM_ATTR TU_ATTR_ALIGNED(4)
#else
#define OUT_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN
@ -135,7 +101,7 @@ tu_static IN_SW_BUF_MEM_ATTR struct {
// Linear buffer TX in case:
// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR
#if CFG_TUD_AUDIO_ENABLE_EP_IN && USE_LINEAR_BUFFER
#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_EDPT_DEDICATED_HWFIFO
tu_static CFG_TUD_MEM_SECTION struct {
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0
TUD_EPBUF_DEF(buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX);
@ -147,7 +113,7 @@ tu_static CFG_TUD_MEM_SECTION struct {
TUD_EPBUF_DEF(buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX);
#endif
} lin_buf_in;
#endif// CFG_TUD_AUDIO_ENABLE_EP_IN && USE_LINEAR_BUFFER
#endif// CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_EDPT_DEDICATED_HWFIFO
// EP OUT software buffers
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
@ -166,7 +132,7 @@ tu_static OUT_SW_BUF_MEM_ATTR struct {
// Linear buffer RX in case:
// - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && USE_LINEAR_BUFFER
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_EDPT_DEDICATED_HWFIFO
tu_static CFG_TUD_MEM_SECTION struct {
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0
TUD_EPBUF_DEF(buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX);
@ -178,7 +144,7 @@ tu_static CFG_TUD_MEM_SECTION struct {
TUD_EPBUF_DEF(buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX);
#endif
} lin_buf_out;
#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && USE_LINEAR_BUFFER
#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_EDPT_DEDICATED_HWFIFO
// Control buffer
CFG_TUD_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SZ];
@ -287,14 +253,12 @@ typedef struct
#endif
// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && USE_LINEAR_BUFFER
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_EDPT_DEDICATED_HWFIFO
uint8_t *lin_buf_out;
#define USE_LINEAR_BUFFER_RX 1
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_IN && USE_LINEAR_BUFFER
#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_EDPT_DEDICATED_HWFIFO
uint8_t *lin_buf_in;
#define USE_LINEAR_BUFFER_TX 1
#endif
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
@ -302,14 +266,6 @@ typedef struct
#endif
} audiod_function_t;
#ifndef USE_LINEAR_BUFFER_TX
#define USE_LINEAR_BUFFER_TX 0
#endif
#ifndef USE_LINEAR_BUFFER_RX
#define USE_LINEAR_BUFFER_RX 0
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ep_out_ff)
#else
@ -498,7 +454,7 @@ tu_fifo_t *tud_audio_n_get_ep_out_ff(uint8_t func_id) {
static bool audiod_rx_xfer_isr(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) {
uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio);
#if USE_LINEAR_BUFFER_RX
#if !CFG_TUD_EDPT_DEDICATED_HWFIFO
// Data currently is in linear buffer, copy into EP OUT FIFO
TU_VERIFY(0 < tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received));
@ -572,7 +528,7 @@ static bool audiod_tx_xfer_isr(uint8_t rhport, audiod_function_t * audio, uint16
#else
n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz);// Limit up to max packet size, more can not be done for ISO
#endif
#if USE_LINEAR_BUFFER_TX
#if !CFG_TUD_EDPT_DEDICATED_HWFIFO
tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx);
TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx, true));
#else
@ -730,32 +686,31 @@ void audiod_init(void) {
break;
#endif
}
#endif// CFG_TUD_AUDIO_ENABLE_EP_IN
// Initialize linear buffers
#if USE_LINEAR_BUFFER_TX
// Initialize linear buffers
#if !CFG_TUD_EDPT_DEDICATED_HWFIFO
switch (i) {
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0
case 0:
audio->lin_buf_in = lin_buf_in.buf_1;
break;
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0
case 1:
audio->lin_buf_in = lin_buf_in.buf_2;
break;
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0
case 2:
audio->lin_buf_in = lin_buf_in.buf_3;
break;
#endif
#endif
}
#endif// USE_LINEAR_BUFFER_TX
#endif// !CFG_TUD_EDPT_DEDICATED_HWFIFO
#endif// CFG_TUD_AUDIO_ENABLE_EP_IN
// Initialize OUT EP FIFO if required
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
switch (i) {
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
case 0:
@ -773,28 +728,28 @@ void audiod_init(void) {
break;
#endif
}
#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT
// Initialize linear buffers
#if USE_LINEAR_BUFFER_RX
#if !CFG_TUD_EDPT_DEDICATED_HWFIFO
// Initialize linear buffers
switch (i) {
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0
case 0:
audio->lin_buf_out = lin_buf_out.buf_1;
break;
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0
case 1:
audio->lin_buf_out = lin_buf_out.buf_2;
break;
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0
case 2:
audio->lin_buf_out = lin_buf_out.buf_3;
break;
#endif
#endif
}
#endif// USE_LINEAR_BUFFER_RX
#endif// !CFG_TUD_EDPT_DEDICATED_HWFIFO
#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
switch (i) {
@ -1207,7 +1162,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p
audiod_parse_flow_control_params(audio, p_desc_parse_for_params);
#endif
// Schedule first transmit if alternate interface is not zero, as sample data is available a ZLP is loaded
#if USE_LINEAR_BUFFER_TX
#if !CFG_TUD_EDPT_DEDICATED_HWFIFO
TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, 0, false));
#else
// Send everything in ISO EP FIFO
@ -1226,7 +1181,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p
audio->ep_out_sz = tu_edpt_packet_size(desc_ep);
// Prepare for incoming data
#if USE_LINEAR_BUFFER_RX
#if !CFG_TUD_EDPT_DEDICATED_HWFIFO
TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz, false));
#else
TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz, false));

View File

@ -65,15 +65,13 @@ typedef struct TU_ATTR_PACKED {
}tu_edpt_state_t;
typedef struct {
struct TU_ATTR_PACKED {
bool is_host : 1; // 1: host, 0: device
bool is_mps512 : 1; // 1: 512, 0: 64 since stream is used for Bulk only
};
bool is_host; // 1: host, 0: device
uint8_t ep_addr;
uint16_t ep_bufsize;
uint8_t *ep_buf; // set to NULL to use xfer_fifo when CFG_TUD_EDPT_DEDICATED_HWFIFO = 1
tu_fifo_t ff;
uint16_t mps;
// mutex: read if rx, otherwise write
OSAL_MUTEX_DEF(ff_mutexdef);
@ -113,7 +111,7 @@ bool tu_edpt_stream_deinit(tu_edpt_stream_t* s);
// Open an endpoint stream
TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) {
s->ep_addr = desc_ep->bEndpointAddress;
s->is_mps512 = tu_edpt_packet_size(desc_ep) == 512;
s->mps = tu_edpt_packet_size(desc_ep);
}
TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_is_opened(const tu_edpt_stream_t *s) {

View File

@ -1480,7 +1480,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
TU_LOG_USBD(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes);
TU_LOG_USBD(" Queue FIFO EP %02X with %u bytes ... ", ep_addr, total_bytes);
// Attempt to transfer on a busy endpoint, sound like a race condition !
TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);

View File

@ -419,8 +419,7 @@ static bool stream_release(uint8_t hwid, tu_edpt_stream_t *s) {
//--------------------------------------------------------------------+
bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint32_t last_xferred_bytes) {
// ZLP condition: no pending data, last transferred bytes is multiple of packet size
const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS;
TU_VERIFY(tu_fifo_empty(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (mps - 1))));
TU_VERIFY(tu_fifo_empty(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (s->mps - 1))));
TU_VERIFY(stream_claim(hwid, s));
TU_ASSERT(stream_xfer(hwid, s, 0));
return true;
@ -476,8 +475,7 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf
// flush if fifo has more than packet size or
// in rare case: fifo depth is configured too small (which never reach packet size)
const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS;
if ((tu_fifo_count(&s->ff) >= mps) || (tu_fifo_depth(&s->ff) < mps)) {
if ((tu_fifo_count(&s->ff) >= s->mps) || (tu_fifo_depth(&s->ff) < s->mps)) {
tu_edpt_stream_write_xfer(hwid, s);
}
return ret;
@ -521,21 +519,22 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t *s) {
} else
#endif
{
const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS;
uint16_t available = tu_fifo_remaining(&s->ff);
// Prepare for incoming data but only allow what we can store in the ring buffer.
// TODO Actually we can still carry out the transfer, keeping count of received bytes
// and slowly move it to the FIFO when read().
// This pre-check reduces endpoint claiming
TU_VERIFY(available >= mps);
TU_VERIFY(available >= s->mps);
TU_VERIFY(stream_claim(hwid, s), 0);
available = tu_fifo_remaining(&s->ff); // re-get available since fifo can be changed
if (available >= mps) {
if (available >= s->mps) {
// multiple of packet size limit by ep bufsize
uint16_t count = (uint16_t) (available & ~(mps - 1));
count = tu_min16(count, s->ep_bufsize);
uint16_t count = (uint16_t) (available & ~(s->mps - 1));
if (s->ep_buf != NULL) {
count = tu_min16(count, s->ep_bufsize);
}
TU_ASSERT(stream_xfer(hwid, s, count), 0);
return count;
} else {

View File

@ -309,7 +309,7 @@
#define CFG_TUD_EDPT_DEDICATED_HWFIFO 1
#endif
#if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE
#if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE
#define CFG_TUH_EDPT_DEDICATED_HWFIFO 1
#endif
#endif
@ -321,10 +321,18 @@
#ifndef CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT
#define CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT 0
#endif
#define CFG_TUD_CI_HS_VBUS_CHARGE CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT
#endif
// CI_HS support FIFO transfer if endpoint buffer is 4k aligned and size is multiple of 4k, also DCACHE is disabled
#ifndef CFG_TUD_CI_HS_EPBUF_4K_ALIGNED
#define CFG_TUD_CI_HS_EPBUF_4K_ALIGNED 0
#endif
#if CFG_TUD_CI_HS_EPBUF_4K_ALIGNED && !CFG_TUD_MEM_DCACHE_ENABLE
#define CFG_TUD_EDPT_DEDICATED_HWFIFO 1
#endif
//------------- pio-usb -------------//
// Enable PIO-USB software host controller
#ifndef CFG_TUH_RPI_PIO_USB
@ -335,11 +343,27 @@
#define CFG_TUD_RPI_PIO_USB 0
#endif
// MAX3421 Host controller option
//------------ MAX3421 -------------//
// Enable MAX3421 USB host controller
#ifndef CFG_TUH_MAX3421
#define CFG_TUH_MAX3421 0
#endif
//------------ FSDEV --------------//
#if defined(TUP_USBIP_FSDEV)
#define CFG_TUD_EDPT_DEDICATED_HWFIFO 1
#endif
//------------ MUSB --------------//
#if defined(TUP_USBIP_MUSB)
#define CFG_TUD_EDPT_DEDICATED_HWFIFO 0 // need testing to enable
#endif
//------------ RUSB2 --------------//
#if defined(TUP_USBIP_RUSB2)
#define CFG_TUD_EDPT_DEDICATED_HWFIFO 0 // need testing to enable
#endif
//--------------------------------------------------------------------
// RootHub Mode detection
//--------------------------------------------------------------------