I'm using an STM32L432 to implement an I2C slave.
I've downloaded the latest version for ChibiOS (v17.6.3), and merge the latest
I2Cslave source (from page 7), then renamed the files are recommended (hal_...).
It builds Ok, and I've neen able to make the STM32 to start communicating as a
slave with a remote I2C master.
However, after a 1-byte write (Master->Slave) and a 2-byte read (Slave->Master)
sequence, the I2Cslave does not seem to receive any other data.
I've checked with a Saleae logic analyser: a new 3-byte I2C frame is sent as
expected from the master, and the STM32 slave acknowleges all the 3 bytes, but
that's it, the I2CSlaveMsg.processMsg is no longer called.
I've enabled the debug traces in hal_i2c_lld.c to see if I could get some
useful info (see below).
The I2C slave I'm trying to emulate follows a common communication scheme over
I2C. The slave supports many registers.
To write to one (or more) registers, the master should first write the register
address (1 byte), followed with the actual data (each register is 2-byte long).
2-byte data packets may be repeated to write to subsequent registers in the
slave, until a STOP condition is generated.
To read from one (or more) register(s), the master should first write the
register address (1 byte), then issue a repeated start condition and read the
register content (2 bytes). The read may be repeated to read subsequent
registers from the slave, until a STOP condition is generated.
Here is the captured sequence with the logic analyser:
Code: Select all
Time [s], Analyzer Name, Decoded Protocol Result
0.000004000000000,I2C,Setup Write to [0x6C] + ACK
0.000065300000000,I2C,0x02 + ACK
0.000790100000000,I2C,Setup Read to [0x6D] + ACK
0.000866000000000,I2C,0x80 + ACK
0.000912500000000,I2C,0x7F + NAK
0.001505400000000,I2C,Setup Write to [0x6C] + ACK
0.001566700000000,I2C,0x02 + ACK
0.001620700000000,I2C,0x28 + ACK
0.001672200000000,I2C,0x2D + ACK
Here is the qEvent queue:
Code: Select all
00: 82->02 01 01FF new receive buffer set
01: 80->02 01 0000 new reply set
02: 04->02 01 0000 Address match
03: 13->02 01 01FF address match - receive
04: 14->02 02 0000 start slave receive operation
05: 04->02 02 0000 Address match
06: 07->02 02 0000 Recovery from untidily finished previous transaction [repeated start cond?]
07: 12->02 02 01FF address match - send
08: 16->02 02 0000 start slave transmit operation
09: 02->02 04 0000 transfer complete received
10: CC->02 04 0000 clearing down after transmission - triggered by NAK received (usually valid)
11: 05->02 04 0000 STOP received
12: 04->02 01 0000 Address match
13: 13->02 01 01FF address match - receive
14: 14->02 02 0000 start slave receive operation
15: 05->02 02 0000 STOP received
16: 00->00 00 0000
On the I2Cslave client API,
1. rxMsg.processMsg() is called once (with 1 byte data payload), then
2. replyMsg.processMsg() is called once (when TX to master complete I believe)
but that's it, I would have expected to observe:
3. rxMsg.processMsg() to be called with a 3-byte data payload
Is there some explicit "reset" to perform after each request?
For now, I only configure the slave with:
Code: Select all
while the .processMsg only update the .body and .size members of their respective
BTW: is there any chance that whatever valid I2CSlave implementation eventually gets merged into the upstream repository?