You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/02/06 16:52:36 UTC

(nuttx) branch master updated (38f8aae3be -> df01c83c25)

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

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


    from 38f8aae3be boards: rv-virt: Add nxrecorder to defconfigs
     new b0cef9e008 risc-v/mpfs: i2c: prevent out of bounds read access
     new bcf7aa4b63 risc-v/mpfs: i2c: perform sanity checks
     new dae31dc866 arch/risc-v/src/mpfs/mpfs_i2c.c: Clear I2C_CTRL bits when initializing/deinitializing bus
     new fc4b39b1dd arch/risc-v/src/mpfs/mpfs_i2c.c: Add more error status codes
     new 120dfbd45f arch/risc-v/src/mpfs/mpfs_i2c.c: Correct i2c reset / error recovery
     new 2b10b38c1d arch/risc-v/src/mpfs/mpfs_i2c.c: Add more i2cerr traces
     new df01c83c25 arch/risc-v/src/mpfs/mpfs_i2c.c: Recover i2c from pending transactions in warm boot

The 7 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/risc-v/src/mpfs/mpfs_i2c.c | 222 ++++++++++++++++++++++++++++++++--------
 1 file changed, 177 insertions(+), 45 deletions(-)


(nuttx) 04/07: arch/risc-v/src/mpfs/mpfs_i2c.c: Add more error status codes

Posted by xi...@apache.org.
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/nuttx.git

commit fc4b39b1dd1cfca093bdf7e410e42d994fb5eecd
Author: Jukka Laitinen <ju...@ssrc.tii.ae>
AuthorDate: Wed Jan 10 08:45:25 2024 +0200

    arch/risc-v/src/mpfs/mpfs_i2c.c: Add more error status codes
    
    Add more error status codes to help debugging in the future.
    
    Signed-off-by: Jukka Laitinen <ju...@ssrc.tii.ae>
---
 arch/risc-v/src/mpfs/mpfs_i2c.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c
index 020b8237e2..0e39e3efc7 100644
--- a/arch/risc-v/src/mpfs/mpfs_i2c.c
+++ b/arch/risc-v/src/mpfs/mpfs_i2c.c
@@ -83,7 +83,10 @@ typedef enum mpfs_i2c_status
   MPFS_I2C_SUCCESS = 0u,
   MPFS_I2C_IN_PROGRESS,
   MPFS_I2C_FAILED,
-  MPFS_I2C_TIMED_OUT
+  MPFS_I2C_FAILED_SLAW_NACK,
+  MPFS_I2C_FAILED_SLAR_NACK,
+  MPFS_I2C_FAILED_TX_DATA_NACK,
+  MPFS_I2C_FAILED_BUS_ERROR,
 } mpfs_i2c_status_t;
 
 typedef enum mpfs_i2c_clock_divider
@@ -468,7 +471,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
 
       case MPFS_I2C_ST_SLAW_NACK:
         modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK);
-        priv->status = MPFS_I2C_FAILED;
+        priv->status = MPFS_I2C_FAILED_SLAW_NACK;
         break;
 
       case MPFS_I2C_ST_SLAW_ACK:
@@ -536,7 +539,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
 
       case MPFS_I2C_ST_TX_DATA_NACK:
         modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK);
-        priv->status = MPFS_I2C_FAILED;
+        priv->status = MPFS_I2C_FAILED_TX_DATA_NACK;
         break;
 
       case MPFS_I2C_ST_SLAR_ACK: /* SLA+R tx'ed. */
@@ -558,7 +561,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
 
       case MPFS_I2C_ST_SLAR_NACK: /* SLA+R tx'ed; send a stop condition */
         modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK);
-        priv->status = MPFS_I2C_FAILED;
+        priv->status = MPFS_I2C_FAILED_SLAR_NACK;
         break;
 
       case MPFS_I2C_ST_RX_DATA_ACK:
@@ -610,7 +613,6 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
 
         priv->rx_buffer[priv->rx_idx] = (uint8_t)getreg32(MPFS_I2C_DATA);
         priv->rx_idx++;
-
         priv->status = MPFS_I2C_SUCCESS;
         modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK);
         break;
@@ -651,7 +653,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
 
         if (priv->status == MPFS_I2C_IN_PROGRESS)
           {
-            priv->status = MPFS_I2C_FAILED;
+            priv->status = MPFS_I2C_FAILED_BUS_ERROR;
           }
 
         break;


(nuttx) 02/07: risc-v/mpfs: i2c: perform sanity checks

Posted by xi...@apache.org.
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/nuttx.git

commit bcf7aa4b631ef21d6d2b668ec87e1458bfac45bf
Author: Eero Nurkkala <ee...@offcode.fi>
AuthorDate: Tue Dec 5 12:53:39 2023 +0200

    risc-v/mpfs: i2c: perform sanity checks
    
    Replace risky DEBUGASSERT()s with real sanity checks. Also,
    do a few more checks as the system might occasionally fire an
    interrupt if the system has been restarted while in middle of
    an i2c transaction.
    
    Yet, modify i2c_transfer() function so that up_disable_irq()
    is always called at the end to better prevent ill-timed irqs.
    
    Signed-off-by: Eero Nurkkala <ee...@offcode.fi>
---
 arch/risc-v/src/mpfs/mpfs_i2c.c | 68 +++++++++++++++++++++++++++++++++++------
 1 file changed, 59 insertions(+), 9 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c
index 7748db1f0f..3a131f68e9 100644
--- a/arch/risc-v/src/mpfs/mpfs_i2c.c
+++ b/arch/risc-v/src/mpfs/mpfs_i2c.c
@@ -437,8 +437,6 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
   volatile uint32_t status;
   uint8_t clear_irq = 1u;
 
-  DEBUGASSERT(msg != NULL);
-
   status = getreg32(MPFS_I2C_STATUS);
 
   switch (status)
@@ -479,7 +477,16 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
       case MPFS_I2C_ST_TX_DATA_ACK:
         if (priv->tx_idx < priv->tx_size)
           {
-            DEBUGASSERT(priv->tx_buffer != NULL);
+            if (priv->tx_buffer == NULL)
+              {
+                i2cerr("ERROR: tx_buffer is NULL!\n");
+
+                /* Clear the serial interrupt flag and exit */
+
+                modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+                return 0;
+              }
+
             putreg32(priv->tx_buffer[priv->tx_idx], MPFS_I2C_DATA);
             priv->tx_idx++;
           }
@@ -557,10 +564,18 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
         break;
 
       case MPFS_I2C_ST_RX_DATA_ACK:
+        if (priv->rx_buffer == NULL)
+          {
+            i2cerr("ERROR: rx_buffer is NULL!\n");
+
+            /* Clear the serial interrupt flag and exit */
+
+            modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+            return 0;
+          }
 
         /* Data byte received, ACK returned */
 
-        DEBUGASSERT(priv->rx_buffer != NULL);
         priv->rx_buffer[priv->rx_idx] = (uint8_t)getreg32(MPFS_I2C_DATA);
         priv->rx_idx++;
 
@@ -572,10 +587,29 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
 
       case MPFS_I2C_ST_RX_DATA_NACK:
 
+        /* Some sanity checks */
+
+        if (priv->rx_buffer == NULL)
+          {
+            i2cerr("ERROR: rx_buffer is NULL!\n");
+
+            /* Clear the serial interrupt flag and exit */
+
+            modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+            return 0;
+          }
+        else if (priv->rx_idx >= priv->rx_size)
+          {
+            i2cerr("ERROR: rx_idx is out of bounds!\n");
+
+            /* Clear the serial interrupt flag and exit */
+
+            modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+            return 0;
+          }
+
         /* Data byte received, NACK returned */
 
-        DEBUGASSERT(priv->rx_buffer != NULL);
-        DEBUGASSERT(priv->rx_idx < priv->rx_size);
         priv->rx_buffer[priv->rx_idx] = (uint8_t)getreg32(MPFS_I2C_DATA);
         priv->rx_idx++;
 
@@ -673,7 +707,11 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
   int ret = OK;
 
   i2cinfo("Starting transfer request of %d message(s):\n", count);
-  DEBUGASSERT(count > 0);
+
+  if (count <= 0)
+    {
+      return -EINVAL;
+    }
 
   ret = nxmutex_lock(&priv->lock);
   if (ret < 0)
@@ -715,9 +753,17 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
 
           if (msgs[i].flags & I2C_M_NOSTOP)
             {
-              /* Support only write + read combinations */
+              /* Support only write + read combinations.  No write + write,
+               * nor read + write without stop condition between supported
+               * yet.
+               */
 
-              DEBUGASSERT(!(msgs[i].flags & I2C_M_READ));
+              if (msgs[i].flags & I2C_M_READ)
+                {
+                  i2cerr("No read before write supported!\n");
+                  nxmutex_unlock(&priv->lock);
+                  return -EINVAL;
+                }
 
               /* Combine write + read transaction into one */
 
@@ -765,6 +811,10 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
         i2cinfo("Message %" PRIu8 " transfer complete.\n", priv->msgid);
     }
 
+  /* Irq was enabled at mpfs_i2c_sendstart()  */
+
+  up_disable_irq(priv->plic_irq);
+
   nxmutex_unlock(&priv->lock);
   return ret;
 }


(nuttx) 01/07: risc-v/mpfs: i2c: prevent out of bounds read access

Posted by xi...@apache.org.
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/nuttx.git

commit b0cef9e0089c8bbbdbc6c7ba11f88737a0942189
Author: Eero Nurkkala <ee...@offcode.fi>
AuthorDate: Mon Nov 6 17:25:13 2023 +0200

    risc-v/mpfs: i2c: prevent out of bounds read access
    
    priv->msgid may grow past its boundaries, causing
    struct i2c_msg_s *msg = &priv->msgv[priv->msgid]
    to read data out of boundaris.
    
    Signed-off-by: Eero Nurkkala <ee...@offcode.fi>
---
 arch/risc-v/src/mpfs/mpfs_i2c.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c
index 26fa4408eb..7748db1f0f 100644
--- a/arch/risc-v/src/mpfs/mpfs_i2c.c
+++ b/arch/risc-v/src/mpfs/mpfs_i2c.c
@@ -493,7 +493,10 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
 
             /* Jump to the next message */
 
-            priv->msgid++;
+            if (priv->msgid < (priv->msgc - 1))
+              {
+                priv->msgid++;
+              }
           }
         else
           {
@@ -512,7 +515,10 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
 
                 /* Jump to the next message */
 
-                priv->msgid++;
+                if (priv->msgid < (priv->msgc - 1))
+                  {
+                    priv->msgid++;
+                  }
               }
             else
               {


(nuttx) 03/07: arch/risc-v/src/mpfs/mpfs_i2c.c: Clear I2C_CTRL bits when initializing/deinitializing bus

Posted by xi...@apache.org.
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/nuttx.git

commit dae31dc866b5226f8d4819a81fc2c42720a69fe3
Author: Jukka Laitinen <ju...@ssrc.tii.ae>
AuthorDate: Wed Jan 10 08:45:25 2024 +0200

    arch/risc-v/src/mpfs/mpfs_i2c.c: Clear I2C_CTRL bits when initializing/deinitializing bus
    
    Ensure that there are no pending state or interrupts in the i2c controller. This removes
    errors caused by deinitialize/initialize sequences in error cases.
    
    Signed-off-by: Jukka Laitinen <ju...@ssrc.tii.ae>
---
 arch/risc-v/src/mpfs/mpfs_i2c.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c
index 3a131f68e9..020b8237e2 100644
--- a/arch/risc-v/src/mpfs/mpfs_i2c.c
+++ b/arch/risc-v/src/mpfs/mpfs_i2c.c
@@ -358,10 +358,9 @@ static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv)
 
       putreg32(priv->ser_address, MPFS_I2C_ADDR);
 
-      /* Enable i2c bus */
+      /* Enable i2c bus, clear all other bits */
 
-      modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_ENS1_MASK,
-                  MPFS_I2C_CTRL_ENS1_MASK);
+      putreg32(MPFS_I2C_CTRL_ENS1_MASK, MPFS_I2C_CTRL);
 
       priv->initialized = true;
     }
@@ -385,8 +384,7 @@ static void mpfs_i2c_deinit(struct mpfs_i2c_priv_s *priv)
   up_disable_irq(priv->plic_irq);
   irq_detach(priv->plic_irq);
 
-  modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_ENS1_MASK,
-              ~MPFS_I2C_CTRL_ENS1_MASK);
+  putreg32(0, MPFS_I2C_CTRL);
 
   priv->initialized = false;
 }


(nuttx) 07/07: arch/risc-v/src/mpfs/mpfs_i2c.c: Recover i2c from pending transactions in warm boot

Posted by xi...@apache.org.
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/nuttx.git

commit df01c83c2524d4316f4dc10629dde00b26174b3e
Author: Jukka Laitinen <ju...@ssrc.tii.ae>
AuthorDate: Fri Jan 12 15:49:27 2024 +0200

    arch/risc-v/src/mpfs/mpfs_i2c.c: Recover i2c from pending transactions in warm boot
    
    Signed-off-by: Jukka Laitinen <ju...@ssrc.tii.ae>
---
 arch/risc-v/src/mpfs/mpfs_i2c.c | 49 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c
index 495ff7658c..cf0ecd418a 100644
--- a/arch/risc-v/src/mpfs/mpfs_i2c.c
+++ b/arch/risc-v/src/mpfs/mpfs_i2c.c
@@ -304,12 +304,57 @@ static uint32_t mpfs_i2c_timeout(int msgc, struct i2c_msg_s *msgv);
 static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv)
 {
   int ret = OK;
+  uint32_t ctrl;
+  uint32_t status;
 
   if (!priv->initialized)
     {
-      /* Clear any pending serial interrupt flag */
+      /* In case of warm boot, or after reset, check that the IP block is
+       * not already active and try to recover from any pending data
+       * transfer if it is.
+       */
 
-      modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+      ctrl = getreg32(MPFS_I2C_CTRL);
+      if (ctrl != 0)
+        {
+          /* Check if the IP is enabled */
+
+          status = getreg32(MPFS_I2C_STATUS);
+          if (ctrl & MPFS_I2C_CTRL_ENS1_MASK)
+            {
+              if (status == MPFS_I2C_ST_RX_DATA_ACK)
+                {
+                  /* In case the machine was in the middle of data RX, try to
+                   * receive one byte and nack it
+                   */
+
+                  modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_AA_MASK, 0);
+                  modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+                  usleep(100);
+                  status = getreg32(MPFS_I2C_STATUS);
+                }
+
+              if (status != MPFS_I2C_ST_IDLE)
+                {
+                  /* If the bus is not idle, send STOP */
+
+                  modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+                  modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK);
+                  usleep(100);
+                  modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+                  status = getreg32(MPFS_I2C_STATUS);
+                }
+            }
+
+          if (status != MPFS_I2C_ST_IDLE)
+            {
+              i2cerr("Bus not idle before init\n");
+            }
+
+          /* Disable IP and continue initialization */
+
+          putreg32(0, MPFS_I2C_CTRL);
+        }
 
       /* Attach interrupt */
 


(nuttx) 05/07: arch/risc-v/src/mpfs/mpfs_i2c.c: Correct i2c reset / error recovery

Posted by xi...@apache.org.
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/nuttx.git

commit 120dfbd45f8b1931c59cf574fe9bc8f1e310643a
Author: Jukka Laitinen <ju...@ssrc.tii.ae>
AuthorDate: Thu Jan 11 12:13:35 2024 +0200

    arch/risc-v/src/mpfs/mpfs_i2c.c: Correct i2c reset / error recovery
    
    - Use mpfs_i2c_deinit+mpfs_i2c_init sequence to re-initialize i2c block
    - Use the i2c mutex to protect the reset; in case there are several devices
      on the same bus, and one of them resets the bus, reset must not occur in
      the middle of another device's transfer.
    - Move irq attach to the i2c_init as the irq detach is in i2c_deinit
    
    Signed-off-by: Jukka Laitinen <ju...@ssrc.tii.ae>
---
 arch/risc-v/src/mpfs/mpfs_i2c.c | 45 ++++++++++++++++++++---------------------
 1 file changed, 22 insertions(+), 23 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c
index 0e39e3efc7..e9754d4ddd 100644
--- a/arch/risc-v/src/mpfs/mpfs_i2c.c
+++ b/arch/risc-v/src/mpfs/mpfs_i2c.c
@@ -126,6 +126,8 @@ static const uint32_t mpfs_i2c_freqs_fpga[MPFS_I2C_NUMBER_OF_DIVIDERS] =
   MPFS_FPGA_BCLK / 8
 };
 
+static int mpfs_i2c_irq(int cpuint, void *context, void *arg);
+
 static int mpfs_i2c_transfer(struct i2c_master_s *dev,
                              struct i2c_msg_s *msgs,
                              int count);
@@ -301,8 +303,22 @@ static uint32_t mpfs_i2c_timeout(int msgc, struct i2c_msg_s *msgv);
 
 static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv)
 {
+  int ret = OK;
+
   if (!priv->initialized)
     {
+      /* Clear any pending serial interrupt flag */
+
+      modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
+
+      /* Attach interrupt */
+
+      ret = irq_attach(priv->plic_irq, mpfs_i2c_irq, priv);
+      if (ret != OK)
+        {
+          return ret;
+        }
+
       if (priv->fpga)
         {
           /* FIC3 is used by many, don't reset it here, or many
@@ -838,26 +854,15 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev)
 {
   struct mpfs_i2c_priv_s *priv = (struct mpfs_i2c_priv_s *)dev;
   int ret;
-  irqstate_t flags;
-
-  DEBUGASSERT(priv != NULL);
 
-  flags = enter_critical_section();
-
-  /* Disabling I2C interrupts.
-   * NOTE: up_enable_irq() will be called at mpfs_i2c_sendstart()
-   */
-
-  up_disable_irq(priv->plic_irq);
+  nxmutex_lock(&priv->lock);
 
-  priv->inflight = false;
-  priv->status = MPFS_I2C_SUCCESS;
-  priv->initialized = false;
+  mpfs_i2c_deinit(priv);
 
   ret = mpfs_i2c_init(priv);
   if (ret != OK)
     {
-      leave_critical_section(flags);
+      nxmutex_unlock(&priv->lock);
       return ret;
     }
 
@@ -865,8 +870,10 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev)
   priv->tx_idx  = 0;
   priv->rx_size = 0;
   priv->rx_idx  = 0;
+  priv->inflight = false;
+  priv->status = MPFS_I2C_SUCCESS;
 
-  leave_critical_section(flags);
+  nxmutex_unlock(&priv->lock);
 
   return OK;
 }
@@ -1060,14 +1067,6 @@ struct i2c_master_s *mpfs_i2cbus_initialize(int port)
   priv->fpga = true;
 #endif
 
-  ret = irq_attach(priv->plic_irq, mpfs_i2c_irq, priv);
-  if (ret != OK)
-    {
-      priv->refs--;
-      nxmutex_unlock(&priv->lock);
-      return NULL;
-    }
-
   ret = mpfs_i2c_init(priv);
   if (ret != OK)
     {


(nuttx) 06/07: arch/risc-v/src/mpfs/mpfs_i2c.c: Add more i2cerr traces

Posted by xi...@apache.org.
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/nuttx.git

commit 2b10b38c1d02477851f2964cbdc649ce2974b99e
Author: Jukka Laitinen <ju...@ssrc.tii.ae>
AuthorDate: Wed Jan 10 08:45:25 2024 +0200

    arch/risc-v/src/mpfs/mpfs_i2c.c: Add more i2cerr traces
    
    Add sanity checks for debugging possible errors in the driver.
    
    Signed-off-by: Jukka Laitinen <ju...@ssrc.tii.ae>
---
 arch/risc-v/src/mpfs/mpfs_i2c.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c
index e9754d4ddd..495ff7658c 100644
--- a/arch/risc-v/src/mpfs/mpfs_i2c.c
+++ b/arch/risc-v/src/mpfs/mpfs_i2c.c
@@ -721,6 +721,10 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
 {
   struct mpfs_i2c_priv_s *priv = (struct mpfs_i2c_priv_s *)dev;
   int ret = OK;
+#ifdef CONFIG_DEBUG_I2C_ERROR
+  int sval;
+  uint32_t status;
+#endif
 
   i2cinfo("Starting transfer request of %d message(s):\n", count);
 
@@ -735,6 +739,24 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
       return ret;
     }
 
+#ifdef CONFIG_DEBUG_I2C_ERROR
+  /* We should never start at transfer with semaphore already signalled */
+
+  sem_getvalue(&priv->sem_isr, &sval);
+  if (sval != 0)
+    {
+      i2cerr("Already signalled at start? %d\n", sval);
+    }
+
+  /* We should always be idle before transfer */
+
+  status = getreg32(MPFS_I2C_STATUS);
+  if (status != MPFS_I2C_ST_IDLE)
+    {
+      i2cerr("I2C bus not idle before transfer! Status: 0x%x\n", status);
+    }
+#endif
+
   priv->msgv = msgs;
   priv->msgc = count;
 
@@ -827,6 +849,16 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
         i2cinfo("Message %" PRIu8 " transfer complete.\n", priv->msgid);
     }
 
+#ifdef CONFIG_DEBUG_I2C_ERROR
+  /* We should always be idle after the transfers */
+
+  status = getreg32(MPFS_I2C_STATUS);
+  if (status != MPFS_I2C_ST_IDLE)
+    {
+      i2cerr("I2C bus not idle after transfer! Status: 0x%x\n", status);
+    }
+#endif
+
   /* Irq was enabled at mpfs_i2c_sendstart()  */
 
   up_disable_irq(priv->plic_irq);