TWI slave on ATmega644: clock stretching does not work

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

Hi,

I can communicate with a ATmega644 as slave on I2C and it works well on low speed. But if I try a clock frequency of more than 50KHz, I see some very strange effects:

- The first byte of two bytes sent to the slave is being ACK-ed, but its value is right-shifted. (I miss the first bit, e.g. if I send a 0x04, I receive 0x02.)
- Sometimes I don't get an ACK for the second byte.

I think both strange effects are due to the fact that apparently the clock stretching mechanism does not work. I can clearly see on the oscilloscope when the AVR pulls down the SDA line, but the clock line is never pulled low by the client.

If I delay writing a '1' to the TWINT bit after being addressed, then I expect a delay on the clock line. But this does not happen.

I have tried to set the lowest to bits of the PORT C Data Direction Register to 1 but this did not change anything. Is there a special register to configure clock stretching?

My Initialisation code is:

#define TWCR_ENABLE         ((1<<TWIE)|(1<<TWEN))
#define TWCR_TWEA           ((1<<TWEA))
#define TWCR_TWINT          ((1<<TWINT))

TWAR = DEFAULT_I2C_ADDRESS << 1;
TWDR = 0xFF;
TWCR = TWCR_ENABLE | TWCR_TWINT;
sei();
TWCR = TWCR_ENABLE | TWCR_TWEA;

Thanks,
Thomas

pycrc -- a free CRC calculator and C source code generator

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

Quote:
- The first byte of two bytes sent to the slave is being ACK-ed, but its value is right-shifted. (I miss the first bit, e.g. if I send a 0x04, I receive 0x02.)
- Sometimes I don't get an ACK for the second byte.

What values are your pull-up resistors?
If not low enough what you describe might occur when raising speed.
Same problem can also happen if your slave is connected to a long wire.

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

What are your I2C speed divisor and prescaler values, and do you obey the possible limitations there are in the datasheet? Hint: Mega64 says the TWBR register should be 10 or bigger.

- Jani

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

Thanks for the reply,

The (external) pull-ups are 2.2kOhm, the cable is about 5cm long.
The flanks of SCL and SDA are very steep (vertical on a screen with 100us/div), which makes me think the it is not related to slow flanks.

I have the TWI Write Collision Flag always set, even though the slave never writes to the I2C bus. Can that be a clue?

Cheers,
Thomas

pycrc -- a free CRC calculator and C source code generator

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

From datasheet:

Quote:
• Bit 3 – TWWC: TWI Write Collision Flag
The TWWC bit is set when attempting to write to the TWI Data Register – TWDR when
TWINT is low. This flag is cleared by writing the TWDR Register when TWINT is high.

Are you setting this flag?
Or is it done by hardware itself?

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

TWBR = 0
Prescaler = 0 (i.e. 1)
I did not set those values, because the ATmega644 is always slave on the bus. Am I wrong?

pycrc -- a free CRC calculator and C source code generator

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

No, only Master use TWBR.
Have you seen this in datasheet:

Quote:
Slave operation does not depend on Bit Rate or Prescaler
settings, but the CPU clock frequency in the Slave must be at least 16 times higher
than the SCL frequency.

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

I'm afraid the Write Collision was a Red Herring: it gets set in my initialisation:

TWDR = 0xFF;
TWCR = TWCR_ENABLE | TWCR_TWINT;

Now I initialise the HW like this:

TWAR = DEFAULT_I2C_ADDRESS << 1;
TWCR = TWCR_ENABLE;
sei();
TWCR = TWCR_ENABLE | TWCR_TWEA; 

And the Write Collision bit is no more set. The original problem (no clock stretching) still persists.

Cheers,
Thomas

pycrc -- a free CRC calculator and C source code generator

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

Yes, I saw this. We run the ATmega644 at 8MHz, so in theory I should be able to run the I2C bus up to 500KHz.

pycrc -- a free CRC calculator and C source code generator

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

Now I'm starting to have no more clues...
I generally use software bit-banged I2C since I never became a friend of hardware TWI in AVR's.
Are you SURE your slave is actually running at 8MHz?

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

Thought that the maximum rate for TWI on an AVR mega was 400 KHz.

Harvey

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

No, but the two specified I2C speed grades which the AVR is compatible with is 0-100kHz and 100kHz-400kHz.

Even if the AVR can do 500kHz I2C, it most propably does not comply with the 400kHz-1MHz specs, it will do it with timings compatible with lower speeds.

- Jani

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

Hi,

I can confirm the clock frequency is 8MHz, external clocking. CKSEL is set to "Ext. Clock; Start-up time: 6 CK + 0 ms", CKDIV = 0. The external frequency is 8MHz.

But again, I don't believe the speed of the device is too low. In fact, the slave address (SLA+R/W) is always being acknowledged. But what I observe is that apparently the ISR does not kick in fast enough: on the oscilloscope I can see that the ISR is executed when the master already transmits the first bit of the following byte.

Odd enough, the second byte gets acknowledged, but it is shifted right by one bit.

This makes me still think that it would work if only I could make the TWI Hardware hold the SCL line low until the ISR sets the TWINT flag (as described in the data sheet).

Can anyone confirm that the ATmega644 TWI can actually do a clock stretching?

Cheers
Thomas

pycrc -- a free CRC calculator and C source code generator

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

Quote:
This makes me still think that it would work if only I could make the TWI Hardware hold the SCL line low until the ISR sets the TWINT flag (as described in the data sheet).

What I meant was: ...until the ISR clears the TWINT flag by writing a '1' to it.

pycrc -- a free CRC calculator and C source code generator

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

At least Mega64 should support it like the datasheet says, but what about the master? What kind of system is transmitting to your AVR? Are those pins open-collector/open-drain and can it cope with clock stretching?

- Jani

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

Quote:
As long as the TWINT Flag is
set, the SCL line is held low. This allows the application software to complete its tasks
before allowing the TWI transmission to continue.

This is from m32 datasheet but probably work exactly the same for your device. So if this is true me think your problem is with the master.
Do you have control of the master so you can add a small delay between bytes?
If I got it correct clocck-stretching would not start until TWINT is set (adress have been recognized) and then it's to late.
I DO have one app with a hardware TWI slave happily ticking (must be lots of others too), so why is this happening to you?
Are there other interrupts blocking TWI ISR?

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

Thanks Jani and Lennart for the replies. I will check the master better. I'm using a Diolan device as master, but I don't have direct access to the code that controls the master.
Tomorrow I will also try with a new USB to I2C converter from www.robot-electronics.co.uk.

pycrc -- a free CRC calculator and C source code generator

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

Just for the record:
the TWI indeed does clock stretching, but the Diolan I2C master ignored this by default, and for some reason I could not spot it in the oscilloscope.
With an Aardvark I2C master I can get more than 400kHz I2C communication! Yay!

pycrc -- a free CRC calculator and C source code generator

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

I also got an Aardvark to play with few weeks ago. A real tool, not some crappy toy whipped up by schoolkids in a garage :)

The Diolan device either ignores the clock line is still low, or has push-pull output. Both are very wrong in terms of I2C specs, compatibility, and if it has push-pull output, it can even break something and smoke will ensue.

But hold your horses, as 400kHz is the official maximum spec for the AVR.

- Jani

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

To be fair I have to say that the Diolan does support clock stretching, but it has to be enabled explicitly. Unfortunately, in this configuration the SCL frequency is throttled(e.g. 80kHz instead of 100kHz).

Thomas

pycrc -- a free CRC calculator and C source code generator