From a271b641a58263fbdc47707b98eeb179e0fcfda2 Mon Sep 17 00:00:00 2001 From: jsanchez-2g Date: Tue, 18 Aug 2026 16:05:33 -0500 Subject: [PATCH] arm/stm32: Fix USB packet memory addressing on M0 parts. The packet memory area (PMA) accessors in the M0 USB device driver were carried over from the STM32F1 implementation, where the PMA is seen by the CPU as 16-bit values placed on 32-bit boundaries. On the STM32F0, STM32L0 and other M0 parts the PMA is a linear 16-bit memory, so the F1 scaling is wrong: - STM32_USB_BTABLE_RADDR() shifted the computed buffer descriptor offset left by one, addressing every second descriptor entry. - The buffer descriptor accessors declared the descriptor entries as uint32_t and accessed them 32 bits at a time, so each write clobbered the adjacent entry. - stm32_copytopma() and stm32_copyfrompma() scaled the PMA offset by two when computing the packet buffer address. The result is that endpoint buffer descriptors and packet data are written to the wrong offsets in packet memory, and no transfer completes correctly. Drop the F1 scaling and use 16-bit accesses throughout. Note that the sibling stm32_usbfs.h defines STM32_USB_BTABLE_RADDR() without the shift already, so this brings the M0 header in line with it. Assisted-by: GitHub Copilot:claude-opus-5 Signed-off-by: jsanchez-2g --- .../common/stm32/hardware/stm32_usbdev_m0.h | 2 +- .../arm/src/common/stm32/stm32_usbdev_m0_v1.c | 28 ++++++++----------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/arch/arm/src/common/stm32/hardware/stm32_usbdev_m0.h b/arch/arm/src/common/stm32/hardware/stm32_usbdev_m0.h index d40fb53b23a..80c3445f962 100644 --- a/arch/arm/src/common/stm32/hardware/stm32_usbdev_m0.h +++ b/arch/arm/src/common/stm32/hardware/stm32_usbdev_m0.h @@ -68,7 +68,7 @@ #define STM32_USB_ADDR_RX_WOFFSET (4) /* Reception buffer address n (16-bits) */ #define STM32_USB_COUNT_RX_WOFFSET (6) /* Reception byte count n (16-bits) */ -#define STM32_USB_BTABLE_RADDR(ep,o) ((((uint32_t)getreg16(STM32_USB_BTABLE) + ((ep) << 3)) + (o)) << 1) +#define STM32_USB_BTABLE_RADDR(ep,o) (((uint32_t)getreg16(STM32_USB_BTABLE) + ((ep) << 3)) + (o)) #define STM32_USB_ADDR_TX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_ADDR_TX_WOFFSET) #define STM32_USB_COUNT_TX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_COUNT_TX_WOFFSET) #define STM32_USB_ADDR_RX_OFFSET(ep) STM32_USB_BTABLE_RADDR(ep,STM32_USB_ADDR_RX_WOFFSET) diff --git a/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c b/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c index 59632743a29..b39b0ad76a1 100644 --- a/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c +++ b/arch/arm/src/common/stm32/stm32_usbdev_m0_v1.c @@ -722,7 +722,7 @@ static void stm32_dumpep(int epno) static inline void stm32_seteptxcount(uint8_t epno, uint16_t count) { - volatile uint32_t *epaddr = (uint32_t *)STM32_USB_COUNT_TX(epno); + volatile uint16_t *epaddr = (uint16_t *)STM32_USB_COUNT_TX(epno); *epaddr = count; } @@ -732,7 +732,7 @@ static inline void stm32_seteptxcount(uint8_t epno, uint16_t count) static inline void stm32_seteptxaddr(uint8_t epno, uint16_t addr) { - volatile uint32_t *txaddr = (uint32_t *)STM32_USB_ADDR_TX(epno); + volatile uint16_t *txaddr = (uint16_t *)STM32_USB_ADDR_TX(epno); *txaddr = addr; } @@ -742,7 +742,7 @@ static inline void stm32_seteptxaddr(uint8_t epno, uint16_t addr) static inline uint16_t stm32_geteptxaddr(uint8_t epno) { - volatile uint32_t *txaddr = (uint32_t *)STM32_USB_ADDR_TX(epno); + volatile uint16_t *txaddr = (uint16_t *)STM32_USB_ADDR_TX(epno); return (uint16_t)*txaddr; } @@ -752,7 +752,7 @@ static inline uint16_t stm32_geteptxaddr(uint8_t epno) static void stm32_seteprxcount(uint8_t epno, uint16_t count) { - volatile uint32_t *epaddr = (uint32_t *)STM32_USB_COUNT_RX(epno); + volatile uint16_t *epaddr = (uint16_t *)STM32_USB_COUNT_RX(epno); uint32_t rxcount = 0; uint16_t nblocks; @@ -801,7 +801,7 @@ static void stm32_seteprxcount(uint8_t epno, uint16_t count) static inline uint16_t stm32_geteprxcount(uint8_t epno) { - volatile uint32_t *epaddr = (uint32_t *)STM32_USB_COUNT_RX(epno); + volatile uint16_t *epaddr = (uint16_t *)STM32_USB_COUNT_RX(epno); return (*epaddr) & USB_COUNT_RX_MASK; } @@ -811,7 +811,7 @@ static inline uint16_t stm32_geteprxcount(uint8_t epno) static inline void stm32_seteprxaddr(uint8_t epno, uint16_t addr) { - volatile uint32_t *rxaddr = (uint32_t *)STM32_USB_ADDR_RX(epno); + volatile uint16_t *rxaddr = (uint16_t *)STM32_USB_ADDR_RX(epno); *rxaddr = addr; } @@ -821,7 +821,7 @@ static inline void stm32_seteprxaddr(uint8_t epno, uint16_t addr) static inline uint16_t stm32_geteprxaddr(uint8_t epno) { - volatile uint32_t *rxaddr = (uint32_t *)STM32_USB_ADDR_RX(epno); + volatile uint16_t *rxaddr = (uint16_t *)STM32_USB_ADDR_RX(epno); return (uint16_t)*rxaddr; } @@ -1049,7 +1049,7 @@ static void stm32_copytopma(const uint8_t *buffer, /* Copy loop. Source=user buffer, Dest=packet memory */ - dest = (uint16_t *)(STM32_USBRAM_BASE + ((uint32_t)pma << 1)); + dest = (uint16_t *)(STM32_USBRAM_BASE + (uint32_t)pma); for (i = nwords; i != 0; i--) { /* Read two bytes and pack into on 16-bit word */ @@ -1058,11 +1058,7 @@ static void stm32_copytopma(const uint8_t *buffer, ms = (uint16_t)(*buffer++); *dest = ms << 8 | ls; - /* Source address increments by 2*sizeof(uint8_t) = 2; Dest address - * increments by 2*sizeof(uint16_t) = 4. - */ - - dest += 2; + dest++; } } @@ -1073,20 +1069,20 @@ static void stm32_copytopma(const uint8_t *buffer, static inline void stm32_copyfrompma(uint8_t *buffer, uint16_t pma, uint16_t nbytes) { - uint32_t *src; + uint16_t *src; int nwords = (nbytes + 1) >> 1; int i; /* Copy loop. Source=packet memory, Dest=user buffer */ - src = (uint32_t *)(STM32_USBRAM_BASE + ((uint32_t)pma << 1)); + src = (uint16_t *)(STM32_USBRAM_BASE + (uint32_t)pma); for (i = nwords; i != 0; i--) { /* Copy 16-bits from packet memory to user buffer. */ *(uint16_t *)buffer = *src++; - /* Source address increments by 1*sizeof(uint32_t) = 4; Dest address + /* Source address increments by 1*sizeof(uint16_t) = 2; Dest address * increments by 2*sizeof(uint8_t) = 2. */