1

I have some experience with I²C (TWI) as I used it before, but it seems I can't solve this particular problem. I intend to communicate two CPUs via I²C. One is always the master and the other is the slave. I'm defining the communication protocol myself, so it's somewhat flexible, but I intend it to be as efficient as possible (i.e. the fewer bytes, the better).

I want the slave to set NACK for certain values; for instance:

MASTER = START + sends SLAVE ADDRESS
SLAVE = sets ACK
MASTER = sends any one "byte" command
SLAVE = sets ACK or NACK depending if "byte" was a valid command or not.

The last statement is the problem, because apparently I -as the slave- have to decide for ACK or NACK before receiving the one "byte" command; i.e., in response to TWSR = 0x60 (SLA+W received). The problem is, I don't know in advance if the command will be valid or not! Apparently setting or clearing the TWEA bit is only effective for the next byte to be received.

As much as I digged into the docs, I cannot find a way to respond with NACK "on the fly" because the ATMega sets the interrupt AFTER sending the ACK (or NACK). TWSR will be either 0x80 or 0x88, which means "byte received, ACK sent" and "byte received, NACK sent" respectively.

Aside from adding padding bytes or implementing a bit-banging I²C library, is there some way to solve this?

The master controller is an NXP LPC2148, while the slave controller is an ATMega1284P.

Thank you.

Guillermo Prandi
  • 897
  • 1
  • 10
  • 24

1 Answers1

1

Please don't do that! That's not what I²C ACK/NACK are intended for. They are meant as protocol elements, not as part of the data.

For example, a NACK received on sending the device address will make the host controller signal an "Addressing error", and a NACK received during a transfer of N bytes will make the host controller signal a "Data transmission error" to the calling driver. Meaning, the amount of bytes sent was wrong or the SMBUS checksum failed.

During read transmissions, the NACK usually denotes end of data to receive.

Is it that what you want to signal? I bet not!

EDIT: I give you an example. Please take a look at the DS28E17 Onewire to I²C master bridge. It's an I²C host controller residing on an onewire bus. It does all the I²C communication autonomously and you cannot (you cannot) receive individual ACK/NACKs. You advise that chip to write a number of bytes and it will do so happily. But it won't tell you whether the last bit was ACK or NACK. It can only tell you whether there was an unexpected NACK. So, your slave breaks the protocol and cannot be used behind a DS28E17.

Janka
  • 13,636
  • 1
  • 19
  • 33
  • However, it doesn't seem to be the case. I read in the (*UM10204 I2C-bus specification and user manual) the following: "There are five conditions that lead to the generation of a NACK: [...] 3. During the transfer, the receiver gets data or commands that it does not understand. 4. During the transfer, the receiver cannot receive any more data bytes. [...]". I intend to use it for both [3] and [4]. – Guillermo Prandi Feb 24 '17 at 22:12
  • The fact that there are devices that do not do that (perhaps the AVR included) doesn't mean it couldn't or shouldn't be done! – Guillermo Prandi Feb 24 '17 at 22:17
  • It's practical usage what counts. Please take a look into the various quirks the Linux kernel has to implement to support the plentiful number of broken host adapters *and* broken devices. They are all broken because their designers said "the spec allows it" and then, they use all what the spec allows to the fullest. That's how you send your users right into doom. Please, don't do that! Please design a device which is most compatible to the pandemonium which is already out in the wild. – Janka Feb 24 '17 at 22:20
  • This is not a case of "the specs doesn't denies it, so it's allowed". This is explicit in the spec as an intended usage of the NACK signal. Your answer "That's not what I²C ACK/NACK are intended for" is either your personal opinion (which is irrelevant to my question) or plainly wrong. – Guillermo Prandi Feb 24 '17 at 22:26
  • @Guillermo Prandi: Please continue with your development work in peace and please, refuse to let me take any more look on it. Thank you. – Janka Feb 24 '17 at 22:28
  • Just for the giggles, NXP's SC16IS741A (I²C to UART interface) does exactly what I want to do: sets NACK when its buffer is full. I just want to emulate that behavior from my ATmega. – Guillermo Prandi Feb 24 '17 at 23:15