This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 4fc76ea661 arch/arm/samv7: fix random corruption of data after SDIO RX 
DMA transaction
4fc76ea661 is described below

commit 4fc76ea661ef9c9354e93f4c2210827d34118314
Author: Petro Karashchenko <petro.karashche...@gmail.com>
AuthorDate: Fri Sep 16 15:26:49 2022 +0200

    arch/arm/samv7: fix random corruption of data after SDIO RX DMA transaction
    
    use time based timeout calculation instead of cycle based
    
    minor styling fixes
    
    Signed-off-by: Petro Karashchenko <petro.karashche...@gmail.com>
---
 arch/arm/src/samv7/sam_hsmci.c | 74 +++++++++++++++++++++++++++---------------
 1 file changed, 47 insertions(+), 27 deletions(-)

diff --git a/arch/arm/src/samv7/sam_hsmci.c b/arch/arm/src/samv7/sam_hsmci.c
index 33761fba59..2517351fd5 100644
--- a/arch/arm/src/samv7/sam_hsmci.c
+++ b/arch/arm/src/samv7/sam_hsmci.c
@@ -120,10 +120,10 @@
 #undef  HSCMI_NORXDMA              /* Define to disable RX DMA */
 #undef  HSCMI_NOTXDMA              /* Define to disable TX DMA */
 
-/* Timing */
+/* Timing : 100mS short timeout, 2 seconds for long one */
 
-#define HSMCI_CMDTIMEOUT         (100000)
-#define HSMCI_LONGTIMEOUT        (0x7fffffff)
+#define HSMCI_CMDTIMEOUT         MSEC2TICK(100)
+#define HSMCI_LONGTIMEOUT        MSEC2TICK(2000)
 
 /* Big DTIMER setting */
 
@@ -404,16 +404,17 @@ static bool sam_checkreg(struct sam_dev_s *priv, bool wr,
 #endif
 
 static inline uint32_t sam_getreg(struct sam_dev_s *priv,
-                  unsigned int offset);
+                                  unsigned int offset);
 static inline void sam_putreg(struct sam_dev_s *priv, uint32_t value,
-                  unsigned int offset);
+                              unsigned int offset);
 
 static inline void sam_configwaitints(struct sam_dev_s *priv,
-              uint32_t waitmask, sdio_eventset_t waitevents);
+                                      uint32_t waitmask,
+                                      sdio_eventset_t waitevents);
 static void sam_disablewaitints(struct sam_dev_s *priv,
-              sdio_eventset_t wkupevent);
+                                sdio_eventset_t wkupevent);
 static inline void sam_configxfrints(struct sam_dev_s *priv,
-              uint32_t xfrmask);
+                                     uint32_t xfrmask);
 static void sam_disablexfrints(struct sam_dev_s *priv);
 static inline void sam_enableints(struct sam_dev_s *priv);
 
@@ -458,14 +459,14 @@ static void sam_cmddump(struct sam_dev_s *priv);
 
 static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result);
 static inline uintptr_t hsmci_regaddr(struct sam_dev_s *priv,
-              unsigned int offset);
+                                      unsigned int offset);
 
 /* Data Transfer Helpers ****************************************************/
 
 static void sam_eventtimeout(wdparm_t arg);
 static void sam_endwait(struct sam_dev_s *priv, sdio_eventset_t wkupevent);
 static void sam_endtransfer(struct sam_dev_s *priv,
-              sdio_eventset_t wkupevent);
+                            sdio_eventset_t wkupevent);
 static void sam_notransfer(struct sam_dev_s *priv);
 
 /* Interrupt Handling *******************************************************/
@@ -481,48 +482,48 @@ static sdio_capset_t sam_capabilities(struct sdio_dev_s 
*dev);
 static sdio_statset_t sam_status(struct sdio_dev_s *dev);
 static void sam_widebus(struct sdio_dev_s *dev, bool enable);
 static void sam_clock(struct sdio_dev_s *dev,
-              enum sdio_clock_e rate);
+                      enum sdio_clock_e rate);
 static int  sam_attach(struct sdio_dev_s *dev);
 
 /* Command/Status/Data Transfer */
 
 static int  sam_sendcmd(struct sdio_dev_s *dev, uint32_t cmd,
-              uint32_t arg);
+                        uint32_t arg);
 static void sam_blocksetup(struct sdio_dev_s *dev, unsigned int blocklen,
-              unsigned int nblocks);
+                           unsigned int nblocks);
 static int  sam_recvsetup(struct sdio_dev_s *dev, uint8_t *buffer,
-              size_t nbytes);
+                          size_t nbytes);
 static int  sam_sendsetup(struct sdio_dev_s *dev,
-              const uint8_t *buffer, size_t nbytes);
+                          const uint8_t *buffer, size_t nbytes);
 static int  sam_cancel(struct sdio_dev_s *dev);
 static int  sam_waitresponse(struct sdio_dev_s *dev, uint32_t cmd);
 static int  sam_recvshort(struct sdio_dev_s *dev, uint32_t cmd,
-              uint32_t *rshort);
+                          uint32_t *rshort);
 static int  sam_recvlong(struct sdio_dev_s *dev, uint32_t cmd,
-              uint32_t rlong[4]);
+                         uint32_t rlong[4]);
 static int  sam_recvnotimpl(struct sdio_dev_s *dev, uint32_t cmd,
-              uint32_t *rnotimpl);
+                            uint32_t *rnotimpl);
 
 /* EVENT handler */
 
 static void sam_waitenable(struct sdio_dev_s *dev,
-              sdio_eventset_t eventset, uint32_t timeout);
+                           sdio_eventset_t eventset, uint32_t timeout);
 static sdio_eventset_t sam_eventwait(struct sdio_dev_s *dev);
 static void sam_callbackenable(struct sdio_dev_s *dev,
-              sdio_eventset_t eventset);
+                               sdio_eventset_t eventset);
 static int  sam_registercallback(struct sdio_dev_s *dev,
-              worker_t callback, void *arg);
+                                 worker_t callback, void *arg);
 
 /* DMA */
 
 #ifdef CONFIG_SAMV7_HSMCI_DMA
 #ifndef HSCMI_NORXDMA
 static int  sam_dmarecvsetup(struct sdio_dev_s *dev,
-              uint8_t *buffer, size_t buflen);
+                             uint8_t *buffer, size_t buflen);
 #endif
 #ifndef HSCMI_NOTXDMA
 static int  sam_dmasendsetup(struct sdio_dev_s *dev,
-              const uint8_t *buffer, size_t buflen);
+                             const uint8_t *buffer, size_t buflen);
 #endif
 #endif
 
@@ -1572,6 +1573,21 @@ static int sam_hsmci_interrupt(int irq, void *context, 
void *arg)
 
           else
             {
+              /* If buffer is not NULL that means that RX DMA is finished.
+               * We need to invalidate RX buffer
+               */
+
+              if (priv->buffer != NULL)
+                {
+                  DEBUGASSERT(priv->remaining > 0);
+
+                  up_invalidate_dcache((uintptr_t)priv->buffer,
+                                       (uintptr_t)priv->buffer +
+                                       priv->remaining);
+                  priv->buffer    = NULL;
+                  priv->remaining = 0;
+                }
+
               /* End the transfer */
 
               sam_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
@@ -2388,6 +2404,7 @@ static int sam_waitresponse(struct sdio_dev_s *dev, 
uint32_t cmd)
   struct sam_dev_s *priv = (struct sam_dev_s *)dev;
   uint32_t sr;
   uint32_t pending;
+  clock_t  watchtime;
   int32_t  timeout;
 
   switch (cmd & MMCSD_RESPONSE_MASK)
@@ -2415,6 +2432,7 @@ static int sam_waitresponse(struct sdio_dev_s *dev, 
uint32_t cmd)
 
   /* Then wait for the response (or timeout) */
 
+  watchtime = clock_systime_ticks();
   for (; ; )
     {
       /* Did a Command-Response sequence termination event occur? */
@@ -2464,7 +2482,7 @@ static int sam_waitresponse(struct sdio_dev_s *dev, 
uint32_t cmd)
               return OK;
             }
        }
-      else if (--timeout <= 0)
+      else if (clock_systime_ticks() - watchtime > timeout)
         {
           mcerr("ERROR: Timeout cmd: %08" PRIx32 " events: %08" PRIx32
                 " SR: %08" PRIx32 "\n",
@@ -3008,9 +3026,11 @@ static int sam_dmarecvsetup(struct sdio_dev_s *dev, 
uint8_t *buffer,
 
   /* Start the DMA */
 
-  priv->dmabusy = true;
-  priv->xfrbusy = true;
-  priv->txbusy  = false;
+  priv->dmabusy   = true;
+  priv->xfrbusy   = true;
+  priv->txbusy    = false;
+  priv->buffer    = (uint32_t *)buffer;
+  priv->remaining = buflen;
   sam_dmastart(priv->dma, sam_dmacallback, priv);
 
   /* Configure transfer-related interrupts.  Transfer interrupts are not

Reply via email to