Skip to content

Initial SPI Slave implementation and examples #2234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jul 6, 2016
Merged

Conversation

me-no-dev
Copy link
Collaborator

No description provided.

@codecov-io
Copy link

codecov-io commented Jul 5, 2016

Current coverage is 27.86%

Merging #2234 into master will not change coverage

@@             master      #2234   diff @@
==========================================
  Files            20         20          
  Lines          3653       3653          
  Methods         335        335          
  Messages          0          0          
  Branches        675        675          
==========================================
  Hits           1018       1018          
  Misses         2457       2457          
  Partials        178        178          

Powered by Codecov. Last updated by 2364ad4...93eb33f

@igrr igrr merged commit 4217e49 into esp8266:master Jul 6, 2016
@me-no-dev me-no-dev deleted the spi-slave branch July 6, 2016 22:01
@ThijsB1983
Copy link

ThijsB1983 commented Jul 7, 2016

Hi,

This library is exactly what i'm looking for. I want to use my ESP12 (mounted on a wemos D1 board) as a SPI slave.

I implemented both the master and slave examples (SPISlave_Master.ino and SPISlave_Test.ino) on two different wemos boards. The master is sending "Are you alive?" -> the slave responds with "Alive for x seconds!"

The master reads the data from the slave, but something strange is happening, I have to shift the byte 1 position to the right. Like this:

void readData(uint8_t * data)
{
    digitalWrite(_ss_pin, LOW);
    SPI.transfer(0x03);
    SPI.transfer(0x00);
    for(uint8_t i=0; i<32; i++) {
        data[i] = SPI.transfer(0);
        data[i] = data[i] >> 1;       // bit shift to right 
    }
    digitalWrite(_ss_pin, HIGH);
}

Is it me, or is this a little bug in the library?

@me-no-dev
Copy link
Collaborator Author

there isn't much that can be bug :) the lib reads from the hardware directly. I had it running for a couple of days here, no miss. What speeds are you using for SPI? Did you try the SafeMaster sketch?

@me-no-dev
Copy link
Collaborator Author

BTW I tested with Arduino UNO and ESP. Will try with two ESPs later (expecting a module in the mail today)

@ThijsB1983
Copy link

I did also try it with an Arduino UNO and and an ESP. That works well.... (master = arduino, slave = ESP).
The problem occurs when I use two ESP's, also with the SafeMaster sketch.
I'm new in the world of SPI, so I don't know what kind of speed I did use. In the SPIClass::begin() the frequency is:
setFrequency(1000000); ///< 1MHz

Is it possible that it has to do with the CPU frequency? Maybe I did setup one EPS with 80Mhz and one with 160Mhz. But I think this is not the problem.

@me-no-dev
Copy link
Collaborator Author

yes default speed is 1MHz, so that is way lower than the 8MHz that I usually run the sketches at...
CPU freq should not matter at all :)
Will see what the result will be today with two ESPs attached to each other

@ThijsB1983
Copy link

any news?

@ccerrillos
Copy link

I can confirm that you need to shift the bits by 1 in the example code when using two ESPs.

//Bump

@vicnevicne
Copy link
Contributor

vicnevicne commented Feb 22, 2017

Probably linked to the clock polarity. See this post (and followings)...
Also linked to #2270

if((status & SPISWBIS) != 0 && (_hspi_slave_rx_data_cb)) {
uint8_t i;
uint32_t data;
uint8_t buffer[33];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this buffer is not used at all.

@beegee-tokyo
Copy link

beegee-tokyo commented Jan 18, 2018

Same here between an ESP32 (SPI master) and an ESP8266 (SPI slave). Need to shift the received data by 1 bit to receive the correct data on the ESP32. The ESP8266 receives data correct.
SPI is set to MSBFIRST and SPI_MODE1.
Looking on my osci shots, it looks like the ESP8266 Slave expects the command to be only 7 bits instead of 8 bits, because he starts to push the MISO line already at the 8th bit of the command!
In attached screenshot yellow is the CLK line, blue is the MISO line:
Top is CLK, bottom is MISO

@vdeconinck
Copy link
Contributor

Could you switch to another SPI mode on the ESP8266 (only) ? Others have observed weird (reversed) behaviours. See #2416

@beegee-tokyo
Copy link

beegee-tokyo commented Jan 19, 2018

@vdeconinck there is no possibility to change the SPI mode in the ESP8266 slave. Only public functions are
in SPISlave.h:

public:
    SPISlaveClass()
        : _data_cb(NULL)
        , _status_cb(NULL)
        , _data_sent_cb(NULL)
        , _status_sent_cb(NULL)
    {}
    ~SPISlaveClass() {}
    void begin();
    void setData(uint8_t * data, size_t len);
    void setData(const char * data)
    {
        setData((uint8_t *)data, strlen(data));
    }
    void setStatus(uint32_t status);
    void onData(SpiSlaveDataHandler cb);
    void onDataSent(SpiSlaveSentHandler cb);
    void onStatus(SpiSlaveStatusHandler cb);
    void onStatusSent(SpiSlaveSentHandler cb);
};

and in hspi_slave.h:

//Start SPI SLave
void hspi_slave_begin(uint8_t status_len, void * arg);

//set the status register so the master can read it
void hspi_slave_setStatus(uint32_t status);

//set the data registers (max 32 bytes at a time)
void hspi_slave_setData(uint8_t *data, uint8_t len);

//set the callbacks
void hspi_slave_onData(void (*rxd_cb)(void *, uint8_t *, uint8_t));
void hspi_slave_onDataSent(void (*txd_cb)(void *));
void hspi_slave_onStatus(void (*rxs_cb)(void *, uint32_t));
void hspi_slave_onStatusSent(void (*txs_cb)(void *));

The rest is hidden in the non-public code of Espressif. I guess @me-no-dev has to work on this, but he is now fully involved in the ESP32 stuff. I don't think anything will change here. Too bad 👎

@vdeconinck
Copy link
Contributor

Mmmh, I once used SPI slave code by @me-no-dev that included the possibility to select the mode, but it didn't seem to make it to the "official" SPI slave lib.
Could I suggest that you try modes 0, 2 and 3 on the ESP32 (master) ? Just to know if I'm on the right track ?

@beegee-tokyo
Copy link

beegee-tokyo commented Jan 19, 2018

I tried all four modes, only mode1 works, but with this strange bit shift.
I might test tomorrow between 2 ESP8266 to see the difference.
I went as well through the code hspi_slave.cpp and tried to unterstand how the SPI registers are setup and played around with them (documentation on this is basically none existent) but I couldn't get it to work. What I really don't understand is why the ESP8266 starts pushing the MISO pin on the 8th bit of the command and stops 1 bit to early at the end. That is really strange. It looks like the state-machine already caught a clock cycle before the ESP32 starts to send the command.But I could never see a SCLK rise/fall before the communication starts. Maybe I try to stop and reinitialize the SPI on the ESP8266 after the first access from the ESP32 and check if that changes anything.

@beegee-tokyo
Copy link

beegee-tokyo commented Jan 20, 2018

Ok did a ESP8266 SPI Master to ESP8266 SPI Slave test. Getting the same result. And same picture on the oscilloscope:

esp8266_slave_problem_2

Wondering how this ever was tagged as working. I have no level shifters laying around so I cannot test against an Arduino Uno as SPI Master, but I doubt that there is any difference.

Maybe between writing the SPI Slave library and today was some changes in the SDK, but I am not sure how to check this.

Giving up on the idea to connect ESP8266 and ESP32 by SPI for now. Too bad that the SPI slave lib is not working. Maybe I try to get an I2C connection to work between the two boards.

@vdeconinck
Copy link
Contributor

Code I used was from http://www.esp8266.com/viewtopic.php?f=32&t=10579&hilit=Spi+slave#p50011 but it predates "official" spi slave lib in the core. I think that thread is worth a read.
Note: using a Uno as a reference is a good idea. just use 1K / 1K5 resistor dividers on clk and mosi for level shifting.

@beegee-tokyo
Copy link

In the [ESP8266 Technical Reference]((https://espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf) I found the following:

4.3.4 Slave SPI Communication Format Supported by Current API
The API function of ESP8266 SPI has a slave initialization mode which is compatible with
most of the devices in bytes. Set the slave communication format of 7 bits command+8
bits read/write data so that other master SPI devices could read and write bytes of slave
SPI via the 16 bits communication (or two times 8 bits with low lever CS). Please refer to
Section 4.4.2 for detailed information.

But the waveform shown in the same documents shows that the data starts after the 8th bit of command:

waveform-graph-2

I could not find anything to change the slave command length, so I am wondering what is correct. Guess I have to check now how to set the ESP32's SPI master command length to 7 bits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants