Skip to content

Commit af0f5ed

Browse files
pablo-mendozaigrr
authored andcommitted
Issue #1062: Implement support for HSPI overlap mode.
1 parent 157698b commit af0f5ed

File tree

4 files changed

+110
-14
lines changed

4 files changed

+110
-14
lines changed

cores/esp8266/esp8266_peri.h

+4
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ extern uint8_t esp8266_gpioToFn[16];
586586
#define SPIE2IHEN 0x3 //SPI_INT_HOLD_ENA
587587
#define SPIE2IHEN_S 0 //SPI_INT_HOLD_ENA_S
588588

589+
//SPI PIN (SPIxP)
590+
#define SPIPCS2DIS (1 << 2)
591+
#define SPIPCS1DIS (1 << 1)
592+
#define SPIPCS0DIS (1 << 0)
589593

590594
//SLC (DMA) Registers
591595
#define SLCC0 ESP8266_REG(0xB00) //SLC_CONF0

doc/libraries.md

+22
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,28 @@ else they default to pins 4(SDA) and 5(SCL).
5656

5757
SPI library supports the entire Arduino SPI API including transactions, including setting phase (CPHA).
5858
Setting the Clock polarity (CPOL) is not supported, yet (SPI_MODE2 and SPI_MODE3 not working).
59+
The usual SPI pins are:
60+
61+
- `MOSI` = GPIO13
62+
- `MISO` = GPIO12
63+
- `SCLK` = GPIO14
64+
65+
There's an extended mode where you can swap the normal pins to the pin0 hardware pins.
66+
This is enabled by calling `SPI.pins(6, 7, 8, 0)` before the call to `SPI.begin()`. The pins would
67+
change to:
68+
69+
- `MOSI` = SD1
70+
- `MISO` = SD0
71+
- `SCLK` = CLK
72+
- `HWCS` = GPIO0
73+
74+
This mode shares the SPI pins with the controller that reads the program code from flash and is
75+
controlled by a hardware arbiter (the flash has always higher priority). For this mode the CS
76+
will be controlled by hardware as you can't handle the CS line with a GPIO, you never actually
77+
know when the arbiter is going to grant you access to the bus so you must let it handle CS
78+
automatically.
79+
80+
5981

6082
## SoftwareSerial
6183

libraries/SPI/SPI.cpp

+82-14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
#include "SPI.h"
2323
#include "HardwareSerial.h"
2424

25+
#define SPI_PINS_HSPI 0 // Normal HSPI mode (MISO = GPIO12, MOSI = GPIO13, SCLK = GPIO14);
26+
#define SPI_PINS_HSPI_OVERLAP 1 // HSPI Overllaped in spi0 pins (MISO = SD0, MOSI = SDD1, SCLK = CLK);
27+
28+
#define SPI_OVERLAP_SS 0
29+
30+
2531
typedef union {
2632
uint32_t regValue;
2733
struct {
@@ -35,12 +41,43 @@ typedef union {
3541

3642
SPIClass::SPIClass() {
3743
useHwCs = false;
44+
pinSet = SPI_PINS_HSPI;
45+
}
46+
47+
bool SPIClass::pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
48+
{
49+
if (sck == 6 &&
50+
miso == 7 &&
51+
mosi == 8 &&
52+
ss == 0) {
53+
pinSet = SPI_PINS_HSPI_OVERLAP;
54+
} else if (sck == 14 &&
55+
miso == 12 &&
56+
mosi == 13) {
57+
pinSet = SPI_PINS_HSPI;
58+
} else {
59+
return false;
60+
}
61+
62+
return true;
3863
}
3964

4065
void SPIClass::begin() {
41-
pinMode(SCK, SPECIAL); ///< GPIO14
42-
pinMode(MISO, SPECIAL); ///< GPIO12
43-
pinMode(MOSI, SPECIAL); ///< GPIO13
66+
switch (pinSet) {
67+
case SPI_PINS_HSPI_OVERLAP:
68+
IOSWAP |= (1 << IOSWAP2CS);
69+
//SPI0E3 |= 0x1; This is in the MP3_DECODER example, but makes the WD kick in here.
70+
SPI1E3 |= 0x3;
71+
72+
setHwCs(true);
73+
break;
74+
case SPI_PINS_HSPI:
75+
default:
76+
pinMode(SCK, SPECIAL); ///< GPIO14
77+
pinMode(MISO, SPECIAL); ///< GPIO12
78+
pinMode(MOSI, SPECIAL); ///< GPIO13
79+
break;
80+
}
4481

4582
SPI1C = 0;
4683
setFrequency(1000000); ///< 1MHz
@@ -50,24 +87,55 @@ void SPIClass::begin() {
5087
}
5188

5289
void SPIClass::end() {
53-
pinMode(SCK, INPUT);
54-
pinMode(MISO, INPUT);
55-
pinMode(MOSI, INPUT);
56-
if(useHwCs) {
57-
pinMode(SS, INPUT);
90+
switch (pinSet) {
91+
case SPI_PINS_HSPI:
92+
pinMode(SCK, INPUT);
93+
pinMode(MISO, INPUT);
94+
pinMode(MOSI, INPUT);
95+
if (useHwCs) {
96+
pinMode(SS, INPUT);
97+
}
98+
break;
99+
case SPI_PINS_HSPI_OVERLAP:
100+
IOSWAP &= ~(1 << IOSWAP2CS);
101+
if (useHwCs) {
102+
SPI1P |= SPIPCS1DIS | SPIPCS0DIS | SPIPCS2DIS;
103+
pinMode(SPI_OVERLAP_SS, INPUT);
104+
}
105+
break;
58106
}
59107
}
60108

61109
void SPIClass::setHwCs(bool use) {
62-
if(use) {
63-
pinMode(SS, SPECIAL); ///< GPIO15
64-
SPI1U |= (SPIUCSSETUP | SPIUCSHOLD);
110+
switch (pinSet) {
111+
case SPI_PINS_HSPI:
112+
if (use) {
113+
pinMode(SS, SPECIAL); ///< GPIO15
114+
SPI1U |= (SPIUCSSETUP | SPIUCSHOLD);
65115
} else {
66-
if(useHwCs) {
67-
pinMode(SS, INPUT);
116+
if (useHwCs) {
117+
pinMode(SS, INPUT);
68118
SPI1U &= ~(SPIUCSSETUP | SPIUCSHOLD);
119+
}
120+
}
121+
break;
122+
case SPI_PINS_HSPI_OVERLAP:
123+
if (use) {
124+
pinMode(SPI_OVERLAP_SS, FUNCTION_1); // GPI0 to SPICS2 mode
125+
SPI1P &= ~SPIPCS2DIS;
126+
SPI1P |= SPIPCS1DIS | SPIPCS0DIS;
127+
SPI1U |= (SPIUCSSETUP | SPIUCSHOLD);
69128
}
129+
else {
130+
if (useHwCs) {
131+
pinMode(SPI_OVERLAP_SS, INPUT);
132+
SPI1P |= SPIPCS1DIS | SPIPCS0DIS | SPIPCS2DIS;
133+
SPI1U &= ~(SPIUCSSETUP | SPIUCSHOLD);
134+
}
135+
}
136+
break;
70137
}
138+
71139
useHwCs = use;
72140
}
73141

@@ -306,7 +374,7 @@ void SPIClass::write32(uint32_t data, bool msb) {
306374
SPI1W0 = data;
307375
SPI1CMD |= SPIBUSY;
308376
}
309-
while(SPI1CMD & SPIBUSY) {}
377+
while(SPI1CMD & SPIBUSY) {}
310378
}
311379

312380
/**

libraries/SPI/SPI.h

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class SPISettings {
5353
class SPIClass {
5454
public:
5555
SPIClass();
56+
bool pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss);
5657
void begin();
5758
void end();
5859
void setHwCs(bool use);
@@ -74,6 +75,7 @@ class SPIClass {
7475
void endTransaction(void);
7576
private:
7677
bool useHwCs;
78+
uint8_t pinSet;
7779
void writeBytes_(uint8_t * data, uint8_t size);
7880
void transferBytes_(uint8_t * out, uint8_t * in, uint8_t size);
7981
inline void setDataBits(uint16_t bits);

0 commit comments

Comments
 (0)