mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2026-01-01 01:41:18 +01:00
Merge #19459
19459: drivers/usbus_synopsys_dwc2: fix interrupt handling in DMA mode r=dylad a=gschorcht ### Contribution description This PR fixes the interrupt handling for IN endpoints in DMA mode. In DMA mode, both the `XFRC` (Transfer Complete) interrupt and the `TXFE` (TX FIFO Empty) interrupt for IN EP1 ... EPn were used to generate the `USBDEV_EVENT_TR_COMPLETE`. This led to problems with USBUS MSC. With this fix, the `TXFE` interrupt is used only in non-DMA mode or only for IN EP0 in DMA mode while the `XFRC` (Transfer Complete) is used only in DMA mode for IN EP1 ... EPn. ### Testing procedure This PR should work together with PR #19458 for SD Card interface for a board with USB HS port, for example: ``` USEMODULE='sdcard_spi mtd_sdcard_default periph_usbdev_hs_ulpi' \ CFLAGS='-DSDCARD_SPI_PARAM_CLK=GPIO_PIN\(PORT_I,1\) -DSDCARD_SPI_PARAM_MISO=GPIO_PIN\(PORT_B,14\) -DSDCARD_SPI_PARAM_MOSI=GPIO_PIN\(PORT_B,15\) -DSDCARD_SPI_PARAM_CS=GPIO_PIN\(PORT_A,8\)' \ BOARD=stm32f746g-disco make -j8 -C tests/usbus_msc flash ``` It should still work for CDC ECM for such a board: ``` USEMODULE='periph_usbdev_hs_ulpi stdio_cdc_acm' BOARD=stm32f746g-disco make -j8 -C tests/usbus_cdc_ecm flash ``` ### Issues/PRs references Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
This commit is contained in:
commit
10e4d5047c
@ -1333,8 +1333,9 @@ static int _usbdev_ep_xmit(usbdev_ep_t *ep, uint8_t *buf, size_t len)
|
||||
_in_regs(conf, ep->num)->DIEPTSIZ = dieptsiz;
|
||||
|
||||
/* 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 only used in non-dma mode */
|
||||
* 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;
|
||||
|
||||
@ -1447,18 +1448,22 @@ 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 all endpoints when DMA is enabled */
|
||||
if (status & USB_OTG_DIEPINT_XFRC && _uses_dma(conf)) {
|
||||
/* XFRC interrupt is used for EP1..EPn in DMA mode but
|
||||
* cleared in any case */
|
||||
if (status & USB_OTG_DIEPINT_XFRC) {
|
||||
_in_regs(conf, ep->num)->DIEPINT = USB_OTG_DIEPINT_XFRC;
|
||||
if (ep->num != 0) {
|
||||
if (_uses_dma(conf) && (ep->num != 0)) {
|
||||
usbdev->usbdev.epcb(ep, USBDEV_EVENT_TR_COMPLETE);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* TXFE empty interrupt is only used with DMA disabled */
|
||||
/* 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) {
|
||||
_device_regs(conf)->DIEPEMPMSK &= ~(1 << ep->num);
|
||||
usbdev->usbdev.epcb(ep, USBDEV_EVENT_TR_COMPLETE);
|
||||
if (!_uses_dma(conf) || (ep->num == 0)) {
|
||||
usbdev->usbdev.epcb(ep, USBDEV_EVENT_TR_COMPLETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user