TWI Slave - How to detect Master has finished sending

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

Hi Guys,

 

I'm having problems determining when the master has finished sending to the slave.

 

I've got some code running on a Atmega324PB which is connected to an arduino Uno running the wire library as a master.

 

I'm trying to determine when the master has finished sending data to the slave.  

 

I know that I could figure it out depending on the register it's writing to, but I'm trying to cater for user error, where more data is sent than is supposed to.

 

The slave is interrupt driven

 

regards

 

This topic has a solution.

Nik Middleton

 

Last Edited: Sun. Jun 30, 2019 - 09:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Either the amount of data needs to be known beforehand

by both master and slave, or the slave tells the master

when it's had enough.  The slave responds to each byte

sent with an ACK or a NACK, so when it wants to say

"stop sending data" it responds with NACK.  An ACK from

the slave lets the master know it can send another byte.

 

--Mike

 

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

Thank you, I figured it had to be something simple.  Just have to do some digging now  to figure out how to get the slave to send a NACK

 

regards

 

Nik Middleton

 

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

See the description for the TWEA bit in the

TWCR register in the datasheet.

 

--Mike

 

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

Thanks for the pointer.  According to the datasheet, I simply set TWEA to 0 and then back to 1 when the next byte is received.  Is this correct?

If it is, then I still have an issue.

 

If the slave is expecting 2 Bytes then I won't know I need to send the NACK until I get the 3rd Byte.  But what then happens if the master is done sending at that point?  My callback function won't be called.

 

regards

 

 

From Datasheet

"If the TWCRn.TWEA bit is reset during a transfer, the TWI will return a "Not Acknowledge" ('1') to SDA after the next received data byte. This can be used to indicate that the Slave is not able to receive any more bytes. While TWEA is zero, the TWI does not acknowledge its own slave address. However, the 2- wire Serial Bus is still monitored and address recognition may resume at any time by setting TWEA. This implies that the TWEA bit may be used to temporarily isolate the TWI from the 2-wire Serial Bus."

Nik Middleton

 

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

If your slave is going to receive only two bytes,

then it will want to respond with ACK for the first

byte and then a NACK after the second byte.  The

TWEA bit needs to be set to one while receiving

the first byte, and then make sure it gets set to

zero before the second byte is received.

 

Set TWEA back to one after you get the 2nd byte so

the slave will respond the next time its address is

recognized.

 

The ACK/NACK thing is used when the amount of

data sent is variable.  If it's always two bytes, the

master may be expecting two ACKs.

 

--Mike

 

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

The slave needs to Ack all bytes, if sent more then it needs, it just ignores the extra.
The master sends Stopwhen it’s done sending.
Jim

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From a Master's perspective,   she can send as many bytes as she likes.   Each byte is ACKed by the Slave.   The "end" is signalled by a STOP or REP_START.

The Slave has to detect STOP and REP_START.    TWI, TWIS, USI can generate interrupts for a detected STOP or START.

 

From a Master's perspective,   she can receive as many bytes as she likes from the Slave.   The Master "requests" a byte from the Slave.   The Master tells the Slave to send the last byte with NAK.    After the last byte,  the Master does STOP or REP_START.

 

The Slave must obviously respect the Master's ACK or NAK.

Likewise,   an unhappy Slave can NAK any bytes sent by the Master.   The Master must respect her Slave.

 

There are no timeouts in I2C.    If you (as a Slave) want to recover from a badly behaved Master,   you can implement some form of timeout.

 

Or the Slave implements a known behaviour.   e.g. the Slave starts  NAKing addresses or data when busy.

This is what 24Cxxx EEPROMs do while they are busy with a Page-Write.

 

David.

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

Disclaimer, I've not used slave mode on AVR, but based on my reading of datasheet :

As an example, if as slave you received 2 bytes then don't want to receive any more, the sequence would be

 

i) get interrupt (or polling TWINT high) after SLA+W to your address (hardware has already returned ACK for SLA+W), keep TWEA high

ii) get interrupt (or polling TWINT high) after the 1st byte received (hardware has already returned ACK for this byte),  keep TWEA high

iii) get interrupt (or polling TWINT high) after the 2nd byte received (hardware has already returned ACK for this byte), now  set TWEA  low.

iv) get interrupt (or polling TWINT high) after the 3rd byte received (hardware has already returned NACK for this byte), you can now set TWEA high again.

 

When master gets the NACK it should give up trying to send any more (and probably do a STOP condition).

 

The status code should tell you at each stage what has happened Table 21-4 for slave receiver mode in the datasheet I'm reading.

 

EDIT.

Hang on, avr-mike is right in post #6.

You can set TWEA low after receiving the 1st byte.

i) get interrupt (or polling TWINT high) after SLA+W to your address (hardware has already returned ACK for SLA+W), keep TWEA high

ii) get interrupt (or polling TWINT high) after the 1st byte received (hardware has already returned ACK for this byte),  now set TWEA low

iii) get interrupt (or polling TWINT high) after the 2nd byte received (hardware has already returned NACK for this byte), you can now set TWEA  high again.

 

EDIT2.

Unless, if the master gets a NAK, it will then try and send the NAk'd byte again at some later point. In that case, maybe you would need the striked-through sequence ie. set TWEA low after 2nd byte.

 

Last Edited: Sun. Jun 30, 2019 - 09:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm, so the only place I should send an NACk is if an invalid register is addressed on the slave I guess as I should always expect at least one more byte on a write from the master.  In order to make the slave robust and in the case where I don't get the second byte, perhaps a timeout to turn the TWEA bit back on so as not to hang the slave?

 

regards

 

Nik Middleton

 

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

Thanks Guys, Excellent responses all round, much appreciated.  While the master is well documented, the slave less so.

 

regards

 

Nik Middleton

 

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

No.   Bear in mind that a Master can do anything and everything wrong.

 

You only have to look at all the student "I want to write my own  TWI Master code"

1.   they write void functions.

2.   they do not examine a Slave's ACK/NAK

3.   they do not clear TWEA for the last receive.

 

Write your Slave.

Write a Test Suite with all Master "mishaps"

I doubt if you will get 100% robust Slave but you should be able to respond to / recover from all the common problems.

 

David.

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

nikm wrote:

Hmm, so the only place I should send an NACk is if an invalid register is addressed on the slave I guess as I should always expect at least one more byte on a write from the master.  In order to make the slave robust and in the case where I don't get the second byte, perhaps a timeout to turn the TWEA bit back on so as not to hang the slave?

That's a good point.

If it is necessary for the slave to NAK in some scenario, I think you're right, you can't guarantee that the master will send any more bytes in this transfer before issuing a STOP, and I don't think the hardware gives you any way of knowing when it has seen a STOP on the bus, so a timoeut sounds like a good plan. If the master does a STOP/START/SLA+W to your address before the timeout has expired then it will see NAK for the SLA+W and know that it has to try again.

I also don't see any way (using the TWI hardware) you can determine whether to ACK or NAK in the time between receiving the 8th data bit and the 9th ACK/NAK bit, so you have to have decided in advance.

The more I think about it, if you can devise a protocol for the slave behaviour (which you get to define) such that it never needs to NAK and can just ACK everything, that sounds a lot simpler!

eg. is it acceptable for the slave to silently ignore invalid address (ACKs it but then simply ignores whatever follows), or do you really need to inform the master that it sent something invalid.

 

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

MrKendo wrote:
eg. is it acceptable for the slave to silently ignore invalid address

Well that is how the protocol works, if the address is invalid, do nothing, the NAK in that case is natural result of not ACKing do to the open collector nature of the bus.

The Slave should NAK when the master sends data and the slave is not ready for it, then the master will try again at a later time. 

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

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

A NAK is simply "ignore".

An ACK is actively pulling the Open Collector bus low.

 

David.

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

ki0bk wrote:

MrKendo wrote:

eg. is it acceptable for the slave to silently ignore invalid address

 

Well that is how the protocol works, if the address is invalid, do nothing, the NAK in that case is natural result of not ACKing do to the open collector nature of the bus.

By invalid address I didn't mean the slave address as used for the SLA+W, I meant if you are building a slave, and your slave implements a number of 'register addresses' that you can write a value to to make the slave do something, then what if one of those 'addresses' is invalid. eg. <SLA+W><addr><data> where the <SLA+W> is correct but <addr> may be invalid.

eg. addr is specified as it has to be 1, 2 or 3, but you send 4.

You could very easily specify that the slave will just ignore it (but will still ACK).

Likewise if you send more than 1 <data>, the slave could just ignore the extra (but will still ACK).

 

 

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

In that case, how the slave responds is up to you....

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274