Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/thirdpin/libopencm3.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib/usb
diff options
context:
space:
mode:
authorSebastian Holzapfel <seb.holzapfel@data61.csiro.au>2018-02-13 00:37:24 +0300
committerKarl Palsson <karlp@tweak.net.au>2018-03-03 01:42:05 +0300
commita0669421e1ca8c7dfec3057c9b8dfb8e78198491 (patch)
tree86b8b941cd13b87134605aacc7cac1a45b913d24 /lib/usb
parenta2ee90fbfedf41230b2ec0ccd5d84c3e55d1f7d0 (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.c50
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));