stm32: Simplify usbotg packet reading and writing
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
4ec6db7a87
commit
8aca7764c3
|
@ -57,40 +57,35 @@ fifo_configure(void)
|
||||||
fpos += ep_size;
|
fpos += ep_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inspect the next packet on the rx queue
|
// Write a packet to a tx fifo
|
||||||
static uint32_t
|
static int_fast8_t
|
||||||
peek_rx_queue(uint32_t ep)
|
fifo_write_packet(uint32_t ep, const uint8_t *src, uint32_t len)
|
||||||
{
|
{
|
||||||
for (;;) {
|
void *fifo = EPFIFO(ep);
|
||||||
USB_OTG_OUTEndpointTypeDef *epo = EPOUT(ep);
|
USB_OTG_INEndpointTypeDef *epi = EPIN(ep);
|
||||||
uint32_t ctl = epo->DOEPCTL;
|
epi->DIEPTSIZ = len | (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
|
||||||
if (!(ctl & USB_OTG_DOEPCTL_EPENA) || ctl & USB_OTG_DOEPCTL_NAKSTS) {
|
epi->DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
|
||||||
// Reenable packet reception if it got disabled by controller
|
int32_t count = len;
|
||||||
epo->DOEPTSIZ = 64 | (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos);
|
while (count >= 4) {
|
||||||
epo->DOEPCTL = ctl | USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
|
uint32_t data;
|
||||||
|
memcpy(&data, src, 4);
|
||||||
|
writel(fifo, data);
|
||||||
|
count -= 4;
|
||||||
|
src += 4;
|
||||||
}
|
}
|
||||||
uint32_t sts = OTG->GINTSTS;
|
if (count) {
|
||||||
if (!(sts & USB_OTG_GINTSTS_RXFLVL))
|
uint32_t data = 0;
|
||||||
// No packet ready
|
memcpy(&data, src, count);
|
||||||
return 0;
|
writel(fifo, data);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a packet from the rx queue
|
// Read a packet from the rx queue
|
||||||
static int_fast8_t
|
static int_fast8_t
|
||||||
fifo_read_packet(uint8_t *dest, uint_fast8_t max_len)
|
fifo_read_packet(uint8_t *dest, uint_fast8_t max_len)
|
||||||
{
|
{
|
||||||
|
// Transfer data
|
||||||
void *fifo = EPFIFO(0);
|
void *fifo = EPFIFO(0);
|
||||||
uint32_t grx = OTG->GRXSTSP;
|
uint32_t grx = OTG->GRXSTSP;
|
||||||
uint32_t bcnt = (grx & USB_OTG_GRXSTSP_BCNT) >> USB_OTG_GRXSTSP_BCNT_Pos;
|
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);
|
uint32_t extra = DIV_ROUND_UP(bcnt, 4) - DIV_ROUND_UP(xfer, 4);
|
||||||
while (extra--)
|
while (extra--)
|
||||||
readl(fifo);
|
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;
|
return xfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a packet to a tx fifo
|
// Inspect the next packet on the rx queue
|
||||||
static void
|
static uint32_t
|
||||||
fifo_write_packet(void *fifo, const uint8_t *src, uint32_t count)
|
peek_rx_queue(uint32_t ep)
|
||||||
{
|
{
|
||||||
while (count >= 4) {
|
for (;;) {
|
||||||
uint32_t data;
|
uint32_t sts = OTG->GINTSTS;
|
||||||
memcpy(&data, src, 4);
|
if (!(sts & USB_OTG_GINTSTS_RXFLVL))
|
||||||
writel(fifo, data);
|
// No packet ready
|
||||||
count -= 4;
|
return 0;
|
||||||
src += 4;
|
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;
|
||||||
}
|
}
|
||||||
if (count) {
|
// Discard informational entries from queue
|
||||||
uint32_t data = 0;
|
fifo_read_packet(NULL, 0);
|
||||||
memcpy(&data, src, count);
|
|
||||||
writel(fifo, data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,20 +157,16 @@ usb_read_bulk_out(void *data, uint_fast8_t max_len)
|
||||||
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)
|
||||||
{
|
{
|
||||||
USB_OTG_INEndpointTypeDef *epi = EPIN(USB_CDC_EP_BULK_IN);
|
uint32_t ctl = EPIN(USB_CDC_EP_BULK_IN)->DIEPCTL;
|
||||||
uint32_t len_d4 = DIV_ROUND_UP(len, 4);
|
|
||||||
uint32_t ctl = epi->DIEPCTL;
|
|
||||||
if (!(ctl & USB_OTG_DIEPCTL_USBAEP))
|
if (!(ctl & USB_OTG_DIEPCTL_USBAEP))
|
||||||
|
// Controller not enabled
|
||||||
return -2;
|
return -2;
|
||||||
if (ctl & USB_OTG_DIEPCTL_EPENA || len_d4 > epi->DTXFSTS) {
|
if (ctl & USB_OTG_DIEPCTL_EPENA) {
|
||||||
// Wait for space to transmit
|
// Wait for space to transmit
|
||||||
OTGD->DIEPEMPMSK |= (1 << USB_CDC_EP_BULK_IN);
|
OTGD->DIEPEMPMSK |= (1 << USB_CDC_EP_BULK_IN);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
epi->DIEPTSIZ = len | (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
|
return fifo_write_packet(USB_CDC_EP_BULK_IN, data, len);
|
||||||
epi->DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
|
|
||||||
fifo_write_packet(EPFIFO(USB_CDC_EP_BULK_IN), data, len);
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int_fast8_t
|
int_fast8_t
|
||||||
|
@ -221,20 +225,13 @@ usb_send_ep0(const void *data, uint_fast8_t len)
|
||||||
// Transfer interrupted
|
// Transfer interrupted
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
USB_OTG_INEndpointTypeDef *epi = EPIN(0);
|
if (EPIN(0)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) {
|
||||||
uint32_t len_d4 = DIV_ROUND_UP(len, 4);
|
|
||||||
uint32_t ctl = epi->DIEPCTL;
|
|
||||||
if (ctl & USB_OTG_DIEPCTL_EPENA || len_d4 > epi->DTXFSTS) {
|
|
||||||
// Wait for space to transmit
|
// Wait for space to transmit
|
||||||
OTGD->DIEPEMPMSK |= (1 << 0);
|
OTGD->DIEPEMPMSK |= (1 << 0);
|
||||||
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
OTG->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
epi->DIEPTSIZ = len | (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
|
return fifo_write_packet(0, data, len);
|
||||||
epi->DIEPCTL = ((ctl & ~USB_OTG_DIEPCTL_STALL) | USB_OTG_DIEPCTL_EPENA
|
|
||||||
| USB_OTG_DIEPCTL_CNAK);
|
|
||||||
fifo_write_packet(EPFIFO(0), data, len);
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue