I2C asynchronous slave reception

ID: LPCBARESDK-709

Status: Open

First reported: 6.0.14.1114

Fixed in: TBD

Description

With the current I2C driver it is not possible to successfully receive two I2C frames consecutively, using the asynchronous API while the device is configured as I2C slave. This is due to an error in handling of the interruption status which results in failing to clear the RX done flag during the first transaction.

Workaround

This can be worked around by modifying the I2C driver in the following way.

The proposed implementation also optimizes the number of interruptions during a read request by filling the FIFO based on the number of bytes to send instead of sending bytes one by one.

@@ -600,38 +602,40 @@ static void intr_slave_transmit_buffer_handler(uint16_t mask)
         i2c_reset_int_rx_overflow();
     }

-    if (mask & I2C_INT_STOP_DETECTED)
+    if (mask & I2C_INT_RX_DONE)
     {
         tx_reply(txs->num == txs->len);

-        // Clear stop detected
-        i2c_reset_int_stop_detected();
+        // Clear rx_done
+        i2c_reset_int_rx_done();
         return;
     }

-    if (mask & I2C_INT_RX_DONE)
+               if (mask & I2C_INT_STOP_DETECTED)
     {
         tx_reply(txs->num == txs->len);

-        // Clear rx_done
-        i2c_reset_int_rx_done();
+        // Clear stop detected
+        i2c_reset_int_stop_detected();
         return;
     }

+
     if (mask & I2C_INT_READ_REQUEST)
     {
-        if (txs->num < txs->len && i2c_is_tx_fifo_not_full())
-        {
-            // Write byte to tx fifo
-            i2c_write_byte(txs->data[txs->num++]);
-        }
-        else
-        {
+        if((txs->num >= txs->len) || !i2c_is_tx_fifo_not_full()){
             tx_reply(false);
-        }
-
+        } else {
+            while (txs->num < txs->len && i2c_is_tx_fifo_not_full())
+            {
+                // Write byte to tx fifo
+                i2c_write_byte(txs->data[txs->num++]);
+            }
+
+        }
         // Clear read request
         i2c_reset_int_read_request();
+        return;
     }
 }