OK, either I don’t know how to use the SPI interface, or the Artemis Arduino SPI implementation is broken. To replicate the issue, try out this minimal Arduino sketch:
#include <SPI.h>
void setup() {
SPI.begin();
Serial.begin(115200);
}
void loop() {
uint32_t cnt=0;
while (1) {
cnt++;
if ((cnt%1000)==0) Serial.println(cnt);
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
for (int i=0; i<4; i++) {
SPI.transfer(i);
}
SPI.endTransaction();
}
}
I don’t care about asserting SS: it is fine for the SPI data to just vanish into the ether. All I care about is that I should be able to begin a transaction, send 4 bytes, and end the transaction. Repeat forever.
Interestingly, this test fails very roughly 1 out of every 2000 times. Here is some output from a typical test run:
1000
2000
3000
4000
5000
6000
7000
got an error on _transfer: 4
8000
9000
10000
got an error on _transfer: 4
11000
got an error on _transfer: 4
12000
got an error on _transfer: 4
got an error on _transfer: 4
13000
14000
got an error on _transfer: 4
15000
got an error on _transfer: 4
got an error on _transfer: 4
16000
17000
18000
19000
got an error on _transfer: 4
20000
21000
These errors occur randomly. Here is another run:
got an error on _transfer: 4
1000
2000
got an error on _transfer: 4
3000
got an error on _transfer: 4
4000
got an error on _transfer: 4
5000
6000
7000
got an error on _transfer: 4
8000
got an error on _transfer: 4
9000
10000
got an error on _transfer: 4
11000
12000
13000
14000
15000
16000
17000
got an error on _transfer: 4
got an error on _transfer: 4
18000
From a user perspective, this is an undetectable error: the Artemis SPI driver may generate an error message to the Serial port, but the Arduino transfer() mechanisms do not support returning error information to the user’s application code, so the driver has no choice but to throw the error on the ground. Sadly, ignorance is not bliss in this case.
Finally, experimentation shows that if the inner loop transmits 4 or more bytes in the transaction, there will be errors. If I change that to be 3 bytes or less, then all the errors go away.