ambiot / ambd_sdk

Release SDK for AmebaD
99 stars 53 forks source link

I2C Slave API fails to recognize the master's final NACK in slave-to-master transmissions #8

Closed xavier862 closed 2 years ago

xavier862 commented 2 years ago

The issue happens when the RTL872x acts as an I2C slave transmitting data to a remote master. The I2C Specification states that a master-receiver must signal the end of the transfer by issuing a NACK to the slave-transmitter. The slave device must recognize this NACK and use it to leave the transmission state – even if the master read fewer bytes than were stored in the slave's Tx FIFO.

In the Ameba D SDK the slave transmission is performed by I2C_SlaveWrite(). In the RTL872x the master's NACK is signaled by the RX_DONE interrupt flag. Unfortunately I2C_SlaveWrite() fails to check this flag, hence does never detect the end of the transmission, which prevents it from returning properly.

The problem can be solved in I2C_SlaveWrite() by changing the final

while((I2C_CheckFlagState(I2Cx, BIT_IC_STATUS_TFE)) == 0);

for

while(((I2C_CheckFlagState(I2Cx, BIT_IC_STATUS_TFE)) == 0) &&
    ((I2Cx->IC_RAW_INTR_STAT & BIT_IC_RAW_INTR_STAT_RX_DONE) == 0));

I2Cx->IC_CLR_INTR;

See full discussion here: https://forum.amebaiot.com/t/rtl8720dn-as-i2c-slave/407/16

Regards

ambiot commented 2 years ago

Fix refer to #13 .