From af0f5ed956b85e41da647d51d1799db469d6e697 Mon Sep 17 00:00:00 2001 From: jpmendoza Date: Sat, 6 May 2017 09:26:19 -0500 Subject: [PATCH] Issue #1062: Implement support for HSPI overlap mode. --- cores/esp8266/esp8266_peri.h | 4 ++ doc/libraries.md | 22 +++++++++ libraries/SPI/SPI.cpp | 96 ++++++++++++++++++++++++++++++------ libraries/SPI/SPI.h | 2 + 4 files changed, 110 insertions(+), 14 deletions(-) diff --git a/cores/esp8266/esp8266_peri.h b/cores/esp8266/esp8266_peri.h index 0ad689353..3610cb693 100644 --- a/cores/esp8266/esp8266_peri.h +++ b/cores/esp8266/esp8266_peri.h @@ -586,6 +586,10 @@ extern uint8_t esp8266_gpioToFn[16]; #define SPIE2IHEN 0x3 //SPI_INT_HOLD_ENA #define SPIE2IHEN_S 0 //SPI_INT_HOLD_ENA_S +//SPI PIN (SPIxP) +#define SPIPCS2DIS (1 << 2) +#define SPIPCS1DIS (1 << 1) +#define SPIPCS0DIS (1 << 0) //SLC (DMA) Registers #define SLCC0 ESP8266_REG(0xB00) //SLC_CONF0 diff --git a/doc/libraries.md b/doc/libraries.md index c22a3d8ce..cbcc9762f 100644 --- a/doc/libraries.md +++ b/doc/libraries.md @@ -56,6 +56,28 @@ else they default to pins 4(SDA) and 5(SCL). SPI library supports the entire Arduino SPI API including transactions, including setting phase (CPHA). Setting the Clock polarity (CPOL) is not supported, yet (SPI_MODE2 and SPI_MODE3 not working). +The usual SPI pins are: + +- `MOSI` = GPIO13 +- `MISO` = GPIO12 +- `SCLK` = GPIO14 + +There's an extended mode where you can swap the normal pins to the pin0 hardware pins. +This is enabled by calling `SPI.pins(6, 7, 8, 0)` before the call to `SPI.begin()`. The pins would +change to: + +- `MOSI` = SD1 +- `MISO` = SD0 +- `SCLK` = CLK +- `HWCS` = GPIO0 + +This mode shares the SPI pins with the controller that reads the program code from flash and is +controlled by a hardware arbiter (the flash has always higher priority). For this mode the CS +will be controlled by hardware as you can't handle the CS line with a GPIO, you never actually +know when the arbiter is going to grant you access to the bus so you must let it handle CS +automatically. + + ## SoftwareSerial diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index ba3a9a044..9431077c4 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -22,6 +22,12 @@ #include "SPI.h" #include "HardwareSerial.h" +#define SPI_PINS_HSPI 0 // Normal HSPI mode (MISO = GPIO12, MOSI = GPIO13, SCLK = GPIO14); +#define SPI_PINS_HSPI_OVERLAP 1 // HSPI Overllaped in spi0 pins (MISO = SD0, MOSI = SDD1, SCLK = CLK); + +#define SPI_OVERLAP_SS 0 + + typedef union { uint32_t regValue; struct { @@ -35,12 +41,43 @@ typedef union { SPIClass::SPIClass() { useHwCs = false; + pinSet = SPI_PINS_HSPI; +} + +bool SPIClass::pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss) +{ + if (sck == 6 && + miso == 7 && + mosi == 8 && + ss == 0) { + pinSet = SPI_PINS_HSPI_OVERLAP; + } else if (sck == 14 && + miso == 12 && + mosi == 13) { + pinSet = SPI_PINS_HSPI; + } else { + return false; + } + + return true; } void SPIClass::begin() { - pinMode(SCK, SPECIAL); ///< GPIO14 - pinMode(MISO, SPECIAL); ///< GPIO12 - pinMode(MOSI, SPECIAL); ///< GPIO13 + switch (pinSet) { + case SPI_PINS_HSPI_OVERLAP: + IOSWAP |= (1 << IOSWAP2CS); + //SPI0E3 |= 0x1; This is in the MP3_DECODER example, but makes the WD kick in here. + SPI1E3 |= 0x3; + + setHwCs(true); + break; + case SPI_PINS_HSPI: + default: + pinMode(SCK, SPECIAL); ///< GPIO14 + pinMode(MISO, SPECIAL); ///< GPIO12 + pinMode(MOSI, SPECIAL); ///< GPIO13 + break; + } SPI1C = 0; setFrequency(1000000); ///< 1MHz @@ -50,24 +87,55 @@ void SPIClass::begin() { } void SPIClass::end() { - pinMode(SCK, INPUT); - pinMode(MISO, INPUT); - pinMode(MOSI, INPUT); - if(useHwCs) { - pinMode(SS, INPUT); + switch (pinSet) { + case SPI_PINS_HSPI: + pinMode(SCK, INPUT); + pinMode(MISO, INPUT); + pinMode(MOSI, INPUT); + if (useHwCs) { + pinMode(SS, INPUT); + } + break; + case SPI_PINS_HSPI_OVERLAP: + IOSWAP &= ~(1 << IOSWAP2CS); + if (useHwCs) { + SPI1P |= SPIPCS1DIS | SPIPCS0DIS | SPIPCS2DIS; + pinMode(SPI_OVERLAP_SS, INPUT); + } + break; } } void SPIClass::setHwCs(bool use) { - if(use) { - pinMode(SS, SPECIAL); ///< GPIO15 - SPI1U |= (SPIUCSSETUP | SPIUCSHOLD); + switch (pinSet) { + case SPI_PINS_HSPI: + if (use) { + pinMode(SS, SPECIAL); ///< GPIO15 + SPI1U |= (SPIUCSSETUP | SPIUCSHOLD); } else { - if(useHwCs) { - pinMode(SS, INPUT); + if (useHwCs) { + pinMode(SS, INPUT); SPI1U &= ~(SPIUCSSETUP | SPIUCSHOLD); + } } + break; + case SPI_PINS_HSPI_OVERLAP: + if (use) { + pinMode(SPI_OVERLAP_SS, FUNCTION_1); // GPI0 to SPICS2 mode + SPI1P &= ~SPIPCS2DIS; + SPI1P |= SPIPCS1DIS | SPIPCS0DIS; + SPI1U |= (SPIUCSSETUP | SPIUCSHOLD); + } + else { + if (useHwCs) { + pinMode(SPI_OVERLAP_SS, INPUT); + SPI1P |= SPIPCS1DIS | SPIPCS0DIS | SPIPCS2DIS; + SPI1U &= ~(SPIUCSSETUP | SPIUCSHOLD); + } + } + break; } + useHwCs = use; } @@ -306,7 +374,7 @@ void SPIClass::write32(uint32_t data, bool msb) { SPI1W0 = data; SPI1CMD |= SPIBUSY; } - while(SPI1CMD & SPIBUSY) {} + while(SPI1CMD & SPIBUSY) {} } /** diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index 22128b8e1..c7e2ae4e7 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -53,6 +53,7 @@ public: class SPIClass { public: SPIClass(); + bool pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss); void begin(); void end(); void setHwCs(bool use); @@ -74,6 +75,7 @@ public: void endTransaction(void); private: bool useHwCs; + uint8_t pinSet; void writeBytes_(uint8_t * data, uint8_t size); void transferBytes_(uint8_t * out, uint8_t * in, uint8_t size); inline void setDataBits(uint16_t bits);