I2C Slave mode support?

ChibiOS public support forum for all topics not covered by a specific support forum.

Moderators: RoccoMarco, lbednarz, utzig, tfAteba, barthess

steved
Posts: 823
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 135 times

Re: I2C Slave mode support?

Postby steved » Fri Aug 29, 2014 6:09 pm

colin wrote:But I do have concerns with the generality of the API and its flexibility. In particular, it looks like the current implementation requires that any message received by the slave from the master, or send as a reply to the master, must fit entirely in a RAM buffer.
Is there a way to allow for reads and writes of indefinite size? The slave should also be able to NAK any received byte as well, e.g. if an invalid command code is received.

My own usage of I2C over the years has rarely needed message lengths of more than 150 bytes or so, and in my particular applications any size constraint has been fairly straightforward to work around. I can see there might be applications where longer messages are needed, but mostly I would expect shorter messages (<256 bytes) to be more usual, and perhaps more in the spirit of I2C. Certainly the existing ChibiOS master I2C driver only supports message lengths up to 255 bytes, and I haven't come across any suggestion that it should be increased. (Possibly message length is platform-dependent? I found the size_t limit of 255 on 32F051).
Transfer time is potentially an issue with larger messages, certainly at 100kHz or 400kHz.
colin wrote:Is there a way to allow for reads and writes of indefinite size?

Initial reaction is that, as Giovanni says, handling large reads and writes would make things much more complicated. And the 'new' driver is already relatively complicated, IMO - partly down to the implementation on the 32F4.

colin wrote:The slave should also be able to NAK any received byte as well, e.g. if an invalid command code is received.
The ability to NAK any received byte mandates interrupt-driven transfers (rather than DMA) with all the overhead that entails. I have got this partially working (on the original 'master' driver) with a callback on every byte - in my case because I wanted to stop transfers on receipt of a specific character, but could also be used to fill a buffer with data, handle variable length messages, or process received messages on the fly. This might be a more practical way of handling large messages than chaining DMA buffers.

genosensor
Posts: 65
Joined: Thu Oct 03, 2013 1:06 am
Location: Santa Cruz, California
Has thanked: 1 time
Been thanked: 1 time

Re: I2C Slave mode support?

Postby genosensor » Fri Aug 29, 2014 6:29 pm

I'm glad to hear this interest in the slave mode I2C API.

The original work I did a decade ago for the TI MSP439169 used a sort of "flow through" model that did not require buffering messages. This was necessary to cope with the 2KBytes of RAM I had available and had a very nice side effect of eliminating most of the latency for an RS232<->I2C bus gateway that was part of that system.

The problems with such "flow through" processing of I2C packets are that:

1) It was not compatible with the master mode I2C or SPI drivers. I saw no examples (aside from async serial) of this sort of behavior in ChiBiOS.

2) It's hard to do in a generic fashion for packetized messaging protocols like I2C, SPI, etc.
(error handling is especially difficult)

3) It practically precludes any meaningful use of hardware DMA. Software must be interrupted on each byte to process it.
[I suppose one could imagine a scheme where the software processed fixed length "chunks" of messages...]

I'm still using the decade old RS232<->I2C bus gateway based on that bare-metal firmware in our current prototypes. It interoperates just fine with the ChiBiOS slave mode I2C and exhibits less latency than I will see when I reimplement the gateway in ChiBiOS (with this I2C slave mode driver) This is part of the reason I'm in no great hurry to do so :-)

Current micros (running ChiBiOS) won't likely be as RAM limited as the old MSP430s were.
However, latency is still an issue.

I'd like to brainstorm about a RS232-style flow through driver API for I2C.
However, I suspect it will be quite a challenge.

Messages >255 bytes are supported by I2C, but many implementations seem to have trouble with them.
Anyone concerned about interoperability would probably do best to avoid really long messages.
Having said that, I think that the ChiBiOS I2C slave driver should handle messages up to at least 32K bytes in length.
Where do you see the 256 message length limit in the API?

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: I2C Slave mode support?

Postby Giovanni » Fri Aug 29, 2014 6:32 pm

It would be possible to imagine some kind of circular receive buffer seen by the application as a stream (even a ChibiOS Queue could do), implementation would be a nightmare if we need to consider DMA.

Giovanni

genosensor
Posts: 65
Joined: Thu Oct 03, 2013 1:06 am
Location: Santa Cruz, California
Has thanked: 1 time
Been thanked: 1 time

Re: I2C Slave mode support?

Postby genosensor » Fri Aug 29, 2014 6:43 pm

That's exactly how I did it on the MSP430169!

The FIFO is a byte oriented ring buffer, like an RS232 fifo would be, but there is a scheme to delimit messages within it.
I doubt the existing ChiBiOS queue class could manage such a message delimiting scheme.
It involves having two tail pointers. One points at the last complete message, which begins with a length word.
The real tail pointer accumulates the bytes as they are received. When the message is complete, the length word, at the base of the current message, and the FIFO pointers are updated.

This scheme is very memory efficient.
DMA might even be possible with controllers that support ring buffers.

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: I2C Slave mode support?

Postby Giovanni » Fri Aug 29, 2014 7:50 pm

The problem with DMAs is that they do not notify for each transferred byte so it is not possible to wakeup the reading thread. If you program a notification for each byte then you fall in the interrupt based case.

I am thinking to leave it lenght based with a notification callback on buffer complete if a STOP does not follow, then introduce an i2cSlaveContinueReceiveI() in order to get the next data buffer. The bus would be in clock stretch mode during the handling of data.

This additional function could be optional and implemented only if the underlying HW supports such a transfer mode, STM32 should allow it.

The state machine would have one more state "PROCESSING" where i2cSlaveContinueReceiveI() can be called.

Giovanni

steved
Posts: 823
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 135 times

Re: I2C Slave mode support?

Postby steved » Fri Aug 29, 2014 9:24 pm

genosensor wrote:The problems with such "flow through" processing of I2C packets are that:

1) It was not compatible with the master mode I2C or SPI drivers. I saw no examples (aside from async serial) of this sort of behavior in ChiBiOS.

2) It's hard to do in a generic fashion for packetized messaging protocols like I2C, SPI, etc.
(error handling is especially difficult)

3) It practically precludes any meaningful use of hardware DMA. Software must be interrupted on each byte to process it.
[I suppose one could imagine a scheme where the software processed fixed length "chunks" of messages...]

As with serial, maybe we end up with two drivers - the existing DMA-driven one, an interrupt-driven byte-orientated one, and maybe even a third type to handle the big messages, if that doesn't fit easily anywhere else.

genosensor wrote:Where do you see the 256 message length limit in the API?

It's determined by the size_t type, which was defined as a uint8_t when I encountered it on the 32F051 (quite possibly on recent 2.x, or maybe on 3.x)
Haven't tracked down where its defined - think its in the compiler bits somewhere. Shouldn't be any problem in principle with redefining it - in fact, maybe there should be an I2C-specific type used, rather than a generic one.
Giovanni wrote:I am thinking to leave it lenght based with a notification callback on buffer complete if a STOP does not follow, then introduce an i2cSlaveContinueReceiveI() in order to get the next data buffer. The bus would be in clock stretch mode during the handling of data.

This additional function could be optional and implemented only if the underlying HW supports such a transfer mode, STM32 should allow it.

The bare bones of this are already in genosensor's driver - it already pauses in clock stretch mode if a transmit or receive buffer is available. Not sure if there would be a timing race if the message was an exact number of buffers long, between STOP notification and 'next buffer' notification.

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: I2C Slave mode support?

Postby Giovanni » Fri Aug 29, 2014 9:31 pm

The problem is that, if I remember well, the I2C sends a STOP as soon the DMA finishes the current transfer. May be this valid only in master mode, I need to re-read the RM, never went into details of I2C on the STM32.

Giovanni

genosensor
Posts: 65
Joined: Thu Oct 03, 2013 1:06 am
Location: Santa Cruz, California
Has thanked: 1 time
Been thanked: 1 time

Re: I2C Slave mode support?

Postby genosensor » Fri Aug 29, 2014 9:49 pm

I recall that the I2C sends STOP (or NAK) at the end of the current DMA transfer.

The current I2C slave mode support does stretch the I2C clock while the callback for responding to an I2C read executes.
There are some other cases where the clock is stretched as well.

Never can rule out the possibility of races, but, so far, I haven't seen any lockups here :-)

colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: I2C Slave mode support?

Postby colin » Fri Aug 29, 2014 10:28 pm

OK, I agree that the transaction size restrictions of this multi-master I2C driver are a reasonable compromise for simple use. If special capability is required then users will just have to write a low level I2C driver customized for that purpose.


It's determined by the size_t type, which was defined as a uint8_t when I encountered it on the 32F051 (quite possibly on recent 2.x, or maybe on 3.x)
Haven't tracked down where its defined - think its in the compiler bits somewhere. Shouldn't be any problem in principle with redefining it - in fact, maybe there should be an I2C-specific type used, rather than a generic one.

As for size_t, I am very surprised that the STM32F051 would have an 8-bit size_t. I am almost certain it is 32 bits wide on gcc.

genosensor
Posts: 65
Joined: Thu Oct 03, 2013 1:06 am
Location: Santa Cruz, California
Has thanked: 1 time
Been thanked: 1 time

Re: I2C Slave mode support?

Postby genosensor » Fri Oct 10, 2014 10:38 pm

I have just merged the slave/multimaster I2C support into the 2.6.x stable branch.

Its available at:

https://github.com/brentr/ChibiOS-RT.git

on the branch:

I2Cmultimaster

Note that Makefiles will have to be updated.
Also note that the makefile looks for a size utility that is not target specific.
I found

SZ = size

worked well.
It was looking for $(TRGT)size


Return to “General Support”

Who is online

Users browsing this forum: No registered users and 8 guests