diff options
author | Sebastian Holzapfel <seb.holzapfel@data61.csiro.au> | 2018-02-13 00:37:24 +0300 |
---|---|---|
committer | Karl Palsson <karlp@tweak.net.au> | 2018-03-03 01:42:05 +0300 |
commit | a0669421e1ca8c7dfec3057c9b8dfb8e78198491 (patch) | |
tree | 86b8b941cd13b87134605aacc7cac1a45b913d24 /lib/usb | |
parent | a2ee90fbfedf41230b2ec0ccd5d84c3e55d1f7d0 (diff) |
usb-dwc: handle any-aligned buffers
This is required to support armv6m targets using this code.
Diffstat (limited to 'lib/usb')
-rw-r--r-- | lib/usb/usb_dwc_common.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/lib/usb/usb_dwc_common.c b/lib/usb/usb_dwc_common.c index 4518adbd..11af2609 100644 --- a/lib/usb/usb_dwc_common.c +++ b/lib/usb/usb_dwc_common.c @@ -194,6 +194,10 @@ uint16_t dwc_ep_write_packet(usbd_device *usbd_dev, uint8_t addr, const void *buf, uint16_t len) { const uint32_t *buf32 = buf; +#if defined(__ARM_ARCH_6M__) + const uint8_t *buf8 = buf; + uint32_t word32; +#endif /* defined(__ARM_ARCH_6M__) */ int i; addr &= 0x7F; @@ -208,10 +212,28 @@ uint16_t dwc_ep_write_packet(usbd_device *usbd_dev, uint8_t addr, REBASE(OTG_DIEPCTL(addr)) |= OTG_DIEPCTL0_EPENA | OTG_DIEPCTL0_CNAK; - /* Copy buffer to endpoint FIFO, note - memcpy does not work */ + /* Copy buffer to endpoint FIFO, note - memcpy does not work. + * ARMv7M supports non-word-aligned accesses, ARMv6M does not. */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) for (i = len; i > 0; i -= 4) { REBASE(OTG_FIFO(addr)) = *buf32++; } +#endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */ + +#if defined(__ARM_ARCH_6M__) + /* Take care of word-aligned and non-word-aligned buffers */ + if (((uint32_t)buf8 & 0x3) == 0) { + for (i = len; i > 0; i -= 4) { + REBASE(OTG_FIFO(addr)) = *buf32++; + } + } else { + for (i = len; i > 0; i -= 4) { + memcpy(&word32, buf8, 4); + REBASE(OTG_FIFO(addr)) = word32; + buf8 += 4; + } + } +#endif /* defined(__ARM_ARCH_6M__) */ return len; } @@ -221,6 +243,10 @@ uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, { 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 @@ -229,10 +255,32 @@ uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr, (void) addr; len = MIN(len, usbd_dev->rxbcnt); + /* ARMv7M supports non-word-aligned accesses, ARMv6M does not. */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) for (i = len; i >= 4; i -= 4) { *buf32++ = REBASE(OTG_FIFO(0)); usbd_dev->rxbcnt -= 4; } +#endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */ + +#if defined(__ARM_ARCH_6M__) + /* Take care of word-aligned and non-word-aligned buffers */ + if (((uint32_t)buf8 & 0x3) == 0) { + for (i = len; i >= 4; i -= 4) { + *buf32++ = REBASE(OTG_FIFO(0)); + usbd_dev->rxbcnt -= 4; + } + } else { + for (i = len; i >= 4; i -= 4) { + word32 = REBASE(OTG_FIFO(0)); + memcpy(buf8, &word32, 4); + usbd_dev->rxbcnt -= 4; + buf8 += 4; + } + /* buf32 needs to be updated as it is used for extra */ + buf32 = (uint32_t *)buf8; + } +#endif /* defined(__ARM_ARCH_6M__) */ if (i) { extra = REBASE(OTG_FIFO(0)); |