diff options
| author | Ha Thach <[email protected]> | 2021-04-16 01:59:47 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-04-16 01:59:47 +0700 |
| commit | c611199632b9288eff76c1c4bfdce5d8cc024748 (patch) | |
| tree | 8ccd5c0b34b4f1eb89276fce866ee34a9ff608e1 /src/portable | |
| parent | 93dffba0ac905d8525c3092a52888e1a5db96390 (diff) | |
| parent | c7e4a8616640165b48cfb0ba4f9346982faa4344 (diff) | |
Merge pull request #593 from hathach/edpt_ISO_xfer
Edpt iso xfer
Diffstat (limited to 'src/portable')
| -rw-r--r-- | src/portable/espressif/esp32s2/dcd_esp32s2.c | 172 | ||||
| -rw-r--r-- | src/portable/microchip/samg/dcd_samg.c | 35 | ||||
| -rw-r--r-- | src/portable/nuvoton/nuc120/dcd_nuc120.c | 60 | ||||
| -rw-r--r-- | src/portable/nuvoton/nuc121/dcd_nuc121.c | 59 | ||||
| -rw-r--r-- | src/portable/nuvoton/nuc505/dcd_nuc505.c | 82 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/dcd_rp2040.c | 3 | ||||
| -rw-r--r-- | src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 160 | ||||
| -rw-r--r-- | src/portable/st/synopsys/dcd_synopsys.c | 73 | ||||
| -rw-r--r-- | src/portable/template/dcd_template.c | 11 | ||||
| -rw-r--r-- | src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 81 |
10 files changed, 635 insertions, 101 deletions
diff --git a/src/portable/espressif/esp32s2/dcd_esp32s2.c b/src/portable/espressif/esp32s2/dcd_esp32s2.c index 703841759..edbc872fe 100644 --- a/src/portable/espressif/esp32s2/dcd_esp32s2.c +++ b/src/portable/espressif/esp32s2/dcd_esp32s2.c @@ -27,6 +27,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_ESP32S2 && TUSB_OPT_DEVICE_ENABLED @@ -59,6 +60,7 @@ typedef struct { uint8_t *buffer; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API uint16_t total_len; uint16_t queued_len; uint16_t max_size; @@ -319,6 +321,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->short_packet = false; @@ -354,6 +357,56 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void)rhport; + + // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 + TU_ASSERT(ff->item_size == 1); + + 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); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", + epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), + num_packets, total_bytes); + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if (dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; + USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } + } else { + // Each complete packet for OUT xfers triggers XFRC. + USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + return true; +} +#endif + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; @@ -462,35 +515,46 @@ static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; } - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; + // Common buffer read +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + // Ring buffer + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); + } + else +#endif + { + uint8_t to_recv_rem = to_recv_size % 4; + uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - // Do not assume xfer buffer is aligned. - uint8_t *base = (xfer->buffer + xfer->queued_len); + // Do not assume xfer buffer is aligned. + uint8_t *base = (xfer->buffer + xfer->queued_len); - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if (to_recv_size >= 4) { - for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (*rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; + // This for loop always runs at least once- skip if less than 4 bytes + // to collect. + if (to_recv_size >= 4) { + for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { + uint32_t tmp = (*rx_fifo); + base[i] = tmp & 0x000000FF; + base[i + 1] = (tmp & 0x0000FF00) >> 8; + base[i + 2] = (tmp & 0x00FF0000) >> 16; + base[i + 3] = (tmp & 0xFF000000) >> 24; + } } - } - // Do not read invalid bytes from RX FIFO. - if (to_recv_rem != 0) { - uint32_t tmp = (*rx_fifo); - uint8_t *last_32b_bound = base + to_recv_size_aligned; + // Do not read invalid bytes from RX FIFO. + if (to_recv_rem != 0) { + uint32_t tmp = (*rx_fifo); + uint8_t *last_32b_bound = base + to_recv_size_aligned; - last_32b_bound[0] = tmp & 0x000000FF; - if (to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if (to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + last_32b_bound[0] = tmp & 0x000000FF; + if (to_recv_rem > 1) { + last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + } + if (to_recv_rem > 2) { + last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + } } } @@ -510,37 +574,47 @@ static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, xfer->queued_len = xfer->total_len - remaining; uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if (to_xfer_size >= 4) { - for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | - (base[i + 2] << 16) | (base[i + 3] << 24); - (*tx_fifo) = tmp; - } +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); } + else +#endif + { + uint8_t to_xfer_rem = to_xfer_size % 4; + uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - // Do not read beyond end of buffer if not divisible by 4. - if (to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; + // Buffer might not be aligned to 32b, so we need to force alignment + // by copying to a temp var. + uint8_t *base = (xfer->buffer + xfer->queued_len); - tmp |= last_32b_bound[0]; - if (to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if (to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); + // This for loop always runs at least once- skip if less than 4 bytes + // to send off. + if (to_xfer_size >= 4) { + for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { + uint32_t tmp = base[i] | (base[i + 1] << 8) | + (base[i + 2] << 16) | (base[i + 3] << 24); + (*tx_fifo) = tmp; + } } - (*tx_fifo) = tmp; + // Do not read beyond end of buffer if not divisible by 4. + if (to_xfer_rem != 0) { + uint32_t tmp = 0; + uint8_t *last_32b_bound = base + to_xfer_size_aligned; + + tmp |= last_32b_bound[0]; + if (to_xfer_rem > 1) { + tmp |= (last_32b_bound[1] << 8); + } + if (to_xfer_rem > 2) { + tmp |= (last_32b_bound[2] << 16); + } + + (*tx_fifo) = tmp; + } } } diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 2f9f1097f..62fab8d17 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -25,6 +25,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_SAMG @@ -43,6 +44,7 @@ typedef struct { uint8_t* buffer; + // tu_fifo_t* ff; // TODO support dcd_edpt_xfer_fifo API uint16_t total_len; volatile uint16_t actual_len; uint16_t epsize; @@ -59,6 +61,7 @@ void xfer_epsize_set(xfer_desc_t* xfer, uint16_t epsize) void xfer_begin(xfer_desc_t* xfer, uint8_t * buffer, uint16_t total_bytes) { xfer->buffer = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->actual_len = 0; } @@ -66,6 +69,7 @@ void xfer_begin(xfer_desc_t* xfer, uint8_t * buffer, uint16_t total_bytes) void xfer_end(xfer_desc_t* xfer) { xfer->buffer = NULL; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = 0; xfer->actual_len = 0; } @@ -293,6 +297,14 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + return true; +} +#endif + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { @@ -402,7 +414,16 @@ void dcd_int_handler(uint8_t rhport) if (xact_len) { // write to EP fifo - xact_ep_write(epnum, xfer->buffer, xact_len); +#if 0 // TODO support dcd_edpt_xfer_fifo + if (xfer->ff) + { + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) &UDP->UDP_FDR[epnum], xact_len); + } + else +#endif + { + xact_ep_write(epnum, xfer->buffer, xact_len); + } // TX ready for transfer csr_set(epnum, UDP_CSR_TXPKTRDY_Msk); @@ -428,7 +449,17 @@ void dcd_int_handler(uint8_t rhport) uint16_t const xact_len = (uint16_t) ((UDP->UDP_CSR[epnum] & UDP_CSR_RXBYTECNT_Msk) >> UDP_CSR_RXBYTECNT_Pos); // Read from EP fifo - xact_ep_read(epnum, xfer->buffer, xact_len); +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) &UDP->UDP_FDR[epnum], xact_len); + } + else +#endif + { + xact_ep_read(epnum, xfer->buffer, xact_len); + } + xfer_packet_done(xfer); if ( 0 == xfer_packet_len(xfer) ) diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index dc48e54cc..5dc3bca21 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -34,6 +34,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC120) @@ -76,6 +77,7 @@ static bool active_ep0_xfer; 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_xfer_fifo() */ // TODO support dcd_edpt_xfer_fifo API 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 */ @@ -142,7 +144,17 @@ static void dcd_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); - memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); + } + else +#endif + { + memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + } + ep->MXPLD = bytes_now; } @@ -267,6 +279,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -286,6 +299,36 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + /* 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) + { + dcd_in_xfer(xfer, ep); + } + else + { + xfer->out_bytes_so_far = 0; + ep->MXPLD = xfer->max_packet_size; + } + + return true; +} +#endif + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -389,9 +432,19 @@ void dcd_int_handler(uint8_t rhport) if (out_ep) { /* copy the data from the PC to the previously provided buffer */ - memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); +#if 0 // // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); + } + else +#endif + { + memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + xfer->data_ptr += available_bytes; + } + xfer->out_bytes_so_far += available_bytes; - xfer->data_ptr += available_bytes; /* when the transfer is finished, alert TinyUSB; otherwise, accept more data */ if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) ) @@ -403,6 +456,7 @@ void dcd_int_handler(uint8_t rhport) { /* update the bookkeeping to reflect the data that has now been sent to the PC */ xfer->in_remaining_bytes -= available_bytes; + xfer->data_ptr += available_bytes; /* if more data to send, send it; otherwise, alert TinyUSB that we've finished */ diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index c9ead6de0..d50e82846 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -34,6 +34,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) @@ -78,6 +79,7 @@ static bool active_ep0_xfer; 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; // TODO support dcd_edpt_xfer_fifo API 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 */ @@ -144,7 +146,17 @@ static void dcd_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); - memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_read_n(xfer->ff, (void *) (USBD_BUF_BASE + ep->BUFSEG), bytes_now); + } + else +#endif + { + memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now); + } + ep->MXPLD = bytes_now; } @@ -273,6 +285,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -292,6 +305,36 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + /* 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) + { + dcd_in_xfer(xfer, ep); + } + else + { + xfer->out_bytes_so_far = 0; + ep->MXPLD = xfer->max_packet_size; + } + + return true; +} +#endif + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -400,9 +443,19 @@ void dcd_int_handler(uint8_t rhport) if (out_ep) { /* copy the data from the PC to the previously provided buffer */ - memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_write_n(xfer->ff, (const void *) (USBD_BUF_BASE + ep->BUFSEG), available_bytes); + } + else +#endif + { + memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes); + xfer->data_ptr += available_bytes; + } + xfer->out_bytes_so_far += available_bytes; - xfer->data_ptr += available_bytes; /* when the transfer is finished, alert TinyUSB; otherwise, accept more data */ if ( (xfer->total_bytes == xfer->out_bytes_so_far) || (available_bytes < xfer->max_packet_size) ) diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index a7961a687..b7bbb020b 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; // TODO support dcd_edpt_xfer_fifo API 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 */ @@ -163,8 +165,7 @@ static USBD_EP_T *ep_entry(uint8_t ep_addr, bool add) /* perform a non-control IN endpoint transfer; this is called by the ISR */ 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; + uint16_t const bytes_now = tu_min16(xfer->in_remaining_bytes, xfer->max_packet_size); /* precompute what amount of data will be left */ xfer->in_remaining_bytes -= bytes_now; @@ -180,20 +181,29 @@ 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 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) { - uint32_t u32; - memcpy(&u32, xfer->data_ptr, 4); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) (&ep->EPDAT_BYTE), bytes_now); + } + else +#endif + { + 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++; } - 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) - ep->EPRSPCTL = USBD_EPRSPCTL_SHORTTXEN_Msk; + if (bytes_now != xfer->max_packet_size) ep->EPRSPCTL = USBD_EPRSPCTL_SHORTTXEN_Msk; } /* called by dcd_init() as well as by the ISR during a USB bus reset */ @@ -385,6 +395,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to /* store away the information we'll needing now and later */ xfer->data_ptr = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->in_remaining_bytes = total_bytes; xfer->total_bytes = total_bytes; @@ -402,6 +413,38 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (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) + { + ep->EPINTEN = USBD_EPINTEN_BUFEMPTYIEN_Msk; + } + else + { + xfer->out_bytes_so_far = 0; + ep->EPINTEN = USBD_EPINTEN_RXPKIEN_Msk; + } + + return true; +} +#endif + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -615,12 +658,25 @@ 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 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) &ep->EPDAT_BYTE, tu_min16(available_bytes, xfer->total_bytes - xfer->out_bytes_so_far)); + } + else +#endif + { + 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; + } + } /* 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) ) + { dcd_event_xfer_complete(0, ep_addr, xfer->out_bytes_so_far, XFER_RESULT_SUCCESS, true); + } #endif } diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index f844a0c65..7731078b5 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -35,7 +35,8 @@ #include "pico/fix/rp2040_usb_device_enumeration.h" #endif - +#include "osal/osal.h" +#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 18f0bc8e1..b8b0fc104 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -102,6 +102,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if defined(STM32F102x6) || defined(STM32F102xB) || \ defined(STM32F103x6) || defined(STM32F103xB) || \ @@ -165,6 +166,7 @@ TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligne typedef struct { uint8_t * buffer; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API uint16_t total_len; uint16_t queued_len; uint16_t pma_ptr; @@ -197,6 +199,9 @@ static void dcd_pma_free(uint8_t ep_addr); static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, size_t wNBytes); static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wNBytes); +//static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes); +//static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes); + // Using a function due to better type checks // This seems better than having to do type casts everywhere else static inline void reg16_clear_bits(__IO uint16_t *reg, uint16_t mask) { @@ -476,8 +481,17 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if (count != 0U) { - dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), - *pcd_ep_rx_address_ptr(USB,EPindex), count); +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + dcd_read_packet_memory_ff(xfer->ff, *pcd_ep_rx_address_ptr(USB,EPindex), count); + } + else +#endif + { + dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), *pcd_ep_rx_address_ptr(USB,EPindex), count); + } + xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -804,7 +818,17 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix) len = xfer->max_packet_size; } uint16_t oldAddr = *pcd_ep_tx_address_ptr(USB,ep_ix); - dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len); + +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + dcd_write_packet_memory_ff(xfer->ff, oldAddr, len); + } + else +#endif + { + dcd_write_packet_memory(oldAddr, &(xfer->buffer[xfer->queued_len]), len); + } xfer->queued_len = (uint16_t)(xfer->queued_len + len); pcd_set_ep_tx_cnt(USB,ep_ix,len); @@ -821,6 +845,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir); xfer->buffer = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; @@ -847,6 +872,39 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = xfer_ctl_ptr(epnum,dir); + + xfer->buffer = NULL; + // xfer->ff = ff; // TODO support dcd_edpt_xfer_fifo API + xfer->total_len = total_bytes; + xfer->queued_len = 0; + + if ( dir == TUSB_DIR_OUT ) + { + if(total_bytes > xfer->max_packet_size) + { + pcd_set_ep_rx_cnt(USB,epnum,xfer->max_packet_size); + } else { + pcd_set_ep_rx_cnt(USB,epnum,total_bytes); + } + pcd_set_ep_rx_status(USB, epnum, USB_EP_RX_VALID); + } + else // IN + { + dcd_transmit_packet(xfer,epnum); + } + return true; +} +#endif + void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void)rhport; @@ -920,8 +978,55 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API /** - * @brief Copy a buffer from user memory area to packet memory area (PMA). + * @brief Copy from FIFO to packet memory area (PMA). + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ + +// THIS FUNCTION IS UNTESTED + +static bool dcd_write_packet_memory_ff(tu_fifo_t * ff, uint16_t dst, uint16_t wNBytes) +{ + // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + void * src; + uint16_t len = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes); // We want to read from the FIFO + TU_VERIFY(len && dcd_write_packet_memory(dst, src, len)); // and write it into the PMA + tu_fifo_advance_read_pointer(ff, len); + + // Check for wrapped part + if (len < wNBytes) + { + // Get remaining wrapped length + uint16_t len2 = tu_fifo_get_linear_read_info(ff, 0, &src, wNBytes - len); + TU_VERIFY(len2); + + // Update destination pointer + dst += len; + + // Since PMA is accessed 16-bit wise we need to handle the case when a 16 bit value was split + if (len % 2) // If len is uneven there is a byte left to copy + { + // Since PMA can accessed only 16 bit-wise we copy the last byte again + tu_fifo_backward_read_pointer(ff, 1); // Move one byte back and copy two bytes for the PMA + tu_fifo_read_n(ff, (void *) &pma[PMA_STRIDE*(dst>>1)], 2); // Since EP FIFOs must be of item size 1 this is safe to do + dst++; + len2--; + } + + TU_VERIFY(dcd_write_packet_memory(dst, src, len2)); + tu_fifo_advance_write_pointer(ff, len2); + } + + return true; +} +#endif + +/** + * @brief Copy a buffer from packet memory area (PMA) to user memory area. * Uses byte-access of system memory and 16-bit access of packet memory * @param wNBytes no. of bytes to be copied. * @retval None @@ -955,5 +1060,52 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API +/** + * @brief Copy a buffer from user packet memory area (PMA) to FIFO. + * Uses byte-access of system memory and 16-bit access of packet memory + * @param wNBytes no. of bytes to be copied. + * @retval None + */ + +// THIS FUNCTION IS UNTESTED + +static bool dcd_read_packet_memory_ff(tu_fifo_t * ff, uint16_t src, uint16_t wNBytes) +{ + // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies + // Check for first linear part + void * dst; + uint16_t len = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes); + TU_VERIFY(len && dcd_read_packet_memory(dst, src, len)); + tu_fifo_advance_write_pointer(ff, len); + + // Check for wrapped part + if (len < wNBytes) + { + // Get remaining wrapped length + uint16_t len2 = tu_fifo_get_linear_write_info(ff, 0, &dst, wNBytes - len); + TU_VERIFY(len2); + + // Update source pointer + src += len; + + // Since PMA is accessed 16-bit wise we need to handle the case when a 16 bit value was split + if (len % 2) // If len is uneven there is a byte left to copy + { + uint32_t temp = pma[PMA_STRIDE*(src>>1)]; + *((uint8_t *)dst++) = ((temp >> 8) & 0xFF); + src++; + len2--; + } + + TU_VERIFY(dcd_read_packet_memory(dst, src, len2)); + tu_fifo_advance_write_pointer(ff, len2); + } + + return true; +} + +#endif + #endif diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 548438b68..0fe7c2a3c 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -28,6 +28,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on @@ -135,6 +136,7 @@ static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; typedef struct { uint8_t * buffer; + tu_fifo_t * ff; uint16_t total_len; uint16_t max_size; uint8_t interval; @@ -644,6 +646,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; + xfer->ff = NULL; xfer->total_len = total_bytes; // EP0 can only handle one packet @@ -668,6 +671,35 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +// The number of bytes has to be given explicitly to allow more flexible control of how many +// bytes should be written and second to keep the return value free to give back a boolean +// success message. If total_bytes is too big, the FIFO will copy only what is available +// into the USB buffer! +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 + TU_ASSERT(ff->item_size == 1); + + 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); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t const short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if(short_packet_size > 0 || (total_bytes == 0)) num_packets++; + + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); + + return true; +} + static void dcd_edpt_disable (uint8_t rhport, uint8_t ep_addr, bool stall) { (void) rhport; @@ -867,10 +899,19 @@ static void handle_rxflvl_ints(uint8_t rhport, USB_OTG_OUTEndpointTypeDef * out_ xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); // Read packet off RxFIFO - read_fifo_packet(rhport, xfer->buffer, bcnt); + if (xfer->ff) + { + // Ring buffer + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, bcnt); + } + else + { + // Linear buffer + read_fifo_packet(rhport, xfer->buffer, bcnt); - // Increment pointer to xfer data - xfer->buffer += bcnt; + // Increment pointer to xfer data + xfer->buffer += bcnt; + } // Truncate transfer length in case of short packet if(bcnt < xfer->max_size) { @@ -966,22 +1007,30 @@ static void handle_epin_ints(uint8_t rhport, USB_OTG_DeviceTypeDef * dev, USB_OT uint16_t remaining_packets = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_PKTCNT_Msk) >> USB_OTG_DIEPTSIZ_PKTCNT_Pos; // Process every single packet (only whole packets can be written to fifo) - for(uint16_t i = 0; i < remaining_packets; i++){ - uint16_t remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; + for(uint16_t i = 0; i < remaining_packets; i++) + { + uint16_t const remaining_bytes = (in_ep[n].DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) >> USB_OTG_DIEPTSIZ_XFRSIZ_Pos; + // Packet can not be larger than ep max size - uint16_t packet_size = tu_min16(remaining_bytes, xfer->max_size); + uint16_t const packet_size = tu_min16(remaining_bytes, xfer->max_size); // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current // EP has to be checked if the buffer can take another WHOLE packet - if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)){ - break; - } + if(packet_size > ((in_ep[n].DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV_Msk) << 2)) break; // Push packet to Tx-FIFO - write_fifo_packet(rhport, n, xfer->buffer, packet_size); + if (xfer->ff) + { + usb_fifo_t tx_fifo = FIFO_BASE(rhport, n); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, packet_size); + } + else + { + write_fifo_packet(rhport, n, xfer->buffer, packet_size); - // Increment pointer to xfer data - xfer->buffer += packet_size; + // Increment pointer to xfer data + xfer->buffer += packet_size; + } } // Turn off TXFE if all bytes are written. diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 618812416..d8c8753d3 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -25,6 +25,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if CFG_TUSB_MCU == OPT_MCU_NONE @@ -104,6 +105,16 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return false; } +// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + (void) ep_addr; + (void) ff; + (void) total_bytes; + return false; +} + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index e08c3536a..48e9dd592 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -26,6 +26,7 @@ */ #include "tusb_option.h" +#include "common/tusb_fifo.h" #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MSP430x5xx ) @@ -48,6 +49,7 @@ uint8_t _setup_packet[8]; typedef struct { uint8_t * buffer; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API uint16_t total_len; uint16_t queued_len; uint16_t max_size; @@ -306,6 +308,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); xfer->buffer = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API xfer->total_len = total_bytes; xfer->queued_len = 0; xfer->short_packet = false; @@ -344,6 +347,36 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t return true; } +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void) rhport; + + 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); + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + ep_regs_t ep_regs = EP_REGS(epnum, dir); + + if(dir == TUSB_DIR_OUT) + { + ep_regs[BCTX] &= ~NAK; + } + else + { + USBIEPIFG |= (1 << epnum); + } + + return true; +} +#endif + void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -443,22 +476,32 @@ static void receive_packet(uint8_t ep_num) to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; } - uint8_t * base = (xfer->buffer + xfer->queued_len); - - if(ep_num == 0) +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) { - volatile uint8_t * ep0out_buf = &USBOEP0BUF; - for(uint16_t i = 0; i < to_recv_size; i++) - { - base[i] = ep0out_buf[i]; - } + volatile uint8_t * ep_buf = (ep_num == 0) ? &USBOEP0BUF : (&USBSTABUFF + (ep_regs[BBAX] << 3)); + tu_fifo_write_n(xfer->ff, (const void *) ep_buf, to_recv_size); } else +#endif { - volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); - for(uint16_t i = 0; i < to_recv_size ; i++) + uint8_t * base = (xfer->buffer + xfer->queued_len); + + if(ep_num == 0) + { + volatile uint8_t * ep0out_buf = &USBOEP0BUF; + for(uint16_t i = 0; i < to_recv_size; i++) + { + base[i] = ep0out_buf[i]; + } + } + else { - base[i] = ep_buf[i]; + volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); + for(uint16_t i = 0; i < to_recv_size ; i++) + { + base[i] = ep_buf[i]; + } } } @@ -499,7 +542,6 @@ static void transmit_packet(uint8_t ep_num) } // Then actually commit to transmit a packet. - uint8_t * base = (xfer->buffer + xfer->queued_len); uint16_t remaining = xfer->total_len - xfer->queued_len; uint8_t xfer_size = (xfer->max_size < xfer->total_len) ? xfer->max_size : remaining; @@ -513,6 +555,7 @@ static void transmit_packet(uint8_t ep_num) if(ep_num == 0) { volatile uint8_t * ep0in_buf = &USBIEP0BUF; + uint8_t * base = (xfer->buffer + xfer->queued_len); for(uint16_t i = 0; i < xfer_size; i++) { ep0in_buf[i] = base[i]; @@ -526,9 +569,19 @@ static void transmit_packet(uint8_t ep_num) ep_regs_t ep_regs = EP_REGS(ep_num, TUSB_DIR_IN); volatile uint8_t * ep_buf = &USBSTABUFF + (ep_regs[BBAX] << 3); - for(int i = 0; i < xfer_size; i++) +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_read_n(xfer->ff, (void *) ep_buf, xfer_size); + } + else +#endif { - ep_buf[i] = base[i]; + uint8_t * base = (xfer->buffer + xfer->queued_len); + for(int i = 0; i < xfer_size; i++) + { + ep_buf[i] = base[i]; + } } ep_regs[BCTX] = (ep_regs[BCTX] & 0x80) + (xfer_size & 0x7F); |
