I2C master driver for AVR

ChibiOS public support forum for topics related to the Atmel AVR family of micro-controllers.

Moderator: tfAteba

Post Reply
utzig
Posts: 359
Joined: Sat Jan 07, 2012 6:22 pm
Has thanked: 1 time
Been thanked: 20 times

I2C master driver for AVR

Post by utzig »

Hello,

Attached is an initial I2C peripheral driver for AVR processor. It was tested with the Arduino Mega with an external FM24C64 FRAM connected on the I2C channel. I only tested with external pull-ups. I'll test with the internal PORT pull-ups and if it works I'll make a patch just with the correct configuration.

This version has the following limitations:

1. Doesn't have timeouts (always INFINITE)
2. Doesn't support acting as a slave on the bus.

Fabio Utzig
Attachments
avr_platform.patch.gz
AVR's platform.(mk|dox) support for I2c
(477 Bytes) Downloaded 690 times
avr_i2c_files.tgz
AVR I2C driver source files
(3.54 KiB) Downloaded 745 times
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Been thanked: 7 times

Re: I2C master driver for AVR

Post by barthess »

Using internal pull-ups for I2C is commonly bad idea because their resistance is too high. Good value for I2C is 1k..5k1 (for 3.3v supply voltage). What resistance have pull-ups in AVR?
utzig
Posts: 359
Joined: Sat Jan 07, 2012 6:22 pm
Has thanked: 1 time
Been thanked: 20 times

Re: I2C master driver for AVR

Post by utzig »

The Manual says Min: 20k, Max: 50k. I'm using external 10k pull-ups with 5V.

Fabio Utzig
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Been thanked: 7 times

Re: I2C master driver for AVR

Post by barthess »

Hm... try them, but check results with oscilloscope. Let us know, how it works.
utzig
Posts: 359
Joined: Sat Jan 07, 2012 6:22 pm
Has thanked: 1 time
Been thanked: 20 times

Re: I2C master driver for AVR

Post by utzig »

It sometimes works and sometimes don't. First I tried using only the internal pull-ups and it worked at both 100khz and 400khz clocks. Disabling the pull-ups returns NOT ACK errors as expected. But when I added the oscilloscope it just stopped working. Then removing it it still didn't work. What happens is that it sometimes work and sometimes don't. When it stops working the SDA line is pulled down. This causes the TWI subsystem to hang forever and the thread that is using the I2C driver also hangs 'cause there's not TIMEOUT implemented yet.

With external pull-ups it seems to always work.

Fabio Utzig
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Been thanked: 7 times

Re: I2C master driver for AVR

Post by barthess »

Try to slow down I2C clock. Pull up resistors in I2C needed to return line state to logical "1". More resistance cause more time to recharge line parasitic capacitance, oscilloscope probe adds its own capacitance. Read this article http://dsscircuits.com/articles/effects ... stors.html
utzig
Posts: 359
Joined: Sat Jan 07, 2012 6:22 pm
Has thanked: 1 time
Been thanked: 20 times

Re: I2C master driver for AVR

Post by utzig »

Hi barthess,

Right now I'm using 3.9K resistors and a clock of 100khz. It's been running for 3 hours without problems. I'm using a "wired-up" I2C FRAM (FM24C64).

Yesterday I was using another board but with the FRAM soldered on board and with 10K resistors and 400KHz (running ChibiOS). I've been using the I2C on this board for 2 months with that configuration without errors (barebones FW with no OS).

Fabio Utzig
utzig
Posts: 359
Joined: Sat Jan 07, 2012 6:22 pm
Has thanked: 1 time
Been thanked: 20 times

Re: I2C master driver for AVR

Post by utzig »

By the way now I read the article. Very good!
utzig
Posts: 359
Joined: Sat Jan 07, 2012 6:22 pm
Has thanked: 1 time
Been thanked: 20 times

Re: I2C master driver for AVR

Post by utzig »

There's an "error" which can happen now when running on an multi-master configuration.

Code: Select all

  default:
    /* FIXME: only gets here if there are other MASTERs in the bus */
    TWCR = ((1 << TWSTO) | (1 << TWINT) | (1 << TWEN));
    wakeup_isr(i2cp, RDY_RESET);


The "default" in the IRQ handler's switch statement doesn't set errors variable to a valid error. So the i2c call will return an error status but i2cGetError will return I2CD_NO_ERROR. That could only happen if there's other master in the bus or if TWSR is read before it's updated which can't happen because the code is interrupt based.

The correct code for the default should probably be:

Code: Select all

  default:
    /* FIXME: only gets here if there are other MASTERs in the bus */
    i2cp->errors |= I2CD_BUS_ERROR;


Although this is not exactly correct, I guess, since there's no I2CD_SOME_UNKNOWN_ERROR that would do the trick for now.

Fabio Utzig
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: I2C master driver for AVR

Post by Giovanni »

I merged the driver.

Giovanni
Post Reply