Your new topic does not fit any of the above??? Check first. Then post here. Thanks.

Moderator: igrr

User avatar
By Vicne
#50477 Hi,

I finally had some free time and could test the SPI slave lib posted above.
The good news is that generally speaking, it works ;-). Master talks to slave and slave talks to master.

Now what's strange is that the slave messages returned to the master (answers) are corrupt.
Here's the result of the samples (SPISlave_SafeMaster on an ESP and SPISlave_Test on another ESP):
2016-07-09_2204_001.png

Basically, the only change I made is that the slave now dumps not only the questions but also its answers on the serial port.
As you can see, the answer dumped by the master is corrupt, but still, it has the right length and the characters are always the same except one.
I first thought of a MSB-LSB issue, but then I noticed that the only character that changes skips one value: d-f-h-j-l-n-p, so it looks like answers are shifted one bit to the left.
I changed the master code to shift answers back to the right and then answers were OK (well, I'm losing the highest bit but it doesn't matter in 7-bit ascii):
2016-07-09_2216.png

Finally, I took a look at the signals on my scope and (although its SPI decoding is flaky), playing with the "sampling clock edge" setting, I noticed I could fix some bytes:
DS1Z_QuickPrint34_annotated.png

DS1Z_QuickPrint35_annotated.png

So obviously, there is a timing issue, like if the MISO signal changes on the clock edge when the master samples the signal.
I will look again at the SPI registers and see if I find something related to those timings.

Kind regards,

Vicne
You do not have the required permissions to view the files attached to this post.
User avatar
By Vicne
#50482 Hi, Me-no-dev,

I've taken a look at the library code. I see you have fixed several settings. It's a pity indeed that some #define's refer to bits by position (like SPIS1LSTA), while other already address bits by masks (like SPIS1RSTA). I admit I didn't spot these mistakes when reading your first code... Nice catch.

Regarding the delay issue (see post above), I'm thinking of testing the different values of SPIUSME & SPIUSSE in SPI1U. What do you think ?

Or maybe tune delays in the SPI1C2 register. Do you know the meaning of the delays in that register ?

Kind regards,

Vicne
User avatar
By Vicne
#50491 More information about the timing issue:
Zooming on the 0x03=0b00000011 of the master, we have this :
DS1Z_QuickPrint48.png

Which looks perfect, the bits are aligned with the LO-HI clock cycle and the rising edge happens right at the middle of the bit.

However, when the "Alive..." message is returned by the slave, the 'A'=0x41=0b01000001 looks like this:
DS1Z_QuickPrint49.png

While this byte is decoded correctly by the scope using the "rising edge" CLK setting, one can see that the bits are not aligned at all, so if we sometimes get it right, it's just pure luck:
DS1Z_QuickPrint50.png

I think bits should be emitted half a cycle later to make sure they are sampled correctly.
I'm digging further to see if I can improve that.
Kind regards,

Vicne
You do not have the required permissions to view the files attached to this post.
User avatar
By Vicne
#50500 Fixed :-)

I added the following line to the init code:
Code: Select allSPI1C2 |= 1 << SPIC2MISODM_S;

This field is known as SPI_MOSI_DELAY_MODE in spi_register.h from the Espressif SDK and is documented as
//mode 0 : posedge; data set at positive edge of clk
//mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk
//mode 2 : Do not use this mode.

I can now get a clean MISO sampling on the rising edge, like on the MOSI line. Here's the 'A':
DS1Z_QuickPrint51.png

And the serial dump is OK:
2016-07-10_1703.png

So this is using two ESP8266, one running your SPISalve_SafeMaster.ino and the other running the version of SPISlave_Test.ino below (slightly edited to add the above change as well as a dump of the answers) :
Code: Select all/*
    SPI Slave Demo Sketch
    Connect the SPI Master device to the following pins on the esp8266:

    GPIO    NodeMCU   Name  |   Uno
  ===================================
     15       D8       SS   |   D10
     13       D7      MOSI  |   D11
     12       D6      MISO  |   D12
     14       D5      SCK   |   D13

    Note: If the ESP is booting at a moment when the SPI Master has the Select line HIGH (deselected)
    the ESP8266 WILL FAIL to boot!
    See SPISlave_SafeMaster example for possible workaround

*/

#include "SPISlave.h"

void setup()
{
    Serial.begin(115200);
    Serial.setDebugOutput(true);
    Serial.println();

    // data has been received from the master. Beware that len is always 32
    // and the buffer is autofilled with zeroes if data is less than 32 bytes long
    // It's up to the user to implement protocol for handling data length
    SPISlave.onData([](uint8_t * data, size_t len) {
        String message = String((char *)data);
        char answer[33];
        if(message.equals("Hello Slave!")) {
            strcpy(answer, "Hello Master!");
        } else if(message.equals("Are you alive?")) {
            sprintf(answer, "Alive for %u seconds!", millis() / 1000);
        } else {
            strcpy(answer, "Say what?");
        }
        SPISlave.setData(answer);
        Serial.printf("Question: %s\Answer: %s\n", (char *)data, answer);
    });

    // The master has read out outgoing data buffer
    // that buffer can be set with SPISlave.setData
    SPISlave.onDataSent([]() {
        Serial.println("Answer Sent");
    });

    // status has been received from the master.
    // The status register is a special register that bot the slave and the master can write to and read from.
    // Can be used to exchange small data or status information
    SPISlave.onStatus([](uint32_t data) {
        Serial.printf("Status: %u\n", data);
        SPISlave.setStatus(millis()); //set next status
    });

    // The master has read the status register
    SPISlave.onStatusSent([]() {
        Serial.println("Status Sent");
    });

    // Setup SPI Slave registers and pins
    SPISlave.begin();

    // Additional setting to have MISO change on falling edge
    SPI1C2 |= 1 << SPIC2MISODM_S;   

    // Set the status register (if the master reads it, it will read this value)
    SPISlave.setStatus(millis());

    // Sets the data registers. Limited to 32 bytes at a time.
    // SPISlave.setData(uint8_t * data, size_t len); is also available with the same limitation
    SPISlave.setData("Ask me a question!");
}

void loop() {}


Thanks again for the hard work. You saved my project :-).


Now that the sample works, I'm going to try and adapt the parameters to the protocol I have to spy, which has other conventions (SPIMODE etc). I'll go on reporting here and might have other questions ;-).

Kind regards,

Vicne
You do not have the required permissions to view the files attached to this post.