summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReinhard Panhuber <[email protected]>2021-02-13 21:00:55 +0100
committerReinhard Panhuber <[email protected]>2021-02-13 21:00:55 +0100
commitb634b5958b92fc2352ea20e279e010d8bf4f2df2 (patch)
treeb5b9544cfcee52499fcc1be909e06b6fa31fe5b2
parent0c3dc8f99bc3bdce40164904d6705f7112b80d9d (diff)
Implement dcd_edpt_iso_xfer() for INTERRUPT driven dcd_nuc505
-rw-r--r--src/portable/nuvoton/nuc505/dcd_nuc505.c68
1 files changed, 58 insertions, 10 deletions
diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c
index a7961a687..92656488d 100644
--- a/src/portable/nuvoton/nuc505/dcd_nuc505.c
+++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c
@@ -34,6 +34,7 @@
*/
#include "tusb_option.h"
+#include "common/tusb_fifo.h"
#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505)
@@ -94,6 +95,7 @@ static uint32_t bufseg_addr;
static struct xfer_ctl_t
{
uint8_t *data_ptr; /* data_ptr tracks where to next copy data to (for OUT) or from (for IN) */
+ tu_fifo_t * ff; /* pointer to FIFO required for dcd_edpt_iso_xfer() */
union {
uint16_t in_remaining_bytes; /* for IN endpoints, we track how many bytes are left to transfer */
uint16_t out_bytes_so_far; /* but for OUT endpoints, we track how many bytes we've transferred so far */
@@ -164,7 +166,6 @@ static USBD_EP_T *ep_entry(uint8_t ep_addr, bool add)
static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep)
{
uint16_t bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size);
- uint16_t countdown = bytes_now;
/* precompute what amount of data will be left */
xfer->in_remaining_bytes -= bytes_now;
@@ -180,16 +181,24 @@ static void dcd_userEP_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep)
}
/* provided buffers are thankfully 32-bit aligned, allowing most data to be transfered as 32-bit */
- while (countdown > 3)
+ if (xfer->data_ptr)
{
- uint32_t u32;
- memcpy(&u32, xfer->data_ptr, 4);
+ uint16_t countdown = bytes_now;
+ while (countdown > 3)
+ {
+ uint32_t u32;
+ memcpy(&u32, xfer->data_ptr, 4);
- ep->EPDAT = u32;
- xfer->data_ptr += 4; countdown -= 4;
+ ep->EPDAT = u32;
+ xfer->data_ptr += 4; countdown -= 4;
+ }
+ while (countdown--)
+ ep->EPDAT_BYTE = *xfer->data_ptr++;
+ }
+ else
+ {
+ tu_fifo_read_n(xfer->ff, (void *) (ep->EPDAT_BYTE), bytes_now);
}
- while (countdown--)
- ep->EPDAT_BYTE = *xfer->data_ptr++;
/* for short packets, we must nudge the peripheral to say 'that's all folks' */
if (bytes_now != xfer->max_packet_size)
@@ -402,6 +411,38 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to
return true;
}
+bool dcd_edpt_iso_xfer (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+{
+ (void) rhport;
+
+ TU_ASSERT(0x80 != ep_addr && 0x00 != ep_addr); // Must not be used for control stuff
+
+ /* mine the data for the information we need */
+ tusb_dir_t dir = tu_edpt_dir(ep_addr);
+ USBD_EP_T *ep = ep_entry(ep_addr, false);
+ struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP];
+
+ /* store away the information we'll needing now and later */
+ xfer->data_ptr = NULL; // Indicates a FIFO shall be used
+ xfer->ff = ff;
+ xfer->in_remaining_bytes = total_bytes;
+ xfer->total_bytes = total_bytes;
+
+ if (TUSB_DIR_IN == dir)
+ {
+ tu_fifo_set_copy_mode_write(ff, TU_FIFO_COPY_CST); // For the PHY in nuc505 the source and destination pointer have to be constant!
+ ep->EPINTEN = USBD_EPINTEN_BUFEMPTYIEN_Msk;
+ }
+ else
+ {
+ tu_fifo_set_copy_mode_read(ff, TU_FIFO_COPY_CST); // For the PHY in nuc505 the source and destination pointer have to be constant!
+ xfer->out_bytes_so_far = 0;
+ ep->EPINTEN = USBD_EPINTEN_RXPKIEN_Msk;
+ }
+
+ return true;
+}
+
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
@@ -615,8 +656,15 @@ void dcd_int_handler(uint8_t rhport)
#else
uint16_t const available_bytes = ep->EPDATCNT & USBD_EPDATCNT_DATCNT_Msk;
/* copy the data from the PC to the previously provided buffer */
- for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++)
- *xfer->data_ptr++ = ep->EPDAT_BYTE;
+ if (xfer->data_ptr)
+ {
+ for (int count = 0; (count < available_bytes) && (xfer->out_bytes_so_far < xfer->total_bytes); count++, xfer->out_bytes_so_far++)
+ *xfer->data_ptr++ = ep->EPDAT_BYTE;
+ }
+ else
+ {
+ tu_fifo_write_n(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far));
+ }
/* when the transfer is finished, alert TinyUSB; otherwise, continue accepting more data */
if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) )