Bug in twi.c

I set up a master/slave test and found that aweiler is correct when pointing out that the TWI/ISR is indeed not called once NACK has been returned in response to slave receive data. The issue then is that our slave receiver remains disabled and so further communication from master to slave is no longer possible.

The condition that triggers this issue is as follows (TWI_BUFFER_LENGTH as configured for slave):

  • Enable twi for slave receive
  • Master sends “TWI_BUFFER_LENGTH + 2” bytes or more to slave
  • Receiver is now disabled

A fix for this might be as follows:

    case TW_SR_DATA_NACK:       // data received, returned nack
    case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack
      // reset buffer
      twi_rxBufferIndex = 0;
      // ack future responses and leave slave receiver state
      twi_releaseBus();
      break;

The above patch will reset state and allow communication as either slave, master or both to continue.

In the case when “TWI_BUFFER_LENGTH + 1” bytes are received, one byte will be lost with no error returned to master. A fix for this additional issue may be as follows:

    case TW_SR_DATA_ACK:       // data received, returned ack
    case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack
      // if there is still room in the rx buffer
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH)
          twi_rxBuffer[twi_rxBufferIndex++] = TWDR;	// put byte in buffer

      // can we accept additional bytes
      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH)
	  twi_reply(1);	// yes, ack additional bytes
      else
      	  twi_reply(0);	// no, nack if master sends additional byte
      break;

The above patch will return an error to master whenever number of bytes received exceeds maximum slave receiver buffer capacity.