usb/dwc: Corrected how packets are read and unloaded from the DWC2 FIFOs on the H7
This commit is contained in:
committed by
Piotr Esden-Tempski
parent
d9779685ae
commit
5e6c423100
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user