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 |

Reply via email to