stm32: Add usbfs double buffer support for bulk tx messages

Implement the usbfs fast buffer switching mechanism on the "bulk in"
endpoint.  This can improve the overall USB throughput and bus
utilization.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2023-09-23 15:31:52 -04:00
parent b1361d9e5b
commit cd8d57c2c6
1 changed files with 28 additions and 8 deletions

View File

@ -118,8 +118,8 @@ btable_configure(void)
epm_ep_desc_setup(USB_CDC_EP_ACM, BUFRX, 0); epm_ep_desc_setup(USB_CDC_EP_ACM, BUFRX, 0);
epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 0, USB_CDC_EP_BULK_OUT_SIZE); epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 0, USB_CDC_EP_BULK_OUT_SIZE);
epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 1, USB_CDC_EP_BULK_OUT_SIZE); epm_ep_desc_setup(USB_CDC_EP_BULK_OUT, 1, USB_CDC_EP_BULK_OUT_SIZE);
epm_ep_desc_setup(USB_CDC_EP_BULK_IN, BUFTX, 0); epm_ep_desc_setup(USB_CDC_EP_BULK_IN, 0, 0);
epm_ep_desc_setup(USB_CDC_EP_BULK_IN, BUFRX, 0); epm_ep_desc_setup(USB_CDC_EP_BULK_IN, 1, 0);
} }
// Read a packet stored in dedicated usb memory // Read a packet stored in dedicated usb memory
@ -236,15 +236,27 @@ usb_read_bulk_out(void *data, uint_fast8_t max_len)
return count; return count;
} }
static uint32_t bulk_in_push_count, bulk_in_pop_flag;
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)
{ {
uint32_t ep = USB_CDC_EP_BULK_IN, epr = USB_EPR[ep]; if (readl(&bulk_in_pop_flag))
if ((epr & USB_EPTX_STAT) != USB_EP_TX_NAK)
// No buffer space available // No buffer space available
return -1; return -1;
btable_write_packet(ep, BUFTX, data, len); uint32_t ep = USB_CDC_EP_BULK_IN;
USB_EPR[ep] = calc_epr_bits(epr, USB_EPTX_STAT, USB_EP_TX_VALID); int bufnum = bulk_in_push_count & 1;
bulk_in_push_count++;
btable_write_packet(ep, bufnum, data, len);
writel(&bulk_in_pop_flag, USB_EP_DTOG_RX);
// Check if hardware needs to be notified
uint32_t epr = USB_EPR[ep];
if (epr_is_dbuf_blocking(epr) && readl(&bulk_in_pop_flag)) {
writel(&bulk_in_pop_flag, 0);
USB_EPR[ep] = calc_epr_bits(epr, 0, 0) | USB_EP_DTOG_RX;
}
return len; return len;
} }
@ -305,6 +317,11 @@ usb_set_configure(void)
uint32_t ep = USB_CDC_EP_BULK_OUT; uint32_t ep = USB_CDC_EP_BULK_OUT;
bulk_out_pop_count = 0; bulk_out_pop_count = 0;
USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPRX_STAT, USB_EP_RX_VALID); USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPRX_STAT, USB_EP_RX_VALID);
ep = USB_CDC_EP_BULK_IN;
bulk_in_push_count = 0;
writel(&bulk_in_pop_flag, 0);
USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPTX_STAT, USB_EP_TX_VALID);
} }
@ -329,8 +346,9 @@ usb_reset(void)
bulk_out_push_flag = USB_EP_DTOG_TX; bulk_out_push_flag = USB_EP_DTOG_TX;
ep = USB_CDC_EP_BULK_IN; ep = USB_CDC_EP_BULK_IN;
USB_EPR[ep] = (USB_CDC_EP_BULK_IN | USB_EP_BULK USB_EPR[ep] = (USB_CDC_EP_BULK_IN | USB_EP_BULK | USB_EP_KIND
| USB_EP_RX_NAK | USB_EP_TX_NAK); | USB_EP_RX_NAK | USB_EP_TX_NAK);
bulk_in_pop_flag = USB_EP_DTOG_RX;
USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM; USB->CNTR = USB_CNTR_CTRM | USB_CNTR_RESETM;
USB->DADDR = USB_DADDR_EF; USB->DADDR = USB_DADDR_EF;
@ -350,7 +368,9 @@ USB_IRQHandler(void)
bulk_out_push_flag = 0; bulk_out_push_flag = 0;
usb_notify_bulk_out(); usb_notify_bulk_out();
} else if (ep == USB_CDC_EP_BULK_IN) { } else if (ep == USB_CDC_EP_BULK_IN) {
USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0); USB_EPR[ep] = (calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0)
| bulk_in_pop_flag);
bulk_in_pop_flag = 0;
usb_notify_bulk_in(); usb_notify_bulk_in();
} else if (ep == 0) { } else if (ep == 0) {
USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0); USB_EPR[ep] = calc_epr_bits(epr, USB_EP_CTR_RX | USB_EP_CTR_TX, 0);