First, I read Raspberry as an I2C SLAVE and followed everything in there. Great thread. However, this thread does not address anything about sending data back.
This is the scenario: rPI4 as master, rPI3 as a slave, and other I2C slaves.
Master sees all devices. Master communicates with other non-rPI I2C slaves. rPI-slave can receive data from the rPI master. rPI-slave seems to send offset data to the master.
The idea is to be able to query the rPI slave for some values (temperature and load for example), using I2C. So I declared 0x01 as temperature register and 0x02 as load register. Anything else generates a "bad call" response. All rPI-slave responses are words (16 bits).
When I print the data as I am sending it, and I look at the I2C logic analyzer (external hardware Saleae), the data received at the master is what I see in the logic analyzer, but does not match what the code is sending. The code is sending: 0x4010, 0x9001, 0xf000, however, the signal analyzer (and master) sees: 0xf000, 0x4010, 0x9001. Some times, the stream is shifted by 1 byte only.
The data reception (rPI master to rPI slave) always works and is similar to the code in the mentioned thread, here is my sending code:
cout << "Sending result: " << std::hex << res << endl;
memset(&xfer,0,sizeof(xfer));
xfer.control = controlBits;
int b1 = (res & 0x00ff);
int b2 = (res & 0xff00) >> 8;
xfer.txBuf[0] = b1;
xfer.txBuf[1] = b2;
xfer.txCnt = 2 ;
cout << "Sending: 0x" << std::hex << b1 << " 0x" << b2 << endl << endl;
status = bscXfer(&xfer);
(All the couts are for debugging. res is the word to be sent. Controlbits is the value calculated in the code link above)
It almost seems like something is getting stuck in the I2C FIFO and since bscXfer only adds to the end of the I2C FIFO, I think only data is getting sent. I have not been able to find a way to empty the FIFO.
I read the BCM relevant pages and cannot seem to find an answer.
I have done an rpi-update on both, using the latest buster, all updates.
First update: I have tried bitbanging the I2C using the pigpio library. I get the exact same result. The analyzer and the master see the same results. However, the slave is sending different data. It's always the same issue: it appears that the slave buffer is not managed properly and therefore there seems to be an offset of 1 or 2 bytes in the return values as a whole (not each value). For example, if the return values should be 0x00 01 0x00 0x02 0xff 0xff, the master can receive something like 0xff 0xff 0x00 0x01 0x00 0x02. The shifting is not always the same, but there is always shifting. At this point, I am almost suspecting a bug in the pigpio code. It seems the FIFO is not managed well. This is only a suspicion.
Update#2 It seems that the hardware has an issue. I brought the actual source of pigpio bscXfer inside my code and made 2 functions: send and receive. This simplifies my code greatly. Still, the problem occurs.
Solution: I finally opted to add a NOOP command that reads the 0x00 register on the slave but returns no data. From the master's side, I can issue the command and read a 16-bit word 3 times. This empties the buffer on the slave and then I can get some good readings reliably.
I would still like to hear if anyone has had any success using the PI as a true I2C slave device: mimicking registers, returning data, and receiving data.