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 <jsanchez@2g-eng.com>
This commit is contained in:
jsanchez-2g 2026-08-18 16:05:33 -05:00 committed by Xiang Xiao
parent a5f8fdaa2e
commit a271b641a5
2 changed files with 13 additions and 17 deletions

View file

@ -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)

View file

@ -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.
*/