I've written a polled master TWI byte-read routine for an ATtiny814 (in C++) - it waits for RIF bit to be set in the MSTATUS register, as described in the datasheet:
The polling for the read+ACK works (i.e. when I am reading multiple bytes & there are more bytes to be read), but the polling for the read+NACK (i.e. reading the last byte) does not work - the RIF bit never gets set.
Here is the code (bPutACK is set by the calling routine depending on whether or not this is the last byte to be read from the slave):
uint8_t TWI_read_data(bool bPutACK, uint8_t &data) { if(bPutACK) TWI0.MCTRLB &= ~(1 << TWI_ACKACT_bp); // More bytes to receive, setup ACK else TWI0.MCTRLB |= TWI_ACKACT_NACK_gc; // Next byte will be last to be received, setup NACK // Read data from MDATA register data = TWI0.MDATA; if(bPutACK) TWI0.MCTRLB |= TWI_MCMD_RECVTRANS_gc; // More bytes to come, so execute ACK (followed by byte read) else TWI0.MCTRLB |= TWI_MCMD_STOP_gc; // End of read, so execute NACK succeeded by issuing a STOP condition // RIF bit of MSATUS gets set to 1 when master byte read operation has completed // For some reason this does not apply if NACK is executed by master... while (!(TWI0.MSTATUS & TWI_RIF_bm)); return TWI0.MSTATUS; }
The "while (!(TWIo.MSTATUS & TWI_RIF_bm));" line is where the polling is done. It works fine for read+ACK, but not for read+NACK (the while loop just continues forever). I can comment out this line for read+NACK and the program will continue just fine with the correct data being read from the slave device - it's just that the RIF bit never seems to get set.
This person seemed to have the same issue:
https://www.avrfreaks.net/forum/attiny814-i2c-code
Is there something I'm missing with regards to TWI polling on the tinyAVR 1-series?
Rob