Hi all,
I'm trying to make a TWI slave application for tiny817.
In my case, the master will address the slave for read operation. The slave should give ACK on address match and then the first byte of data on data interrupt. On successful reception of the byte, master will give ACK if it needs more data, or NACK if it does't need more data. In case of NACK, no data transfer is expected. Immediate stop condition can be expected after the NACK.
I'm using MCP2221 usb-i2c bridge as master. I'm trying to read 3 bytes of data from the slave. It causes 4 data interrupts including a NACK for the final byte.
Everything is fine except NACK. The NACK condition flag RXACK is not getting cleared on stop condition. It lasts up to next successful byte transfer.
This is my TWI slave isr
void I2C_0_isr() { static volatile uint8_t first_byte=0; if (TWI0.SSTATUS & TWI_COLL_bm) { I2C_0_collision_callback(); return; } if (TWI0.SSTATUS & TWI_BUSERR_bm) { I2C_0_bus_error_callback(); return; } if ((TWI0.SSTATUS & TWI_APIF_bm) && (TWI0.SSTATUS & TWI_AP_bm)) { I2C_0_address_callback(); first_byte = 1; return; } if ( ((TWI0.SSTATUS & TWI_DIF_bm) && (!(TWI0.SSTATUS & TWI_RXACK_bm))) || ((TWI0.SSTATUS & TWI_DIF_bm) && first_byte) ) { if (TWI0.SSTATUS & TWI_DIR_bm) { // Master wishes to read from slave I2C_0_read_callback(); TWI0.SCTRLB = (0 << TWI_ACKACT_bp) | TWI_SCMD_RESPONSE_gc; first_byte = 0; return; } else // Master wishes to write to slave { I2C_0_write_callback(); return; } } else if( (TWI0.SSTATUS & TWI_DIF_bm) && (TWI0.SSTATUS & TWI_RXACK_bm)) { TWI0.SCTRLB |= TWI_SCMD_COMPTRANS_gc; return; } // Check if STOP was received if ((TWI0.SSTATUS & TWI_APIF_bm) && (!(TWI0.SSTATUS & TWI_AP_bm))) { I2C_0_stop_callback(); TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc; return; } }
As you can see, I made a special handling to the first byte of transaction since NACK flag set from previous transaction is not yet cleared.
I enabled stop/address match and data interrupts.
On NACK condition, i'm giving a CTRLB write like this.
TWI0.SCTRLB |= TWI_SCMD_COMPTRANS_gc;
I tried the other options like TWI_SCMD_RESPONSE_gc, TWI_SCMD_NOACT_gc or even a dummy data write. No difference or some errors were the results. Can anyone help me on these?
1. What is wrong here?
2. How RXACK can be cleared by the end of each transaction?
Thanks in advance,
Tintu Thomas.