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 f26227f431ba7d0451274b0fdc473236de4cc70d
Author: Max Kriegleder <[email protected]>
AuthorDate: Mon Oct 26 20:58:50 2026 +0100

    arch/arm/nrf53: Use a repeated START for an I2C register read.
    
    nrf53_i2c.c is the nRF52 TWIM driver with more instances and ignores
    I2C_M_NOSTOP the same way. Apply the nRF52 change: a write with
    I2C_M_NOSTOP followed by a read from the same address runs as one TWIM
    transfer with a repeated START. Also indent the frequency switch's case
    labels as on the nRF52 (whitespace only).
    
    Build-tested only (nrf5340-dk with NRF53_I2C0_MASTER); the code is the
    one tested on the nRF52840 and the nRF9160.
    
    Assisted-by: Claude:claude-opus-5-5
    Signed-off-by: Max Kriegleder <[email protected]>
---
 arch/arm/src/nrf53/nrf53_i2c.c | 56 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 10 deletions(-)

diff --git a/arch/arm/src/nrf53/nrf53_i2c.c b/arch/arm/src/nrf53/nrf53_i2c.c
index c1f9d3dd020..429e9b5ae8e 100644
--- a/arch/arm/src/nrf53/nrf53_i2c.c
+++ b/arch/arm/src/nrf53/nrf53_i2c.c
@@ -28,6 +28,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <stdbool.h>
 
 #include <nuttx/debug.h>
 #include <nuttx/irq.h>
@@ -262,6 +263,7 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev,
   struct nrf53_i2c_priv_s *priv = (struct nrf53_i2c_priv_s *)dev;
   uint32_t regval = 0;
   int      ret = OK;
+  bool     rx_after = false;
 #ifndef CONFIG_NRF53_I2C_MASTER_DISABLE_NOSTART
   uint8_t *pack_buf = NULL;
 #endif
@@ -294,25 +296,25 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev,
 
       switch (priv->msgv->frequency)
         {
-            case 100000:
+          case 100000:
             {
               regval = TWIM_FREQUENCY_100KBPS;
               break;
             }
 
-            case 250000:
+          case 250000:
             {
               regval = TWIM_FREQUENCY_250KBPS;
               break;
             }
 
-            case 400000:
+          case 400000:
             {
               regval = TWIM_FREQUENCY_400KBPS;
               break;
             }
 
-            default:
+          default:
             {
               ret = -EINVAL;
               goto errout;
@@ -342,6 +344,8 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev,
       i2cinfo("ptr=%p dcnt=%d flags=%d addr=%d\n",
               priv->ptr, priv->dcnt, priv->flags, priv->addr);
 
+      rx_after = false;
+
       /* Write TWI address */
 
       regval = priv->addr;
@@ -421,10 +425,42 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev,
           regval = priv->dcnt;
           nrf53_i2c_putreg(priv, NRF53_TWIM_TXDMAXCNT_OFFSET, regval);
 
-          /* Shortcut from LASTTX to STOP */
+          /* A write without STOP followed by a read from the same address
+           * (a register read): repeated START into the read, then STOP.
+           * Both run as one transfer ending in one STOPPED event.  Only
+           * for data in both directions, as the shortcuts need the LASTTX
+           * and LASTRX events.
+           */
 
-          nrf53_i2c_putreg(priv, NRF53_TWIM_SHORTS_OFFSET,
-                           TWIM_SHORTS_LASTTX_STOP);
+          rx_after = (priv->flags & I2C_M_NOSTOP) != 0 &&
+                     priv->dcnt > 0 &&
+                     priv->msgc > 1 &&
+                     priv->msgv[1].length > 0 &&
+                     (priv->msgv[1].flags & I2C_M_READ) != 0 &&
+                     (priv->msgv[1].flags & I2C_M_NOSTART) == 0 &&
+                     priv->msgv[1].addr == priv->addr;
+
+          if (rx_after)
+            {
+              regval = (uint32_t)priv->msgv[1].buffer;
+              DEBUGASSERT(nrf53_easydma_valid(regval));
+              nrf53_i2c_putreg(priv, NRF53_TWIM_RXDPTR_OFFSET, regval);
+              nrf53_i2c_putreg(priv, NRF53_TWIM_RXDMAXCNT_OFFSET,
+                               priv->msgv[1].length);
+
+              /* Shortcuts from LASTTX to STARTRX, LASTRX to STOP */
+
+              nrf53_i2c_putreg(priv, NRF53_TWIM_SHORTS_OFFSET,
+                               TWIM_SHORTS_LASTTX_STARTRX |
+                               TWIM_SHORTS_LASTRX_STOP);
+            }
+          else
+            {
+              /* Shortcut from LASTTX to STOP */
+
+              nrf53_i2c_putreg(priv, NRF53_TWIM_SHORTS_OFFSET,
+                               TWIM_SHORTS_LASTTX_STOP);
+            }
 
           /* Start TX sequence */
 
@@ -491,10 +527,10 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev,
         }
 #endif
 
-      /* Next message */
+      /* Next message (two after a write with its read) */
 
-      priv->msgc -= 1;
-      priv->msgv += 1;
+      priv->msgc -= rx_after ? 2 : 1;
+      priv->msgv += rx_after ? 2 : 1;
     }
   while (priv->msgc > 0);
 

Reply via email to