aboutsummaryrefslogtreecommitdiffstats
path: root/src/stm32/usbotg.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2019-08-16 08:40:03 -0400
committerKevin O'Connor <kevin@koconnor.net>2019-08-16 21:03:47 -0400
commit8aca7764c32fc9308b701081aeb158cb433c4596 (patch)
treec6b0227daccaccbb40e84dd262d53f013234a8fb /src/stm32/usbotg.c
parent4ec6db7a87b2f0b0e033b87ca912818dc84cbe2f (diff)
downloadkutter-8aca7764c32fc9308b701081aeb158cb433c4596.tar.gz
kutter-8aca7764c32fc9308b701081aeb158cb433c4596.tar.xz
kutter-8aca7764c32fc9308b701081aeb158cb433c4596.zip
stm32: Simplify usbotg packet reading and writing
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/stm32/usbotg.c')
-rw-r--r--src/stm32/usbotg.c111
1 files changed, 54 insertions, 57 deletions
diff --git a/src/stm32/usbotg.c b/src/stm32/usbotg.c
index d263b280..b47643c3 100644
--- a/src/stm32/usbotg.c
+++ b/src/stm32/usbotg.c
@@ -57,40 +57,35 @@ fifo_configure(void)
fpos += ep_size;
}
-// Inspect the next packet on the rx queue
-static uint32_t
-peek_rx_queue(uint32_t ep)
+// Write a packet to a tx fifo
+static int_fast8_t
+fifo_write_packet(uint32_t ep, const uint8_t *src, uint32_t len)
{
- for (;;) {
- USB_OTG_OUTEndpointTypeDef *epo = EPOUT(ep);
- uint32_t ctl = epo->DOEPCTL;
- if (!(ctl & USB_OTG_DOEPCTL_EPENA) || ctl & USB_OTG_DOEPCTL_NAKSTS) {
- // Reenable packet reception if it got disabled by controller
- epo->DOEPTSIZ = 64 | (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos);
- epo->DOEPCTL = ctl | USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
- }
- uint32_t sts = OTG->GINTSTS;
- if (!(sts & USB_OTG_GINTSTS_RXFLVL))
- // No packet ready
- return 0;
- uint32_t grx = OTG->GRXSTSR;
- uint32_t pktsts = ((grx & USB_OTG_GRXSTSP_PKTSTS_Msk)
- >> USB_OTG_GRXSTSP_PKTSTS_Pos);
- if (pktsts != 1 && pktsts != 3 && pktsts != 4) {
- // A packet is ready
- if ((grx & USB_OTG_GRXSTSP_EPNUM_Msk) != ep)
- return 0;
- return grx;
- }
- // Discard informational entries from queue
- grx = OTG->GRXSTSP;
+ void *fifo = EPFIFO(ep);
+ USB_OTG_INEndpointTypeDef *epi = EPIN(ep);
+ epi->DIEPTSIZ = len | (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
+ epi->DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
+ int32_t count = len;
+ while (count >= 4) {
+ uint32_t data;
+ memcpy(&data, src, 4);
+ writel(fifo, data);
+ count -= 4;
+ src += 4;
}
+ if (count) {
+ uint32_t data = 0;
+ memcpy(&data, src, count);
+ writel(fifo, data);
+ }
+ return len;
}
// Read a packet from the rx queue
static int_fast8_t
fifo_read_packet(uint8_t *dest, uint_fast8_t max_len)
{
+ // Transfer data
void *fifo = EPFIFO(0);
uint32_t grx = OTG->GRXSTSP;
uint32_t bcnt = (grx & USB_OTG_GRXSTSP_BCNT) >> USB_OTG_GRXSTSP_BCNT_Pos;
@@ -108,24 +103,37 @@ fifo_read_packet(uint8_t *dest, uint_fast8_t max_len)
uint32_t extra = DIV_ROUND_UP(bcnt, 4) - DIV_ROUND_UP(xfer, 4);
while (extra--)
readl(fifo);
+
+ // Reenable packet reception if it got disabled by controller
+ USB_OTG_OUTEndpointTypeDef *epo = EPOUT(grx & USB_OTG_GRXSTSP_EPNUM_Msk);
+ uint32_t ctl = epo->DOEPCTL;
+ if (!(ctl & USB_OTG_DOEPCTL_EPENA) || ctl & USB_OTG_DOEPCTL_NAKSTS) {
+ epo->DOEPTSIZ = 64 | (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos);
+ epo->DOEPCTL = ctl | USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
+ }
return xfer;
}
-// Write a packet to a tx fifo
-static void
-fifo_write_packet(void *fifo, const uint8_t *src, uint32_t count)
+// Inspect the next packet on the rx queue
+static uint32_t
+peek_rx_queue(uint32_t ep)
{
- while (count >= 4) {
- uint32_t data;
- memcpy(&data, src, 4);
- writel(fifo, data);
- count -= 4;
- src += 4;
- }
- if (count) {
- uint32_t data = 0;
- memcpy(&data, src, count);
- writel(fifo, data);
+ for (;;) {
+ uint32_t sts = OTG->GINTSTS;
+ if (!(sts & USB_OTG_GINTSTS_RXFLVL))
+ // No packet ready
+ return 0;
+ uint32_t grx = OTG->GRXSTSR;
+ uint32_t pktsts = ((grx & USB_OTG_GRXSTSP_PKTSTS_Msk)
+ >> USB_OTG_GRXSTSP_PKTSTS_Pos);
+ if (pktsts != 1 && pktsts != 3 && pktsts != 4) {
+ // A packet is ready
+ if ((grx & USB_OTG_GRXSTSP_EPNUM_Msk) != ep)
+ return 0;
+ return grx;
+ }
+ // Discard informational entries from queue
+ fifo_read_packet(NULL, 0);
}
}
@@ -149,20 +157,16 @@ usb_read_bulk_out(void *data, uint_fast8_t max_len)
int_fast8_t
usb_send_bulk_in(void *data, uint_fast8_t len)
{
- USB_OTG_INEndpointTypeDef *epi = EPIN(USB_CDC_EP_BULK_IN);
- uint32_t len_d4 = DIV_ROUND_UP(len, 4);
- uint32_t ctl = epi->DIEPCTL;
+ uint32_t ctl = EPIN(USB_CDC_EP_BULK_IN)->DIEPCTL;
if (!(ctl & USB_OTG_DIEPCTL_USBAEP))
+ // Controller not enabled
return -2;
- if (ctl & USB_OTG_DIEPCTL_EPENA || len_d4 > epi->DTXFSTS) {
+ if (ctl & USB_OTG_DIEPCTL_EPENA) {
// Wait for space to transmit
OTGD->DIEPEMPMSK |= (1 << USB_CDC_EP_BULK_IN);
return -1;
}
- epi->DIEPTSIZ = len | (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
- epi->DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
- fifo_write_packet(EPFIFO(USB_CDC_EP_BULK_IN), data, len);
- return len;
+ return fifo_write_packet(USB_CDC_EP_BULK_IN, data, len);
}
int_fast8_t
@@ -221,20 +225,13 @@ usb_send_ep0(const void *data, uint_fast8_t len)
// Transfer interrupted
return -2;
}
- USB_OTG_INEndpointTypeDef *epi = EPIN(0);
- uint32_t len_d4 = DIV_ROUND_UP(len, 4);
- uint32_t ctl = epi->DIEPCTL;
- if (ctl & USB_OTG_DIEPCTL_EPENA || len_d4 > epi->DTXFSTS) {
+ if (EPIN(0)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) {
// Wait for space to transmit
OTGD->DIEPEMPMSK |= (1 << 0);
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
return -1;
}
- epi->DIEPTSIZ = len | (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
- epi->DIEPCTL = ((ctl & ~USB_OTG_DIEPCTL_STALL) | USB_OTG_DIEPCTL_EPENA
- | USB_OTG_DIEPCTL_CNAK);
- fifo_write_packet(EPFIFO(0), data, len);
- return len;
+ return fifo_write_packet(0, data, len);
}
void