How to clear RXACK flag in TWI slave of tiny817?

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

--TintuVayalattu

Last Edited: Sat. Jan 27, 2018 - 05:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TintuVayalattu wrote:

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.

 

As I understand it, the Master in Receive mode simply does not acknowledge at all after the last byte it wants to receive. I quote from Philips 'The I2C-Bus Specification Version 2.1 January 2000', page 10:

 

If a master-receiver is involved in a transfer, it must signal
the end of data to the slave- transmitter by not generating
an acknowledge on the last byte that was clocked out of
the slave. The slave-transmitter must release the data line
to allow the master to generate a STOP or repeated
START condition.

 

Does this help?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can clear RXACK, RIF, WIF, ARBLOST, BUSERR by writing 1 to the appropriate bit(s)

 

In practice,  you do not normally need to do this.   e.g. RXACK will get cleared with the next successful i2c_start(MADDR)

 

My apologies.   You are using the TWI Slave.

It should work just the same.   i.e. write a 1 to DIF, APIF, ...

 

David.

Last Edited: Tue. Feb 13, 2018 - 11:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi @jbug11,

 

Thanks for the response!

 

Actually, I cannot control the master receiver. I'm using USB I2C clickboard as a reference master device. That gives a NACK after the final byte, which sets the RXACK flag.

--TintuVayalattu

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
My apologies.   You are using the TWI Slave.

It should work just the same.   i.e. write a 1 to DIF, APIF, ...

You can, but why, normally these are completely unnecessary.  Read the fine manual, paragraph 26.5.10 Slave Control B.  New chips David, new rules!

 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius