This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 3693257175ab909ab2f25f63b99f4e5ae9822ea1 Author: Jukka Laitinen <[email protected]> AuthorDate: Wed Sep 9 12:52:34 2026 +0300 arc/arm/imxrt/imxrt_usbdev.c: Fix for imxrt118x-evk - Move/make sure that ep0buf is in usb dma capable memory. Especially if .data/.bss are in TCM, the buffers need to be placed in another section. If the section .dmamemory doesn't exist, they will end up in .data like before - change "#ifdef CONFIG_ARCH_FAMILY_IMXRT117x" into "#if defined(CONFIG_ARCH_FAMILY_IMXRT117x) || defined(CONFIG_ARCH_FAMILY_IMXRT118x)" - In imxrt_epcomplete dtd->buffer0 must NOT be used to compute the data buffer's cache-maintenance address range. The hardware advances buffer0 (and its "current offset" low-order bits) as the transfer progresses, so by completion time it points *past* the start of the buffer (at start + xfer_len), not at the buffer itself. Instead, use the original privreq->req.buf when the transfer is complete. Signed-off-by: Jukka Laitinen <[email protected]> --- arch/arm/src/imxrt/hardware/imxrt_usbphy.h | 5 ++- arch/arm/src/imxrt/imxrt_usbdev.c | 58 ++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/arch/arm/src/imxrt/hardware/imxrt_usbphy.h b/arch/arm/src/imxrt/hardware/imxrt_usbphy.h index 0e703a5ac81..ea6d4ef932d 100644 --- a/arch/arm/src/imxrt/hardware/imxrt_usbphy.h +++ b/arch/arm/src/imxrt/hardware/imxrt_usbphy.h @@ -36,11 +36,14 @@ #define IMXRT_USBPHY_BASE_OFFSET 0x1000 /* USB1 PHY Base */ -/* Simple hack to get iMXRT117x working with same macro */ +/* Simple hack to get iMXRT117x/iMXRT118x working with same macro */ #ifdef CONFIG_ARCH_FAMILY_IMXRT117x # define IMXRT_ANATOP_BASE 0x40433000 /* ANATOP doesn't exist on rt117x, it is used this way here only to make the code compatible */ # define IMXRT_USBPHY_SHIFT 0x4000 +#elif defined(CONFIG_ARCH_FAMILY_IMXRT118x) +# define IMXRT_ANATOP_BASE (IMXRT_USBPHY1_BASE - IMXRT_USBPHY_BASE_OFFSET) /* ANATOP doesn't exist on rt118x */ +# define IMXRT_USBPHY_SHIFT 0x10000 #else # define IMXRT_USBPHY_SHIFT 0x1000 #endif diff --git a/arch/arm/src/imxrt/imxrt_usbdev.c b/arch/arm/src/imxrt/imxrt_usbdev.c index 5e380616dcc..117cd5adf89 100644 --- a/arch/arm/src/imxrt/imxrt_usbdev.c +++ b/arch/arm/src/imxrt/imxrt_usbdev.c @@ -207,11 +207,21 @@ const struct trace_msg_t g_usb_trace_strings_intdecode[] = #endif #if defined(CONFIG_ARMV7M_DCACHE) -# define cache_aligned_alloc(s) kmm_memalign(ARMV7M_DCACHE_LINESIZE,(s)) +# define cache_aligned_alloc(s) \ + kmm_memalign(ARMV7M_DCACHE_LINESIZE, \ + (((s) + ARMV7M_DCACHE_LINESIZE - 1) & \ + ~(ARMV7M_DCACHE_LINESIZE - 1))) # define CACHE_ALIGNED_DATA aligned_data(ARMV7M_DCACHE_LINESIZE) +# define DCACHE_LINEMASK (ARMV7M_DCACHE_LINESIZE - 1) +# define DCACHE_ALIGN_UP(a) (((a) + DCACHE_LINEMASK) & ~DCACHE_LINEMASK) +# define IS_CACHE_ALIGNED(x,y) \ + (((uintptr_t)(x) & DCACHE_LINEMASK) == 0 && \ + ((y) & DCACHE_LINEMASK) == 0) #else # define cache_aligned_alloc kmm_malloc # define CACHE_ALIGNED_DATA +# define DCACHE_ALIGN_UP(a) (a) +# define IS_CACHE_ALIGNED(x,y) (true) #endif /* Hardware interface *******************************************************/ @@ -369,7 +379,7 @@ struct imxrt_usbdev_s uint8_t ep0state; /* State of certain EP0 operations */ /* buffer for EP0 short transfers */ - uint8_t ep0buf[64] CACHE_ALIGNED_DATA; + uint8_t *ep0buf; uint8_t paddr; /* Address assigned by SETADDRESS */ uint8_t stalled:1; /* 1: Protocol stalled */ uint8_t selfpowered:1; /* 1: Device is self powered */ @@ -390,6 +400,8 @@ struct imxrt_usbdev_s struct imxrt_ep_s eplist[IMXRT_NPHYSENDPOINTS]; }; +#define IMXRT_EP0BUF_SIZE 64 /* Size of the EP0 short transfer buffer */ + #define EP0STATE_IDLE 0 /* Idle State, leave on receiving a setup packet or epsubmit */ #define EP0STATE_SETUP_OUT 1 /* Setup Packet received - SET/CLEAR */ #define EP0STATE_SETUP_IN 2 /* Setup Packet received - GET */ @@ -513,12 +525,34 @@ static int imxrt_pullup(struct usbdev_s *dev, bool enable); static struct imxrt_usbdev_s g_usbdev; +/* Normally g_qh, g_td and g_ep0buf are statically allocated in .bss. + * But they need to be DMA-capable for usb engine to access them. If we + * run with TCM memory as the primary, there has to be another memory + * segment elsewhere, in DMA capable memory (.dmamemory). Also we must have + * USBDEV_DMAMEMORY enabled to be able to dynamically allocate from there. + */ + +#ifdef CONFIG_IMXRT_TCM_PRIMARY +# ifndef CONFIG_USBDEV_DMAMEMORY +# error "CONFIG_USBDEV_DMAMEMORY must be defined" +# endif +# define USBDEV_DMA_SECTION locate_data(".dmamemory") +#else +# define USBDEV_DMA_SECTION +#endif + static struct imxrt_dqh_s g_qh[IMXRT_NPHYSENDPOINTS] + USBDEV_DMA_SECTION aligned_data(2048); static struct imxrt_dtd_s g_td[IMXRT_NPHYSENDPOINTS] + USBDEV_DMA_SECTION aligned_data(32); +static uint8_t g_ep0buf[IMXRT_EP0BUF_SIZE] + USBDEV_DMA_SECTION + aligned_data(32); + static const struct usbdev_epops_s g_epops = { .configure = imxrt_epconfigure, @@ -751,6 +785,11 @@ static inline void imxrt_writedtd(struct imxrt_dtd_s *dtd, const uint8_t *data, uint32_t nbytes) { +#if defined(CONFIG_ARMV7M_DCACHE) + DEBUGASSERT(data == NULL || + IS_CACHE_ALIGNED(data, DCACHE_ALIGN_UP(nbytes))); +#endif + dtd->nextdesc = DTD_NEXTDESC_INVALID; dtd->config = DTD_CONFIG_LENGTH(nbytes) | DTD_CONFIG_IOC | DTD_CONFIG_ACTIVE; @@ -1752,7 +1791,7 @@ static void imxrt_ep0complete(struct imxrt_usbdev_s *priv, uint8_t epphy) */ up_invalidate_dcache((uintptr_t)priv->ep0buf, - (uintptr_t)priv->ep0buf + sizeof(priv->ep0buf)); + (uintptr_t)priv->ep0buf + IMXRT_EP0BUF_SIZE); imxrt_dispatchrequest(priv, &priv->ep0ctrl); imxrt_ep0state(priv, EP0STATE_WAIT_NAK_IN); @@ -1887,8 +1926,6 @@ bool imxrt_epcomplete(struct imxrt_usbdev_s *priv, uint8_t epphy) up_invalidate_dcache((uintptr_t)dtd, (uintptr_t)dtd + sizeof(struct imxrt_dtd_s)); - up_invalidate_dcache((uintptr_t)dtd->buffer0, - (uintptr_t)dtd->buffer0 + dtd->xfer_len); int xfrd = dtd->xfer_len - (dtd->config >> 16); @@ -1903,6 +1940,14 @@ bool imxrt_epcomplete(struct imxrt_usbdev_s *priv, uint8_t epphy) */ usbtrace(TRACE_INTDECODE(IMXRT_TRACEINTID_EPIN), complete); + + /* Invalidate the RX buffer */ + + DEBUGASSERT(IS_CACHE_ALIGNED(privreq->req.buf, + DCACHE_ALIGN_UP(privreq->req.xfrd))); + up_invalidate_dcache((uintptr_t)privreq->req.buf, + (uintptr_t)privreq->req.buf + + DCACHE_ALIGN_UP(privreq->req.xfrd)); } else { @@ -2896,6 +2941,7 @@ void arm_usbinitialize(void) priv->usbdev.ops = &g_devops; priv->usbdev.ep0 = &priv->eplist[IMXRT_EP0_IN].ep; priv->epavail = IMXRT_EPALLSET & ~IMXRT_EPCTRLSET; + priv->ep0buf = g_ep0buf; /* Initialize the endpoint list */ @@ -2950,7 +2996,7 @@ void arm_usbinitialize(void) imxrt_clockall_usboh3(); -#ifdef CONFIG_ARCH_FAMILY_IMXRT117x +#if defined(CONFIG_ARCH_FAMILY_IMXRT117x) || defined(CONFIG_ARCH_FAMILY_IMXRT118x) up_mdelay(1); putreg32(USBPHY_PLL_SIC_PLL_POWER |
