1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:12:57 +01:00

drivers/usbdev_synopsys_dwc2: use XFRC for IN EPs in non-DMA mode

XFRC (Transfer Complete) interrupts are now also used for IN EPs in non-DMA mode. TXFE (TX FIFO Empty) interrupts are not necessarily needed but are still enabled.
This commit is contained in:
Gunar Schorcht 2023-04-15 15:11:30 +02:00
parent 1a37d3b9e0
commit 1ccafe1621

View File

@ -1027,13 +1027,14 @@ static void _usbdev_init(usbdev_t *dev)
* Only needed when using DMA, otherwise the RX FIFO not empty
* interrupt is used */
_device_regs(conf)->DOEPMSK |= USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_STUPM;
_device_regs(conf)->DIEPMSK |= USB_OTG_DIEPMSK_XFRCM;
}
else {
/* Use RXFLVL (RX FIFO Level) interrupt for IN EPs in non-DMA mode */
gint_mask |= USB_OTG_GINTMSK_RXFLVLM;
}
_device_regs(conf)->DIEPMSK |= USB_OTG_DIEPMSK_XFRCM;
/* Clear the interrupt flags and unmask those interrupts */
_global_regs(conf)->GINTSTS |= gint_mask;
_global_regs(conf)->GINTMSK |= gint_mask;
@ -1370,19 +1371,12 @@ static int _usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len)
* controller in the peripheral
*/
/* Packet count seems not to decrement below 1 and thus is broken in
* combination with the TXFE irq, it does however work with control
* transfers and when using DMA */
uint32_t dieptsiz = (len & USB_OTG_DIEPTSIZ_XFRSIZ_Msk);
if (ep->num == 0 || _uses_dma(conf)) {
dieptsiz |= (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
}
_in_regs(conf, ep->num)->DIEPTSIZ = dieptsiz;
/* PKTCNT has to be set for all IN EPs to use the XFRC interrupt */
_in_regs(conf, ep->num)->DIEPTSIZ = (len & USB_OTG_DIEPTSIZ_XFRSIZ_Msk) |
(1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos);
/* Intentionally enabling this before the FIFO is filled, unmasking the
* interrupts after the FIFO is filled doesn't always trigger the ISR */
/* TX FIFO empty interrupt is used for EP0..EPn in non-DMA mode and
* for EP0 for DMA mode */
_device_regs(conf)->DAINTMSK |= 1 << ep->num;
_device_regs(conf)->DIEPEMPMSK |= 1 << ep->num;
@ -1495,22 +1489,15 @@ static void _usbdev_ep_esr(usbdev_ep_t *ep)
if (ep->dir == USB_EP_DIR_IN) {
uint32_t status = _in_regs(conf, ep->num)->DIEPINT;
/* XFRC interrupt is used for EP1..EPn in DMA mode but
* cleared in any case */
/* XFRC (Transfer Complete) interrupt is used to signal that the
* transfer is complete. XFRC interrupts only work if the packet
* count (PKTCNT) is set in DIEPTSIZ register. */
if (status & USB_OTG_DIEPINT_XFRC) {
_in_regs(conf, ep->num)->DIEPINT = USB_OTG_DIEPINT_XFRC;
if (_uses_dma(conf) && (ep->num != 0)) {
usbdev->usbdev.epcb(ep, USBDEV_EVENT_TR_COMPLETE);
}
usbdev->usbdev.epcb(ep, USBDEV_EVENT_TR_COMPLETE);
}
else
/* TXFE interrupt is used for all EPs in non-DMA mode but only for EP0
* in DMA mode. It is disabled in any case. */
if (status & USB_OTG_DIEPINT_TXFE) {
else if (status & USB_OTG_DIEPINT_TXFE) {
_device_regs(conf)->DIEPEMPMSK &= ~(1 << ep->num);
if (!_uses_dma(conf) || (ep->num == 0)) {
usbdev->usbdev.epcb(ep, USBDEV_EVENT_TR_COMPLETE);
}
}
}
else {