I2C asynchronous slave reception
ID: LPCBARESDK-709
Status: Fixed
First reported: 6.0.14.1114
Fixed in: 6.0.20.1338
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;
}
}