Particle as SPI Slave Incorrect Reads

I’m having some issues using my Particle as a SPI slave with a PIC device functioning as a SPI Master. The PIC device sends 4 bytes upon initial turn on. When the Particle is freshly reset, it reads these bytes correctly. However turning the PIC device on and off again after the Particle has successfully read the bytes once, yields a different read. Looking at the signals with a logic analyzer, everything looks good. Does anyone have any suggestions for troubleshooting steps I can take?

Code below:

#include "application.h"

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

static uint8_t rx_buffer[4];
static uint8_t tx_buffer[4];
static volatile uint32_t select_state = 0x00;
static volatile uint32_t transfer_state = 0x00;
int rx_val;

void onTransferFinished() {
//    digitalWriteFast(A0, HIGH);   // we are in slave mode
    transfer_state = 1;
}

void onSelect(uint8_t state) {
    if (state)
        select_state = state;
}

/* executes once at startup */
void setup() {
    Serial.begin(9600);
    SPI.onSelect(onSelect);
    SPI.begin(SPI_MODE_SLAVE, A2);
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE0);
    memset(rx_buffer, 0, sizeof(rx_buffer));
    for (int i = 0; i < sizeof(tx_buffer); i++)
        tx_buffer[i] = (uint8_t)i;
}

/* executes continuously after setup() runs */
void loop() {
    
    WiFi.on();
    delay(1000);
       
    WiFi.connect();

   Particle.connect();
   
    while (1) {
        while(select_state == 0);
        select_state = 0;

        transfer_state = 0;
        SPI.transfer(tx_buffer, rx_buffer, sizeof(rx_buffer), onTransferFinished);
        while(transfer_state == 0);
        if (SPI.available() > 0) {
            Serial.printf("Received %d (0x%02x) bytes", SPI.available(), SPI.available());
            Serial.println();
            for (int i = 0; i < SPI.available(); i++) {
                Serial.printf("%02x ", rx_buffer[i]);
                rx_val = rx_buffer[5];
            }
            Serial.println();

            // if (rx_buffer[transferLength - 1] != 0x00) {
            //     Serial.println("Error");
            //     while(true);
            // }
            Particle.variable("SPI RX", &rx_val, INT);
            Particle.publish("SPI RX", (const char *)rx_val, 200, PUBLIC);
            Particle.process();
            for (int i = 0; i < sizeof(tx_buffer); i++)
            tx_buffer[i] = rx_buffer[i];
            memset(rx_buffer, 0, sizeof(rx_buffer));
            
            rx_val = 0;
            delay(750);
        }
    }
}

How are you handling the CS line on the PIC side?
Are you keeping it LOW all the time or do you let it go HIGH again after you’re done transfering?

If you keep the slave enabled, the “random signals” on the SPI lines caused by the reset might get interpreted too.

1 Like