I2C Slave mode support?

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

Moderators: barthess, RoccoMarco, utzig, lbednarz, tfAteba

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

I2C Slave mode support?

Postby genosensor » Fri Nov 08, 2013 1:24 am

Hi,

What is the current status of slave mode support for the I2C bus?

I see some attempts to implement it, but nothing in the mainline release.
Is it slated for 3.0?

I'd rather stick with 2.6.x for my current project involving up to 60 STM32Lxx MPUs in a peer-to-peer I2C network.

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

Re: I2C Slave mode support?

Postby Giovanni » Fri Nov 08, 2013 10:28 am

Hi,

Currently there are no plans, should it happen it would be a separate driver, not a change in the current one. Of course an I2C slave can be added as a custom driver, there is nothing in the HAL architecture preventing this.

Giovanni

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

Re: I2C Slave mode support?

Postby genosensor » Fri Nov 08, 2013 5:40 pm

I2C is a multimaster bus,in which nodes may switch between master and slave modes frequently.
To facilitate that, the same functional units and registers on the chip typically contain bits to support both master and slave modes. Honestly, for the STM32 at least, I cannot see how an independent driver could be written to add slave support without modifying the existing low-level, master mode driver code.

Could you explain why you would prefer that I2C slave support be implemented by a separate driver?

Ideally, it would seem to make more sense to have a single high-level driver that has compile-time options to support either master, slave or both modes.

P.S. Sorry about the previous cross posting. I hadn't yet discovered the existing STM32 specific thread when I started this one.

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

Re: I2C Slave mode support?

Postby Giovanni » Fri Nov 08, 2013 6:16 pm

Hi,

The problems I see are:
1) Portability of such a multi master/slave driver.
2) Rework of all implementations.
3) Testing.
4) Support.

1) Cannot be ensured unless you define a very abstract API that can be adapted at as many architectures as possible (is this even possible?), this is not about STM32 alone.
2) Who is going to do that on other platforms?
3) How are we going test such a complex driver in all possible scenarios? the current simple driver proved to be troublesome enough.
4) Contributors usually quickly disappear but the code remains.

A separated driver, could be supported as a contribution, would not impact the existing code and would live or die depending on the effort stakeholders put in it.

In ChibiOS 3.0 there will be a restricted set of supported drivers and everything else will go into an "extended HAL" supported (or unsupported) by the community. I wish a mechanism that would allow everybody to submit code without too much screening and then let natural selection decide.

Anyway, let's see your proposal first, I am interested.

Giovanni

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

Re: I2C Slave mode support?

Postby genosensor » Wed Nov 13, 2013 11:07 pm

Attached is my first cut at an abstract API for support of I2C slave mode

The I2C slave driver is conceptually independent of the I2C (master) driver at at a high level,
however, I strongly suspect that each low-level I2C driver will have to be reworked if it is to support slave mode transactions.

Let me know what you think.
Is it abstract enough?

I've tried to avoid the use of configuration structures to allow drivers more flexibility in how they represent their internals.
But, I could be convinced otherwise.
I might need Interrupt variants of some of the functions.
All those I variants really do and to clutter, unfortunately.

If we can converge on an API, I'll quickly implement and test it for the STM32Lxx, as an example.
Other platforms could return an "unsupported" error during compile if HAL_USE_I2C_SLAVE is defined
until someone supplies an implementation for it.
Attachments
i2cslave.zip
First cut at an abstract I2C slave API
(2.42 KiB) Downloaded 185 times

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

Re: I2C Slave mode support?

Postby Giovanni » Thu Nov 14, 2013 9:23 am

Hi,

genosensor wrote:I've tried to avoid the use of configuration structures to allow drivers more flexibility in how they represent their internals.


This is the first problem, drivers have a pattern to follow, dynamic reconfiguration is discouraged except in xxxStart().

Optional callbacks make the API less than an API, the code would no more be portable unless the target supports the feature. In general there are a lot of functions, the interface does not look minimalist.
Are you sure that the protocol you imagined can be implemented on all/most devices, it pretty much follows the STM32 way to do things.

I would consider making the driver configuration-driven and handle transfers using "transaction descriptors" prepared in advance and containing all the required pointers to buffers, transfer sizes, limits and a "done" callback. Then a single function i2cSlaveStartTransaction(&descriptor). This would allow the low level driver optimize the transaction handling without making any assumption on the internal process.

Giovanni

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

Re: I2C Slave mode support?

Postby genosensor » Fri Nov 15, 2013 9:58 am

The use of a config struct certainly does clean up the API!

Notes:
i2cSlaveStartTransaction() makes no sense to me.
I2C slaves, by definition, do not initiate any bus transactions.
Instead, I just have defined an i2cSlaveStart()

There are separate instances of the same configuration structure for receiving and replying.

What you call "dynamic reconfiguration" seems to me to be a very logical way to handle message parsing.
I've included a toy example of the technique to demonstrate this.
It seems pretty clean to me. The active I2CSlaveConfig structs determine how incoming messages and queries are processed.

Would it help to rename I2CSlaveConfig to something like I2CslaveState or I2CslaveTransaction?

I have little experience with the STM32. All my previous I2C work is with the MSP430.
If you think this workable for the STM32, I can vouch for the MSP430.
Others are invited to weigh in concerning their favorite microcontrollers.

I think we need an "address matched" callback in addition to a "done" callback.
Consider the case of a rapidly changing sensor being read infrequently by an I2C master node.
The most efficient approach would be to compose the read response message just after the read address match is recognized. Otherwise, one is forced to continuously poll the sensor and update a response buffer in anticipation of relatively infrequent read requests. The i2cslave.c example demos this by returning chTimeNow() in response to a zero length write.

Because composing a response may not always be feasible in interrupt context, there needs to be some way to leave the ISR without completing the response -- likely stretching the I2C clock as a result. I've allowed this without adding any functions to the API.
Attachments
i2cslave.zip
Second cut at an abstract I2C slave API
(3.78 KiB) Downloaded 112 times

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

Re: I2C Slave mode support?

Postby genosensor » Fri Nov 15, 2013 7:25 pm

I streamlined things a bit more on this third revision...

Callbacks take just one parameter now: the I2CDriver *
They return void.

The relevant I2CSlaveConfig can be retrieved from the I2CDriver *
The I2C destination address is written through an additional pointer in I2CSlaveConfig.
When desired, changing the active I2CSlaveConfig is always done via calls to i2cSlaveReceiveI()
or i2cSlaveReplyI().

I also worked a bit on the comments to emphasize the fact that changing config dynamically is an "advanced usage". It is not required for very basic I2C message handling.

I'll stop fiddling now and wait for feedback.
Attachments
i2cslave.zip
3rd version of I2C Slave API proposal
(3.81 KiB) Downloaded 126 times

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

Re: I2C Slave mode support?

Postby Giovanni » Mon Nov 18, 2013 10:43 am

I imagine you can test it, the API is simple but the usage is still complex looking at your test application.

I wonder if it would be possible to make all functions synchronous and do not rely on callbacks. Something like:
i2cSlaveWaitAddressMatch(i2cp, addrlist);
i2cSlaveGetMessage(i2cp, bufp, np);
i2cSlaveAnswerMessage(i2cp, bufp, n);

Each function would just get the parameters it needs. The driver state machine would define what function you are supposed to call in any moment.

Giovanni

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

Re: I2C Slave mode support?

Postby genosensor » Tue Nov 19, 2013 7:16 am

I was planning to implement along the lines of what ChiBiOS already has in place for the ADC and other drivers.
As such, the core I2Cslave driver would rely on asynchronous callbacks.
These could be used to handle events in interrupt context or to wake threads.

Keep in mind that I2C Slave mode requires event driven programming, as
slaves do not determine the sequence in which messages will arrive.

Looking at your suggestion, consider:

What if the master requests an answer (reply) before sending a message?
What if another master requests some response after the slave returns from i2cSlaveWaitAddressMatch()?

Here's an API, very similar to your suggestion, that would handle multimaster access.

Address matching set up would be unchanged. We generally don't want to disable address matching and reenable it for every message processed, as this would cause the slave to NAK messages when they arrive in rapid succession.

After setting up address matching, an I2C messaging thread would loop, servicing events with code like this:

Code: Select all

i2caddr_t  accessAdr;

switch i2cSlaveAwaitAddressMatch(i2cp, &accessAdr) {
  case i2cSlaveReceiving:
    i2cSlaveAccept(i2cp, inputBufp, sizeof(inputBuf));
    //parse and process inputBuf
    break;
  case i2cSlaveQueried:
    //compose outputBuf
    i2cSlaveAnswer(i2cp, outputBufp, sizeof(outputBuf));
    break;
}

i2cSlaveAwaitAddressMatch() blocks until the slave is accessed.
It records the address accessed -- typically its address or 0 for a general call -- then
returns in indication of whether the master is trying to send a message (i2cSlaveReceiving) or is
waiting on a response to a query (i2cSlaveQueried). The I2C bus is locked in either case,
until i2cSlaveAccept() or i2cSlaveAnswer() is called. Both Accept() and Answer() would
return the number of bytes transferred.


Return to “General Support”

Who is online

Users browsing this forum: No registered users and 4 guests