Internal handling of I2C(slave)-traffic

03 Mar 2012

Hello,

I'm wondering how the internal handling of i2c-slave is accomplished. As I understand the documentation this is done by polling the slave.receive() function to check if new data has arrived.

When I'm using mbed to to other things, too - let's say, a webserver, this might use pretty much processing time which might beeing used better at other parts of my project.

How could I provide an interrupt-driven routine which is only called when there is a need to instead of testing over and over again? Especially I don't know what happens when an attached i2c-master sends data which isn't beeing processed in time - is that data stored to a receive buffer and does it get overwritten if another write access is done by the master side (in my case, this would be O.K., but I can't imagine this to be so)?

Why isn't there a method like 'Ticker' or 'Timeout' which could be used? Or am I thinking the wrong way around...?

Every hint is welcome...

Michael

03 Mar 2012

The I2C hardware engine on the lpc1768 is a rather complicated state machine that generates interrupts on events like receiving a new byte. The interrupt handler must then decide on the next action, like reading the byte from the receive register and storing it. It seems that the current slave implementation is not really interrupt driven but blocking with a timeout. So after the init it is ready to receive data and waits for its slave address. You have to poll to find out if that happened. The I2C engine will block further traffic on the bus until your code has handled the event. This is done by pulling the SCL low. You may be able to intercept the interrupt and avoid polling the i2c.receive and still use i2c.read, which will still be blocking. However, best solution is probably to use your own fully interrupt driven i2c slave software. There are good examples on the internet.

With the current mbed lib you can use a ticker that checks the receive and reads the data. Obviously this read is still blocking

03 Mar 2012

Hello Wim,

this is exactly the scenario I expected... I knew about the interrupt-capability of the hardware, but I can't figure out why this is handled the way it is (with blocking). As I'm really new to c++ it's going to become a hard way to accomplish what I want to do - especially because the hardware I'm connecting throws an error itself when it's not beeing serviced within a given time (in fact when SCL is kept low). If you have a link or something similar to give a start for programming a own interrupt routine I'd be glad for any hint...

(Is http://ics.nxp.com/support/documents/microcontrollers/zip/lpc17xx.cmsis.driver.library.zip one of the examples you're talking about?)

Thanks,

Michael

03 Mar 2012

The reason that the mbed lib doesnt use the interrupt is probably just to keep it simple. Note that you cant create 'generic' I2C slave code. It may have multiple internal addresses or registers, it may or may not support read and write etc. So first you need to define what the detailed protocol is for the slave and then implement that behaviour. A simple model would be to emulate a serial RAM of 32 bytes that you can read and write. You allow the master to select the starting address and you implement address autoincrements etc. The slave is implemented using interrupts and you need some sort of flag to indicate to your 'main' loop that something has changed in the slave memory.

You can find examples on: http://ics.nxp.com/support/lpcxpresso/#Examples

Download the: MCB1700 Sample Code Bundle for LPC1769 Peripherals using LPCXpresso V2.00 (Jan 10, 2011) and find the I2C subdirectory. That includes slave code for I2C1 and I2C2 ports (the only available I2C ports on mbed), the interrupt handler etc. It will need work to integrate that code in the mbed environment and avoid conflicts. Check the LPC1768 user manual and also study some other examples in the cookbook that deal with interrupts.

03 Mar 2012

Hello Wim,

thanks for the tips - I'll study them...

As I only have to 'emulate' a simple SAA1064 it couldn't be too hard to implement this, if I figure out how to use the samples with the mbed.

As an alternative I'm thinking about using an additional portpin, connected to SCL to generate an interrupt and use the mbed-routines - at least as long I can't get the other solution to work...

Michael