Hello, can anyone verify that, as is in firmware release 1.1.0, the SPI::onSelect() interrupt callback is being triggered? I have tried the sample SPI slave code, with 2 argon’s. The first was acting as a slave
and another one as the master, but it seems that the SPI::onSelect is never triggered, despite the fact that I “change” the ss pin’s state. Used a photon and a peripheral device (3d accelerometer) for troubleshooting, that both work as expected. I also tried various pins(+ default ss pin).
Yup, I can confirm that.
I’ve been testing with this code between two Photons where it worked and between a Photon master and Argon slave were the onSelect
function was never executed
//#define pinMASTER A2 // SS pin on the master
#define pinSLAVE D0 // SS pin on the slave (also tested with A2)
#if defined(pinMASTER)
char tx[64];
char rx[64];
void setup() {
Serial.begin();
SPI.begin(pinMASTER);
digitalWrite(pinMASTER, HIGH);
}
void loop() {
if (!digitalRead(BTN)) { // when SETUP/MODE button is pressed
delay(50); // debounce
while(!digitalRead(BTN)); // wait for button release
digitalWrite(pinMASTER, LOW); // select slave
Time.format().toCharArray(tx, sizeof(tx)); // copy current time to transfer buffer
Serial.printlnf("TX: %s", tx);
SPI.transfer(tx, rx, sizeof(tx), NULL); // transfer data to slave
Serial.printlnf("RX: %s", rx);
delay(50); // debounce
digitalWrite(pinMASTER, HIGH); // deselect slave
}
}
#elif defined(pinSLAVE)
SYSTEM_MODE(MANUAL);
// SPI slave example
static uint8_t rx_buffer[64];
static uint8_t tx_buffer[64];
static uint32_t transfer_state = 0x00;
volatile uint32_t select_state = 0x00;
void onTransferFinished() {
transfer_state = 1;
}
void onSelect(uint8_t state) {
if (state) {
select_state = state;
}
digitalWrite(D7, !digitalRead(D7));
}
/* executes once at startup */
void setup() {
Serial.begin();
pinMode(D7, OUTPUT);
for (int i = 0; i < sizeof(tx_buffer); i++)
tx_buffer[i] = (uint8_t)i;
SPI.onSelect(onSelect);
SPI.begin(SPI_MODE_SLAVE, pinSLAVE);
//pinMode(pinSLAVE, INPUT); // doesn't help either
}
/* executes continuously after setup() runs */
void loop() {
while(select_state == 0);
Serial.println("selected");
select_state = 0;
transfer_state = 0;
SPI.transfer(tx_buffer, rx_buffer, sizeof(rx_buffer), NULL); //onTransferFinished);
//while(transfer_state == 0);
if (SPI.available() > 0) {
Serial.printf("Received %d bytes", SPI.available());
Serial.println();
Serial.write(rx_buffer, strlen((char*)rx_buffer));
Serial.println();
}
}
#else
#error "no role selected"
#endif
Update:
@gerasimos, I have inquired about the matter and got told that on Gen3 devices Slave Mode is only supported on SPI1
(which also maxes out at 8MHz, while SPI
can get up to 32MHz but can’t offer Slave Mode).
1 Like
Thanks for that info, are there any future plans to utilize SPI as well?
As it seems that is a hardware limitation of the nRF52840 controller and hence won’t be an option ever.
Update:
This code now works (Master SPI with CS on A2 & Slave SPI1 with CS on D5)
//#define pinMASTER A2 // SS pin on the master
#define pinSLAVE D5 // SS pin on the slave
#if defined(pinMASTER)
SPIClass &spi = SPI;
char tx[64];
char rx[64];
void setup() {
Serial.begin();
spi.setClockSpeed(8, MHZ);
spi.begin(pinMASTER);
digitalWrite(pinMASTER, HIGH);
}
void loop() {
if (!digitalRead(BTN)) { // when SETUP/MODE button is pressed
delay(50); // debounce
while(!digitalRead(BTN)); // wait for button release
digitalWrite(pinMASTER, LOW); // select slave
Time.format().toCharArray(tx, sizeof(tx)); // copy current time to transfer buffer
Serial.printlnf("TX: %s", tx);
spi.transfer(tx, rx, sizeof(tx), NULL); // transfer data to slave
Serial.printlnf("RX: %s", rx);
delay(50); // debounce
digitalWrite(pinMASTER, HIGH); // deselect slave
}
}
#elif defined(pinSLAVE)
SYSTEM_MODE(MANUAL);
// SPI slave example
SPIClass &spi = SPI1;
static uint8_t rx_buffer[64];
static uint8_t tx_buffer[64];
static uint32_t transfer_state = 0x00;
volatile uint32_t select_state = 0x00;
void onTransferFinished() {
transfer_state = 1;
}
void onSelect(uint8_t state) {
if (state) {
select_state = state;
}
digitalWrite(D7, !digitalRead(D7));
}
/* executes once at startup */
void setup() {
Serial.begin();
pinMode(D7, OUTPUT);
for (int i = 0; i < sizeof(tx_buffer); i++)
tx_buffer[i] = (uint8_t)i;
spi.onSelect(onSelect);
spi.setClockSpeed(8, MHZ);
spi.begin(SPI_MODE_SLAVE, pinSLAVE);
pinMode(pinSLAVE, INPUT);
}
/* executes continuously after setup() runs */
void loop() {
while(select_state == 0);
Serial.println("selected");
select_state = 0;
transfer_state = 0;
spi.transfer(tx_buffer, rx_buffer, sizeof(rx_buffer), NULL); //onTransferFinished);
//while(transfer_state == 0);
if (spi.available() > 0) {
Serial.printf("Received %d bytes", spi.available());
Serial.println();
Serial.write(rx_buffer, strlen((char*)rx_buffer));
Serial.println();
}
}
#else
#error "no role selected"
#endif
2 Likes