Bug Report: SPI Slave Mode: MSBFIRST non-functional

Hello,

Not sure where to post bugs - but it would appear that SPI.setBitOrder(MSBFIRST);
does not work.
Has Particle thoroughly tested this?

If so; please post a COMPLETE SPI SLAVE configuration that has passed all combinations of MODES and bit orders - so we can compare apples to apples.

I have pretty much verified with an analyzer that MSBFIRST doesn’t work from the Photon. There is still a small chance this could be due to a set-up variable on my end due to rather incomplete examples for SPI provided by Photon.

So, if you guys have a QA dept. that has thoroughly tested this - please attach the code to a reply and I will test.
I will post my code here so everyone can see it.

Thanks In Advance,
John W.

// This #include statement was automatically added by the Particle IDE.
// #include "lib3.h"

// This #include statement was automatically added by the Particle IDE.
// #include "lib2.h"

// This #include statement was automatically added by the Particle IDE.
// #include "lib1.h"

#include "application.h"

#define SLAVE    //  (1)  // defines Photon to be in slave mode

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

// #define WIFI_SSID (123456)
// #define WIFI_PWD    (XXXXYYYYZZZ)


/* Define either MASTER or SLAVE operating mode */
//#define MASTER
// #define SLAVE

// static uint8_t rx_buffer[64];
// static uint8_t tx_buffer[64];
static uint8_t rx_buffer[10];
static uint8_t tx_buffer[10];
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;
}

/* *********************************************************************************************************** */
#ifdef SLAVE

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(LSBFIRST);
    SPI.setDataMode(SPI_MODE3);
    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);
 
    while(!(WiFi.hasCredentials()))
    {
        Serial1.println("setting WiFi credentials");
        WiFi.setCredentials("123456", "XXXXYYYYZZZZ");
    } 

         WiFi.connect();

        Particle.connect();
//         Spark.process();


    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);
        }
    }
}
/* *********************************************************************************************************** */
#else
/* *********************************************************************************************************** */
static int random_range(int minVal, int maxVal)
{
    return rand() % (maxVal-minVal+1) + minVal;
}

/* executes once at startup */
void setup() {
    Serial.begin(9600);
    SPI.begin(SPI_MODE_MASTER, A2);
    memset(rx_buffer, 0, sizeof(rx_buffer));
    memset(tx_buffer, 0, sizeof(tx_buffer));

    uint32_t seed = millis(); 
    srand(seed);
}

/* executes continuously after setup() runs */
void loop() {
    while (1) {
        int transferLength = random_range(1, sizeof(tx_buffer));
        for (int i = 0; i < transferLength; i++)
            tx_buffer[i] = (uint8_t)(transferLength - i - 1);

        memset(rx_buffer, 0, sizeof(rx_buffer));

        digitalWrite(A2, LOW);
        delay(1);

        transfer_state = 0;
        SPI.transfer(tx_buffer, rx_buffer, transferLength, onTransferFinished);
        while(transfer_state == 0);

        digitalWrite(A2, HIGH);

        Serial.printf("Sent %d (0x%02x) bytes, got back:", transferLength, transferLength);
        Serial.println();
        for (int i = 0; i < transferLength; i++) {
            Serial.printf("%02x ", rx_buffer[i]);
        }
        Serial.println();

        if (rx_buffer[transferLength - 1] != (uint8_t)(transferLength - 1)) {
            Serial.println("Error");
            delay(1000);
        }

        delay(100);
    }
}
/* *********************************************************************************************************** */
#endif

The best place to file a bug report would be here by opening a new issue (or check if there is one already)

Could you try setting the configuration before SPI.begin()

    SPI.setBitOrder(LSBFIRST);
    SPI.setDataMode(SPI_MODE3);
    SPI.onSelect(onSelect);
    SPI.begin(SPI_MODE_SLAVE, A2);

Also, the SPI Master code does not explicitly set:

    SPI.setBitOrder(LSBFIRST);
    SPI.setDataMode(SPI_MODE3);

:smiley:

Appears to be something similar here:

Thanks guys - I will see what I can do based on your replies and this bug report and report back here.

I suppose the SPI operation does have a default mode; correct?

Nope, this was a different issue and the root cause for this might have had to do with the boot-up behaviour of some D-pins with default pull-resistors.

Please report back, once you have tried the tips from above.

1 Like