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 141d5f80653274b1d949f449bc4a4f8d475d0f79
Author: Eren Terzioglu <[email protected]>
AuthorDate: Thu Mar 20 10:52:39 2025 +0100

    arch/risc-v/esp32[c3|c6|h2]: Fix I2C Slave driver write bug
    
    Fix I2C Slave driver write bug when multiple write operation existed for 
risc-v based Espressif devices
    
    Signed-off-by: Eren Terzioglu <[email protected]>
---
 arch/risc-v/src/common/espressif/esp_i2c_slave.c | 76 ++++++++++++++++--------
 arch/risc-v/src/common/espressif/esp_i2c_slave.h |  4 +-
 2 files changed, 52 insertions(+), 28 deletions(-)

diff --git a/arch/risc-v/src/common/espressif/esp_i2c_slave.c 
b/arch/risc-v/src/common/espressif/esp_i2c_slave.c
index 151f631173..163ad409eb 100644
--- a/arch/risc-v/src/common/espressif/esp_i2c_slave.c
+++ b/arch/risc-v/src/common/espressif/esp_i2c_slave.c
@@ -38,6 +38,7 @@
 #include <debug.h>
 #include <time.h>
 #include <sys/time.h>
+#include <sys/param.h>
 
 #include <nuttx/arch.h>
 #include <nuttx/irq.h>
@@ -74,6 +75,7 @@
 #define I2C_SLAVE_TIMEOUT_DEFAULT     32000                /* I2C slave 
timeout value, APB clock cycle number */
 #define I2C_SLAVE_SDA_SAMPLE_DEFAULT  10                   /* I2C slave sample 
time after scl positive edge default value */
 #define I2C_SLAVE_SDA_HOLD_DEFAULT    10                   /* I2C slave hold 
time after scl negative edge default value */
+#define I2C_SLAVE_BUFF_SIZE           1024
 #ifdef CONFIG_I2C_POLLED
 #define I2C_SLAVE_POLL_RATE           10
 #endif
@@ -121,16 +123,16 @@ struct esp_i2c_priv_s
   bool enabled;
 #endif
 
-  uint32_t error;                   /* I2C transform error */
-  i2c_hal_context_t *ctx;           /* Common layer struct */
-  int addr;                         /* Slave device address */
-  int nbits;                        /* Slave device address bit count */
-  i2c_slave_callback_t *cb;         /* Callback function when interrupt 
happens */
-  void *cb_arg;                     /* Argument of callback function */
-  uint32_t tx_length;               /* Location of next TX value */
-  uint8_t *tx_buffer;               /* I2C Slave TX queue buffer */
-  uint32_t rx_length;               /* Location of next RX value */
-  uint8_t *rx_buffer;               /* I2C Slave RX queue buffer */
+  uint32_t error;                         /* I2C transform error */
+  i2c_hal_context_t *ctx;                 /* Common layer struct */
+  int addr;                               /* Slave device address */
+  int nbits;                              /* Slave device address bit count */
+  i2c_slave_callback_t *cb;               /* Callback function when interrupt 
happens */
+  void *cb_arg;                           /* Argument of callback function */
+  uint32_t tx_length;                     /* Location of next TX value */
+  uint8_t tx_buffer[I2C_SLAVE_BUFF_SIZE]; /* I2C Slave TX queue buffer */
+  uint32_t rx_length;                     /* Location of next RX value */
+  uint8_t rx_buffer[I2C_SLAVE_BUFF_SIZE]; /* I2C Slave RX queue buffer */
 };
 
 /****************************************************************************
@@ -172,7 +174,7 @@ static const struct i2c_slaveops_s esp_i2c_ops =
   .registercallback = esp_i2c_slave_registercallback,
 };
 
-#ifdef CONFIG_ESPRESSIF_I2C0_SLAVE
+#ifdef CONFIG_ESPRESSIF_I2C0_SLAVE_MODE
 
 i2c_hal_context_t i2c0_ctx =
 {
@@ -216,13 +218,19 @@ static struct esp_i2c_priv_s esp_i2c0_priv =
   .cb         = NULL,
   .cb_arg     = NULL,
   .tx_length  = 0,
-  .tx_buffer  = NULL,
+  .tx_buffer  =
+  {
+    0
+  },
   .rx_length  = 0,
-  .rx_buffer  = NULL
+  .rx_buffer  =
+  {
+    0
+  },
 };
 #endif
 
-#ifdef CONFIG_ESPRESSIF_I2C1_SLAVE
+#ifdef CONFIG_ESPRESSIF_I2C1_SLAVE_MODE
 
 i2c_hal_context_t i2c1_ctx =
 {
@@ -266,9 +274,15 @@ static struct esp_i2c_priv_s esp_i2c1_priv =
   .cb         = NULL,
   .cb_arg     = NULL,
   .tx_length  = 0,
-  .tx_buffer  = NULL,
+  .tx_buffer  =
+  {
+    0
+  },
   .rx_length  = 0,
-  .rx_buffer  = NULL
+  .rx_buffer  =
+  {
+    0
+  },
 };
 #endif /* CONFIG_ESPRESSIF_I2C1 */
 
@@ -380,10 +394,11 @@ static int esp_i2c_slave_write(struct i2c_slave_s *dev,
 
   /* Update the registered buffer and length */
 
-  priv->tx_buffer = buffer;
-  priv->tx_length = buflen;
+  cnt = MIN(I2C_SLAVE_BUFF_SIZE - priv->tx_length, buflen);
+  memcpy(priv->tx_buffer + priv->tx_length, buffer, cnt);
+  priv->tx_length += cnt;
 
-  if (buflen > 0)
+  if (priv->tx_length > 0)
     {
       i2c_ll_slave_enable_tx_it(priv->ctx->dev);
     }
@@ -423,16 +438,20 @@ static int esp_i2c_slave_read(struct i2c_slave_s *dev,
 {
   struct esp_i2c_priv_s *priv = (struct esp_i2c_priv_s *)dev;
   irqstate_t flags = enter_critical_section();
+  int read_len = ERROR;
 
   /* Update the registered buffer and length */
 
   i2c_ll_slave_enable_rx_it(priv->ctx->dev);
-  priv->rx_buffer  = buffer;
-  priv->rx_length = buflen;
+
+  read_len = MIN(priv->rx_length, buflen);
+  memcpy(buffer, priv->rx_buffer, read_len);
+  memmove(priv->rx_buffer, priv->rx_buffer + read_len, read_len);
+  priv->rx_length -= read_len;
 
   leave_critical_section(flags);
 
-  return OK;
+  return read_len;
 }
 
 /****************************************************************************
@@ -733,8 +752,10 @@ static void esp_i2c_process(struct esp_i2c_priv_s *priv,
       evt_type == I2C_INTR_EVENT_RXFIFO_FULL)
     {
       i2c_ll_get_rxfifo_cnt(priv->ctx->dev, &rx_fifo_cnt);
-      i2c_ll_read_rxfifo(priv->ctx->dev, priv->rx_buffer, rx_fifo_cnt);
-      priv->rx_length -= rx_fifo_cnt;
+      rx_fifo_cnt = MIN(I2C_SLAVE_BUFF_SIZE - priv->rx_length, rx_fifo_cnt);
+      i2c_ll_read_rxfifo(priv->ctx->dev, priv->rx_buffer + priv->rx_length,
+                         rx_fifo_cnt);
+      priv->rx_length += rx_fifo_cnt;
 
       /* Code closed for temporary time due to upper layer function issues */
 
@@ -748,9 +769,12 @@ static void esp_i2c_process(struct esp_i2c_priv_s *priv,
   else if (evt_type == I2C_INTR_EVENT_TXFIFO_EMPTY)
     {
       i2c_ll_get_txfifo_len(priv->ctx->dev, &tx_fifo_rem);
+      tx_fifo_rem = MIN(priv->tx_length, tx_fifo_rem);
       if (tx_fifo_rem != 0)
         {
           i2c_ll_write_txfifo(priv->ctx->dev, priv->tx_buffer, tx_fifo_rem);
+          memmove(priv->tx_buffer, priv->tx_buffer + tx_fifo_rem,
+                  tx_fifo_rem);
         }
       else
         {
@@ -806,12 +830,12 @@ struct i2c_slave_s *esp_i2cbus_slave_initialize(int port, 
int addr)
 
   switch (port)
     {
-#ifdef CONFIG_ESPRESSIF_I2C0_SLAVE
+#ifdef CONFIG_ESPRESSIF_I2C0_SLAVE_MODE
     case ESPRESSIF_I2C0_SLAVE:
       priv = &esp_i2c0_priv;
       break;
 #endif
-#ifdef CONFIG_ESPRESSIF_I2C1_SLAVE
+#ifdef CONFIG_ESPRESSIF_I2C1_SLAVE_MODE
     case ESPRESSIF_I2C1_SLAVE:
       priv = &esp_i2c1_priv;
       break;
diff --git a/arch/risc-v/src/common/espressif/esp_i2c_slave.h 
b/arch/risc-v/src/common/espressif/esp_i2c_slave.h
index 4eb7189190..29477bca77 100644
--- a/arch/risc-v/src/common/espressif/esp_i2c_slave.h
+++ b/arch/risc-v/src/common/espressif/esp_i2c_slave.h
@@ -37,11 +37,11 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_ESPRESSIF_I2C0_SLAVE
+#ifdef CONFIG_ESPRESSIF_I2C0_SLAVE_MODE
 #  define ESPRESSIF_I2C0_SLAVE 0
 #endif
 
-#ifdef CONFIG_ESPRESSIF_I2C1_SLAVE
+#ifdef CONFIG_ESPRESSIF_I2C1_SLAVE_MODE
 #  define ESPRESSIF_I2C1_SLAVE 1
 #endif
 

Reply via email to