Yes, I called that a "misfire". That is a bug. For safety you have to filter those out anyway.
You are very polite.
Please don't try to be smart and think ahead of a problem that does not exist. Always follow the KISS principle.
You do this:
typedef struct Command{
uint8_t cmd : 8;
uint32_t payload : 24;
}Command;
Every Arduino board puts the struct elements at byte order to be compatible with all the other Arduino boards. Please don't use bit definitions, use normal uint8_t (or byte) or an array of bytes or other variables.
By the way, 24 bits is only 3 bytes. Your struct uses 5 bytes and only 4 are used. That is what happens if you forget about the KISS principle ![]()
There is a timing thing.
When a fast Master does a I2C write and a I2C read session, then a slower Slave might not be ready. Especially the slower boards such as a Arduino Uno needs "time to breathe".
Don't be surprised if things work better with a delay:
Wire.beginTransmission(M0_I2C_SLAVE_ADDRESS);
Wire.write((byte *)&commandStruct, COMMAND_LEN);
int error = Wire.endTransmission ();
delay(1); // give Slave "time to breathe"
if (Wire.requestFrom(M0_I2C_SLAVE_ADDRESS, responseSize) == responseSize) // all okay ?
{
Wire.readBytes( buffer, responseSize); // <-- this is weird, but allowed
}
Here is a puzzle for you:
Look at the loop() of the Slave. Suppose that some time ago the printRequest was set to 1 and the loop() detects that. Then suddenly new data arrives via the I2C bus while the loop() is still busy between the if(printrequest){ and the printRequest=0.
Then you have half the old data and half the new data.
Solution: make some kind of handshake; or make of copy of the struct and clear the flag with the interrupts turned off; or make an error counter in the onReceive handler.