E70 TWI master read communication problem

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

I've connected two E70 boards via TWI0 to test my TWI master application using a second E70 board running a simple TWI slave test application.

After debugging my application 3 days I finally could reproduce my problem in a few lines of two slightly modified ASF TWI master and slave demos.

 

What I do:

The master tries to read 8 bytes from the slave in a loop.

The slave responds with data until NACK condition has been detected. Slave data is an array with pre-initialized data bytes e.g. 0,1,2,3,....

 

What I expect: Master reads 8 bytes of data

0 1 2 3 4 5 6 7

0 1 2 3 4 5 6 7

0 1 2 3 4 5 6 7

.....

 

What I get: Master reads 8 bytes of data

0 1 2 3 4 5 6 7

8 0 1 2 3 4 5 6

7 0 1 2 3 4 5 6

7 0 1 2 3 4 5 6
....

 

I can see exactly these bytes in the scope. Here are the last 2 bytes of the first 8 byte master read (0 1 2 3 4 5 6 7):

 

and here are last 2 bytes of the second 8 byte master read (8 0 1 2 3 4 5 6):

 

So the problem must somewhere arise on the slave side. The slave write code (snippet) goes like this:

	for (i = 0; i < MEMORY_SIZE; i++) {
		uc_memory[i] = i & 0xff;
	}

	/* Configure TWIHS as slave */
	puts("-I- Configuring the TWIHS in slave mode\n\r");
	twihs_slave_init(BOARD_BASE_TWIHS_SLAVE, SLAVE_ADDRESS);

	/* Clear receipt buffer */
	twihs_read_byte(BOARD_BASE_TWIHS_SLAVE);

	while(1)
	{
		uint32_t cnt = twihs_slave_write(BOARD_BASE_TWIHS_SLAVE, uc_memory);
		printf("Slave sent %ld bytes\n", cnt);
	}

and the master side:

	twihs_master_options_t opt = {
		.speed = 40000,      
		.chip  = TCA6424A_BUS_ADDR
	};

	twihs_package_t sTwiCmd = {
		.addr         = 0,							// TWIHS slave address data
		.addr_length  = 0,							// TWIHS slave address data size
		.chip         = TCA6424A_BUS_ADDR,			// TWIHS slave bus address
		.buffer       = (void *)data_buffer,		// transfer data source buffer
	};
		
	twihs_master_setup( TWIM0, &opt);

	while(1)
	{
		sTwiCmd.length = 8;
		status = twihs_master_read(TWIM0, &sTwiCmd);
		if( status == TWIHS_SUCCESS )
			printf("Master read %ld bytes\n", sTwiCmd.length);

		for(uint8_t i=0; i<sTwiCmd.length; i++)
		{
			if(data_buffer[i] != i)
				printf("Master read %d, expected %d\n", data_buffer[i], i);
		}
	}

Slave terminal output:

-I- Configuring the TWIHS in slave mode

Slave sent 9 bytes
Slave sent 8 bytes
Slave sent 8 bytes
Slave sent 8 bytes

Master terminal output:

-- SAME70-XPLD --
-- Compiled: Sep  4 2017 16:06:07 --

Master read 8 bytes
Master 8 bytes test OK
Master read 8 bytes
Master read 8, expected 0
Master read 0, expected 1
Master read 1, expected 2
Master read 2, expected 3
Master read 3, expected 4
Master read 4, expected 5
Master read 5, expected 6
Master read 6, expected 7
Master read 8 bytes
Master read 7, expected 0
Master read 0, expected 1
Master read 1, expected 2
Master read 2, expected 3
Master read 3, expected 4
Master read 4, expected 5
Master read 5, expected 6
Master read 6, expected 7

 

I assume that in the first transfer cycle the slave writes 9 bytes into the TWI transmit register but because the master only clocks in only 8 bytes "0...7"  and the 9th byte ("8") remains in transmit register.

In the second 8 byte master read the remaining byte ("8") is sent in front of the test data before the requested data "0...7" is sent. Now the "7" remains unsent in the transmit register and is sent first at the next master read a.s.o.

 

Looking into the ASF slave read function code

uint32_t twihs_slave_write(Twihs *p_twihs, uint8_t *p_data)
{
	uint32_t status, cnt = 0;

	do {
		status = p_twihs->TWIHS_SR;
		if (status & TWIHS_SR_SVACC) {
			if (!(status & (TWIHS_SR_GACC | TWIHS_SR_NACK)) &&
			((status & (TWIHS_SR_SVREAD | TWIHS_SR_TXRDY))
			== (TWIHS_SR_SVREAD | TWIHS_SR_TXRDY))) {
				p_twihs->TWIHS_THR = *p_data++;
				cnt++;
			}
		} else if ((status & (TWIHS_SR_EOSACC | TWIHS_SR_TXCOMP))
					== (TWIHS_SR_EOSACC | TWIHS_SR_TXCOMP)) {
			break;
		}
	} while (1);

	return cnt;
}

Now my assumption is that after the transfer of the 8th byte the TX bit is set before the NACK bit and a 9th byte is written into the transmit register. This is probably a timing problem due to a race condition.

 

The E70 manual master read timing suggests that the NACK is always set before or at the same time as TX bit is set and the ASF code seems to rely on this:

 

Regarding the results above my only explanation is that NACK is (sometimes?) set after TX bit. Surprisingly this flowchart does not care about NACK bit:

 

 

although the I2C specification states that the slave shall stop sending bytes if NACK condition is detected:

 

A master-receiver is done reading data and indicates this to the slave through a NACK.

Am I wrong ? Who is right ? Has anyone seen such a problem before ?

SAME newbie

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

I am having a problem with the TWIHS as well where if poll the status register the system stops working.  I think what is happening is that there is a race condition where the TWIHS hardware can not set the status register while it is being read.  I have been fighting this problem for a few days and can not find any solution.  Did you happen to find one? 

 

Thanks

Trampas