Bug: I2C master reader reads extra one byte

I'm quite new to bug reporting on a forum. I'm sorry if this article seems not friendly for you.

******** Phenomenon ************
Wire.requestFrom(slav_addr, read_len) doesn't output NACK until {read_len+1}bytes of read is over.

******** How I found this bug **************
I'm using Arduino 0016 and found this bug when I tried to use an EEPROM(24C1024) from Arduino(pro mini 328) via I2C communication with Wire Library.
The EEPROM I use is designed to read sequentially: reading without specifying an address means reading from the next byte of the last read.

First I tested read and write operation like follows:

  1. write each byte data 0 to 255 into address 0 to 255
  2. read one byte using {Wire.requestFrom(ARRD, 1)} and send result w/ serial com using {while(Wire.available()){println((int)Wire.receive());}}.
  3. Repeat "2." 256 times.
    This test supposed to output:
    0
    1
    2
    3
    ...
    255
    on the serial monitor. But the result I've got was:
    0
    2
    4
    ....
    This seems a bug described as follows:
  • Wire.requestFrom(ADDR, 1) reads two bytes (=extra one byte) from EEPROM
  • but Wire.available() returns 1 (though this supposed to be the # of buffered bytes)

Debugging using oscilloscope revealed that:

  • NACK which supposed to come right after read a byte comes after two bytes of read in reality

Then I looked into sources of Wire library.
Wire.requestFrom() calls another library function twi_readFrom() in Wire/utility/twi.c and this funciton just sets registers to start master reader.
So the problem must be in the Interrupt handler: SIGNAL(TWI_vect) in Wire/utility/twi.c.

*********** How to fix this bug *************
As a result, I could fix this bug by editing three points in Wire/utility/twi.c.

$ diff twi.c.orig twi.c
126a127,129

if(length < 1){
return 0;
}
152c155
< if (twi_masterBufferIndex < length)


//if (twi_masterBufferIndex < length)
374c377
< if(twi_masterBufferIndex < twi_masterBufferLength){


if(twi_masterBufferIndex < (twi_masterBufferLength - 1)){

I beleive there was a correction for this in version 0017 so you may want to grab a copy of the latest update to the wire library.

BenF

Thank you for informing updates!
I confirmed that the problem has been got rid of correctly :slight_smile:

sagiii