Race condition in Wire onReceive?

Here’s the code sample:

#include <Wire.h>

char receiveBuffer[32];

void setup() {
  Wire.begin(8);
  Wire.onReceive(receiveEvent);
}

void loop() {
  // do some stuff based on the receiveBuffer (e.g. calculations, pin state changes, etc.)
}

void receiveEvent(int howMany) {
  int i = 0;
  while (Wire.available()) {
    receiveBuffer[i++] = Wire.read();
  }
}

The question is how to avoid a chance of overwriting the data in receiveBuffer when it is being used in the main loop? I assume anytime another portion of data in receiveBuffer can show up and invalidate the previous portion.

Slaves don't send data until you tell them to.

void receiveEvent(int howMany) {
  int i = 0;
  while (Wire.available()) {
    receiveBuffer[i++] = Wire.read();
  }
}

Why do you suppose the function knows how many bytes are supposed to be received? Why don't you read that many?

This is an interrupt service routine. Other code will not be executed while this is running (getting data) so there is no worry about receiveBuffer being in an inconsistent state.

It would be good to make sure that there is actually room in the buffer before writing to it.

The buffer is preallocated to 32 (same as the buffer in the wire lib), and sure - I guess I should have maybe used the howMany variable and limit the amount of data stored to 32 - but this is not the question here :slight_smile:

The point is that while the main loop is processing data, the master decides to send some data (KeithRB - this code is for slave, not a master).

So while I am iterating over the buffer in the MAIN loop, I get an interrupt which totally changes the buffer. This can mess things up. How to avoid this?

EDIT: Actually I’ve checked the Wire/twi library and it seems there’s no need to check the howMany variable. The Wire.available()/read() is all that is needed to get the whole thing. So I guess the example is bug free. The only problem is that the code in the main loop might have its data swapped during processing.

EDIT2: I think one can enable some flag in the main code when the change of the buffer is forbidden and the callback would not update the buffer when the flag is HIGH. But in this case the data received would not be saved…