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.