rp2040: Add support for double buffering on USB bulk tx packets

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2023-09-24 02:24:54 -04:00
parent 90427fe30e
commit 472fd32cab
1 changed files with 10 additions and 4 deletions

View File

@ -101,22 +101,26 @@ usb_read_bulk_out(void *data, uint_fast8_t max_len)
return c; return c;
} }
static uint32_t bulk_in_pop_count;
int_fast8_t int_fast8_t
usb_send_bulk_in(void *data, uint_fast8_t len) usb_send_bulk_in(void *data, uint_fast8_t len)
{ {
// Check if there is room for this packet // Check if there is room for this packet
uint32_t bipc = bulk_in_pop_count, bufnum = bipc & 1;
uint32_t ep = USB_CDC_EP_BULK_IN; uint32_t ep = USB_CDC_EP_BULK_IN;
volatile uint16_t *epbp = lookup_epbufctrl(ep, 0, 0); volatile uint16_t *epbp = lookup_epbufctrl(ep, 0, bufnum);
uint32_t epb = *epbp; uint32_t epb = *epbp;
if (epb & (USB_BUF_CTRL_AVAIL|USB_BUF_CTRL_FULL)) if (epb & (USB_BUF_CTRL_AVAIL|USB_BUF_CTRL_FULL))
return -1; return -1;
// Determine the next packet header // Determine the next packet header
uint32_t pid = next_data_pid(epb); bulk_in_pop_count = bipc + 1;
uint32_t pid = bufnum ? USB_BUF_CTRL_DATA1_PID : 0;
uint32_t new_epb = USB_BUF_CTRL_FULL | USB_BUF_CTRL_LAST | pid | len; uint32_t new_epb = USB_BUF_CTRL_FULL | USB_BUF_CTRL_LAST | pid | len;
*epbp = new_epb; *epbp = new_epb;
barrier(); barrier();
// Copy the packet to the hw buffer // Copy the packet to the hw buffer
memcpy(usb_buf_addr(ep, 0), data, len); memcpy(usb_buf_addr(ep, bufnum), data, len);
// Inform the USB hardware of the available packet // Inform the USB hardware of the available packet
barrier(); barrier();
*epbp = new_epb | USB_BUF_CTRL_AVAIL; *epbp = new_epb | USB_BUF_CTRL_AVAIL;
@ -219,7 +223,8 @@ usb_set_address(uint_fast8_t addr)
void void
usb_set_configure(void) usb_set_configure(void)
{ {
usb_dpram->ep_buf_ctrl[USB_CDC_EP_BULK_IN].in = USB_BUF_CTRL_DATA1_PID; bulk_in_pop_count = 0;
usb_dpram->ep_buf_ctrl[USB_CDC_EP_BULK_IN].in = 0;
bulk_out_push_count = 0; bulk_out_push_count = 0;
uint32_t epb0 = USB_BUF_CTRL_AVAIL | USB_BUF_CTRL_LAST | DPBUF_SIZE; uint32_t epb0 = USB_BUF_CTRL_AVAIL | USB_BUF_CTRL_LAST | DPBUF_SIZE;
@ -361,6 +366,7 @@ endpoint_setup(void)
| (USB_ENDPOINT_XFER_BULK << EP_CTRL_BUFFER_TYPE_LSB)); | (USB_ENDPOINT_XFER_BULK << EP_CTRL_BUFFER_TYPE_LSB));
usb_dpram->ep_ctrl[USB_CDC_EP_BULK_OUT-1].out = ep_out; usb_dpram->ep_ctrl[USB_CDC_EP_BULK_OUT-1].out = ep_out;
uint32_t ep_in = (EP_CTRL_ENABLE_BITS | usb_buf_offset(USB_CDC_EP_BULK_IN) uint32_t ep_in = (EP_CTRL_ENABLE_BITS | usb_buf_offset(USB_CDC_EP_BULK_IN)
| EP_CTRL_DOUBLE_BUFFERED_BITS
| EP_CTRL_INTERRUPT_PER_BUFFER | EP_CTRL_INTERRUPT_PER_BUFFER
| (USB_ENDPOINT_XFER_BULK << EP_CTRL_BUFFER_TYPE_LSB)); | (USB_ENDPOINT_XFER_BULK << EP_CTRL_BUFFER_TYPE_LSB));
usb_dpram->ep_ctrl[USB_CDC_EP_BULK_IN-1].in = ep_in; usb_dpram->ep_ctrl[USB_CDC_EP_BULK_IN-1].in = ep_in;