usb/dwc: Corrected how packets are read and unloaded from the DWC2 FIFOs on the H7

This commit is contained in:
dragonmux
2024-04-18 17:16:23 +01:00
committed by Piotr Esden-Tempski
parent d9779685ae
commit 5e6c423100

View File

@@ -253,20 +253,30 @@ uint16_t dwc_ep_write_packet(usbd_device *usbd_dev, uint8_t addr, const void *bu
uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, void *buf, uint16_t len) uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, void *buf, uint16_t len)
{ {
int i;
uint32_t *buf32 = buf;
#if defined(__ARM_ARCH_6M__)
uint8_t *buf8 = buf;
uint32_t word32;
#endif /* defined(__ARM_ARCH_6M__) */
uint32_t extra;
/* We do not need to know the endpoint address since there is only one /* We do not need to know the endpoint address since there is only one
* receive FIFO for all endpoints. * receive FIFO for all endpoints.
*/ */
(void)addr; (void)addr;
#if defined(STM32H7)
const size_t count = MIN(len, usbd_dev->rxbcnt);
uint8_t *const buf8 = buf;
/* Figure out where to copy the data from */
const volatile uint32_t *const fifo = (const volatile uint32_t *)(usbd_dev->driver->base_address + OTG_FIFO(0));
/* Copy the data out of the FIFO for this endpoint */
for (size_t offset = 0; offset < count; offset += 4) {
const uint32_t data = fifo[offset >> 2U];
const size_t amount = MIN(count - offset, 4U);
memcpy(buf8 + offset, &data, amount);
}
usbd_dev->rxbcnt -= count;
return count;
#else
len = MIN(len, usbd_dev->rxbcnt); len = MIN(len, usbd_dev->rxbcnt);
int i = 0;
uint32_t *buf32 = buf;
/* ARMv7M supports non-word-aligned accesses, ARMv6M does not. */ /* ARMv7M supports non-word-aligned accesses, ARMv6M does not. */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
for (i = len; i >= 4; i -= 4) { for (i = len; i >= 4; i -= 4) {
@@ -276,6 +286,7 @@ uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, void *buf, uint
#endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */ #endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */
#if defined(__ARM_ARCH_6M__) #if defined(__ARM_ARCH_6M__)
uint8_t *buf8 = buf;
/* Take care of word-aligned and non-word-aligned buffers */ /* Take care of word-aligned and non-word-aligned buffers */
if (((uint32_t)buf8 & 0x3) == 0) { if (((uint32_t)buf8 & 0x3) == 0) {
for (i = len; i >= 4; i -= 4) { for (i = len; i >= 4; i -= 4) {
@@ -284,7 +295,7 @@ uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, void *buf, uint
} }
} else { } else {
for (i = len; i >= 4; i -= 4) { for (i = len; i >= 4; i -= 4) {
word32 = REBASE(OTG_FIFO(0)); const uint32_t word32 = REBASE(OTG_FIFO(0));
memcpy(buf8, &word32, 4); memcpy(buf8, &word32, 4);
usbd_dev->rxbcnt -= 4; usbd_dev->rxbcnt -= 4;
buf8 += 4; buf8 += 4;
@@ -295,7 +306,7 @@ uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, void *buf, uint
#endif /* defined(__ARM_ARCH_6M__) */ #endif /* defined(__ARM_ARCH_6M__) */
if (i) { if (i) {
extra = REBASE(OTG_FIFO(0)); const uint32_t extra = REBASE(OTG_FIFO(0));
/* we read 4 bytes from the fifo, so update rxbcnt */ /* we read 4 bytes from the fifo, so update rxbcnt */
if (usbd_dev->rxbcnt < 4) { if (usbd_dev->rxbcnt < 4) {
/* Be careful not to underflow (rxbcnt is unsigned) */ /* Be careful not to underflow (rxbcnt is unsigned) */
@@ -307,6 +318,7 @@ uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, void *buf, uint
} }
return len; return len;
#endif
} }
static void dwc_flush_txfifo(usbd_device *usbd_dev, int ep) static void dwc_flush_txfifo(usbd_device *usbd_dev, int ep)
@@ -410,10 +422,21 @@ void dwc_poll(usbd_device *usbd_dev)
} }
/* Discard unread packet data. */ /* Discard unread packet data. */
#if defined(STM32H7)
const size_t total_length = (rxstsp & OTG_GRXSTSP_BCNT_MASK) >> 4U;
const size_t consumed = total_length - usbd_dev->rxbcnt;
const volatile uint32_t *const fifo = (const volatile uint32_t *)(usbd_dev->driver->base_address + OTG_FIFO(0));
for (size_t offset = consumed; offset < total_length; offset += 4) {
(void)fifo[offset >> 2U];
}
REBASE(OTG_DOEPINT(ep)) = OTG_DOEPINTX_XFRC;
#else
for (size_t i = 0; i < usbd_dev->rxbcnt; i += 4) { for (size_t i = 0; i < usbd_dev->rxbcnt; i += 4) {
/* There is only one receive FIFO, so use OTG_FIFO(0) */ /* There is only one receive FIFO, so use OTG_FIFO(0) */
(void)REBASE(OTG_FIFO(0)); (void)REBASE(OTG_FIFO(0));
} }
#endif
usbd_dev->rxbcnt = 0; usbd_dev->rxbcnt = 0;
} }