esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
15.89k stars 13.35k forks source link

setting SPI Slave mode #5104

Open paultanner opened 5 years ago

paultanner commented 5 years ago

Platform

Settings in IDE

Problem Description

I am using and nRF52832 as master using nrf5 SDK and 8266 as SPI slave. The master works with other SPI slave devices. It appears that the mode is wrong on the SPI slave as the data is changing on the leading edge of the clock and most of the time is getting corrupted. In other words data is flowing in both directions but is mostly incorrect. I need to change the slave to mode 3. I verified this by changing the mode at the master. This is not the right solution as there are other slaves that need mode 0.
SPISlave.begin() has no facility for setting the mode but I guess one could set the mode bits after invoking that. Is there any code example anywhere that would show me how to do this? Better still, could a mode parameter be added to this call? Note: https://github.com/esp8266/Arduino/issues/2416#issue-172312441 is related but not the same issue.

Sketch

Test sketch is the one in the current version of this repo.

https://github.com/esp8266/Arduino/blob/74819a763bfb6e9890a57411dcea4aba221a778d/libraries/SPISlave/examples/SPISlave_Test/SPISlave_Test.ino

Debug Messages

none
GuaAck commented 5 years ago

Hallo,

I had difficulties to connect an Arduino DUE with ESP8266 as SPI-Slave. DUE and ESP are configured with SPI-Mode=0. I tried alle modes 0 to 3 on the DUE, without any success. The screen shots (attached) from an oscilloscope show the reason: MISO does not match with MODE 0, where the sampling occures with the rising edge and the data change at the falling edge of SCK. (With a slower Arduino UNO it works nevertheless, but not very reliable.)

My work around: The ESP provides the option to delay the MISO-Signal. I found the refering registers and added one line in the file hspi_slave.c: of the SPISlave-Library (to the ESP8266): ` void hspi_slave_begin(uint8_t status_len, void * arg) { .... SPI1CMD = SPIBUSY; SPI1C2=(0x2<<SPIC2MOSIDN_S) | (0x3<<SPIC2MISODN_S) | (0x7<<SPIC2MISODN_S); // Added 28.10.2018, works for SCK = 4 MHz ETS_SPI_INTR_ATTACH(_hspi_slave_isr_handler,arg); ... }

The delay also for MOSI seems not reasonable, but I found in the ESP32 reference that it has to be 0x2 for MODE0, so I added it, but I found no influence.

With this change, the timing was perfect and the communication with the DUE works reliable.

spimodes

GuaAck commented 5 years ago

Hallo again, there is a much better solution: SPI1C2=(0x2<<SPIC2MOSIDN_S) | (0x1<<SPIC2MISODM_S); (Please take care of "N_S" and "M_S".);

This works also with much lower frequencies.

GuaAck

devyte commented 5 years ago

@GuaAck could you please explain in detail what you're doing, and why the second solution is better?

GuaAck commented 5 years ago

Hallo,

to answer the question:

I tried to connect an EP8266 with my Arduino DUE, it fails. The program works with the UNO and the MEGA. As a reason I found, that the timing of MISO does not match with SPI-MODE0. (Setting the MODE 1 - 3 in the master had no success.) The slower UNO and MEGA fread the correct bit, but the much faster DUE does not (See photos in the post above). I found somewhere, that the ESP32 has a SPI-module similar to that one in the ESP8266. On base of the technical reference I inserted the delay of the MISO of 8 cycles (MISODN=7) and it works for 4 MHz. But because it is a simple delay, I had doubts that it works for lower clock frequencies (it does not), but this was no problem for my project.

I have also contacted Jiri Bilek (https://github.com/JiriBilek/WiFiSpiESP), I use his library. We worked together to find out, what happens. Finally Jiri has had the idea to set MISODM=1 and to forget MISODN. I tried it, and it works perfectly and independant on the SCK-frequency, tested with 4 MHZ and 320 kHz.

I hope this helps, GuaAck

devyte commented 5 years ago

@GuaAck thank you, that certainly clears up the intent at high level. But I meant at low level, as in what does the line of code do? What registers are accessed, what do the bits mean? Like you said, the ESP's registers aren't really documented, and you seem to have investigated, so my request is for the details, so that they can be added e.g. as comments to a PR or inline with the code. And speaking of PR, how about making one with your code change? This core is a community effort, and your contribution is highly welcome. It's only fair that your name shows up in the contribution history :)