diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c71ad6b8e..ef533e540 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -135,7 +135,6 @@ typedef struct CFG_TUSB_MCU == OPT_MCU_RP2040 || /* Don't want to change driver */ \ CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI || /* Intermediate software buffer required */ \ CFG_TUSB_MCU == OPT_MCU_CXD56 || /* No clue how driver works */ \ - CFG_TUSB_MCU == OPT_MCU_DA1469X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_NRF5X || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_LPC11UXX || /* Uses DMA - Ok for FIFO, had no time for implementation */ \ CFG_TUSB_MCU == OPT_MCU_LPC13XX || \ diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 59f728d08..8e1a5ddfd 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -25,6 +25,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_DA1469X @@ -196,6 +197,7 @@ typedef struct typedef struct { EPx_REGS * regs; uint8_t * buffer; + tu_fifo_t * ff; // Total length of current transfer uint16_t total_len; // Bytes transferred so far @@ -292,7 +294,6 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) EPx_REGS *regs = xfer->regs; uint8_t const epnum = tu_edpt_number(xfer->ep_addr); - src = &xfer->buffer[xfer->transferred]; left_to_send = xfer->total_len - xfer->transferred; if (left_to_send > xfer->max_packet_size - xfer->last_packet_size) { @@ -301,12 +302,51 @@ static void fill_tx_fifo(xfer_ctl_t * xfer) // Loop checks TCOUNT all the time since this value is saturated to 31 // and can't be read just once before. - while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) + + if (xfer->ff) { - regs->txd = *src++; - xfer->last_packet_size++; - left_to_send--; + // Since TCOUNT is to be considered, we handle the FIFO reading manually here + // As we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + uint8_t * src; + uint16_t len = tu_fifo_get_linear_read_info(xfer->ff, 0, &src, left_to_send); // We want to read from the FIFO + uint16_t len1 = len; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + len1--; + } + + tu_fifo_advance_read_pointer(ff, len-len1); + left_to_send -= (len-len1); + + // Check for wrapped part + if ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) && left_to_send > 0) + { + len = tu_fifo_get_linear_read_info(xfer->ff, 0, &src, left_to_send); // We want to read from the FIFO + len1 = len; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && len1 > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + len1--; + } + tu_fifo_advance_read_pointer(ff, len-len1); + left_to_send -= (len-len1); + } } + else + { + src = &xfer->buffer[xfer->transferred]; + while ((regs->txs & USB_USB_TXS1_REG_USB_TCOUNT_Msk) > 0 && left_to_send > 0) + { + regs->txd = *src++; + xfer->last_packet_size++; + left_to_send--; + } + } + if (epnum != 0) { if (left_to_send > 0) @@ -363,13 +403,14 @@ static void start_rx_packet(xfer_ctl_t *xfer) xfer->last_packet_size = 0; if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE) { - if (try_allocate_dma(epnum, TUSB_DIR_OUT)) + if (try_allocate_dma(epnum, TUSB_DIR_OUT) && !xfer->ff) { start_rx_dma(&xfer->regs->rxd, xfer->buffer + xfer->transferred, size); } else { // Other endpoint is using DMA in that direction, fall back to interrupts. + // Or if an ISO EP transfer was scheduled, currently not handled by DMA! // For endpoint size greater then FIFO size enable FIFO level warning interrupt // when FIFO has less then 17 bytes free. xfer->regs->rxc |= USB_USB_RXC1_REG_USB_RFWL_Msk; @@ -409,7 +450,7 @@ static void start_tx_packet(xfer_ctl_t *xfer) regs->txc = USB_USB_TXC1_REG_USB_IGN_ISOMSK_Msk; if (xfer->data1) xfer->regs->txc |= USB_USB_TXC1_REG_USB_TOGGLE_TX_Msk; - if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN)) + if (xfer->max_packet_size > FIFO_SIZE && remaining > FIFO_SIZE && try_allocate_dma(epnum, TUSB_DIR_IN) && !xfer->ff) { // Whole packet will be put in FIFO by DMA. Set LAST bit before start. start_tx_dma(xfer->buffer + xfer->transferred, ®s->txd, size); @@ -430,9 +471,16 @@ static void read_rx_fifo(xfer_ctl_t *xfer, uint16_t bytes_in_fifo) if (remaining < bytes_in_fifo) receive_this_time = remaining; - uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; + if (xfer->ff) + { + tu_fifo_write_n(xfer->ff, (const void *) ®s->rxd, receive_this_time); + } + else + { + uint8_t *buf = xfer->buffer + xfer->transferred + xfer->last_packet_size; - for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; + for (int i = 0; i < receive_this_time; ++i) buf[i] = regs->rxd; + } xfer->last_packet_size += receive_this_time; } @@ -918,6 +966,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t (void)rhport; xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; xfer->last_packet_size = 0; xfer->transferred = 0; @@ -934,6 +983,41 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t return true; } +bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + + (void)rhport; + + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->last_packet_size = 0; + xfer->transferred = 0; + + if (dir == TUSB_DIR_IN) + { + tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); + } + else + { + tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); + } + + if (dir == TUSB_DIR_OUT) + { + start_rx_packet(xfer); + } + else // IN + { + start_tx_packet(xfer); + } + + return true; +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 5f8c44638..1d0bb5107 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -684,7 +684,7 @@ bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_ uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = NULL; // Indicates a FIFO shall be used + xfer->buffer = NULL; xfer->ff = ff; xfer->total_len = total_bytes;