Skip to content

Commit 2e5c932

Browse files
P-R-O-C-H-Ylucasssvazme-no-dev
authored
SPI - Allow detaching of some SPI pins without stopping SPI (espressif#9117)
* feature(spi): Allow detach of some SPI pins * fix(spi): Remove unnecessary check Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> * feat(spi): Rename CS pin to SS to match Arduino standard * fix(spi): Remove unnecessary checks * remove lock from spiAttackMISO --------- Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com> Co-authored-by: me-no-dev <hristo@espressif.com>
1 parent 4766608 commit 2e5c932

File tree

5 files changed

+124
-87
lines changed

5 files changed

+124
-87
lines changed

Diff for: cores/esp32/esp32-hal-periman.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const char* perimanGetTypeName(peripheral_bus_type_t type) {
7878
case ESP32_BUS_TYPE_SPI_MASTER_SCK: return "SPI_MASTER_SCK";
7979
case ESP32_BUS_TYPE_SPI_MASTER_MISO: return "SPI_MASTER_MISO";
8080
case ESP32_BUS_TYPE_SPI_MASTER_MOSI: return "SPI_MASTER_MOSI";
81-
case ESP32_BUS_TYPE_SPI_MASTER_CS: return "SPI_MASTER_CS";
81+
case ESP32_BUS_TYPE_SPI_MASTER_SS: return "SPI_MASTER_SS";
8282
#endif
8383
#if SOC_SDMMC_HOST_SUPPORTED
8484
case ESP32_BUS_TYPE_SDMMC_CLK: return "SDMMC_CLK";

Diff for: cores/esp32/esp32-hal-periman.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ typedef enum {
7777
ESP32_BUS_TYPE_SPI_MASTER_SCK, // IO is used as SPI master SCK pin
7878
ESP32_BUS_TYPE_SPI_MASTER_MISO, // IO is used as SPI master MISO pin
7979
ESP32_BUS_TYPE_SPI_MASTER_MOSI, // IO is used as SPI master MOSI pin
80-
ESP32_BUS_TYPE_SPI_MASTER_CS, // IO is used as SPI master CS pin
80+
ESP32_BUS_TYPE_SPI_MASTER_SS, // IO is used as SPI master SS pin
8181
#endif
8282
#if SOC_SDMMC_HOST_SUPPORTED
8383
ESP32_BUS_TYPE_SDMMC_CLK, // IO is used as SDMMC CLK pin

Diff for: cores/esp32/esp32-hal-spi.c

+99-60
Original file line numberDiff line numberDiff line change
@@ -177,36 +177,65 @@ static spi_t _spi_bus_array[] = {
177177
static bool spiDetachBus(void * bus){
178178
uint8_t spi_num = (int)bus - 1;
179179
spi_t * spi = &_spi_bus_array[spi_num];
180-
if(spi->dev->clock.val != 0){
181-
log_d("Stopping SPI BUS");
180+
181+
if(spi->dev->clock.val == 0){
182+
log_d("SPI bus already stopped");
183+
return true;
184+
}
185+
else if(spi->sck == -1 || (spi->miso == -1 && spi->mosi == -1)){
186+
log_d("Stopping SPI bus");
182187
spiStopBus(spi);
188+
189+
spiDetachSCK(spi);
190+
spiDetachMISO(spi);
191+
spiDetachMOSI(spi);
192+
spiDetachSS(spi);
193+
spi = NULL;
194+
return true;
183195
}
196+
return true;
197+
}
198+
199+
static bool spiDetachBus_SCK(void * bus){
200+
uint8_t spi_num = (int)bus - 1;
201+
spi_t * spi = &_spi_bus_array[spi_num];
184202
if(spi->sck != -1){
185-
log_d("SPI detach SCK pin %d",spi->sck);
186-
spiDetachSCK(spi,spi->sck);
203+
spiDetachSCK(spi);
204+
spiDetachBus(bus);
187205
}
206+
return true;
207+
}
208+
209+
static bool spiDetachBus_MISO(void * bus){
210+
uint8_t spi_num = (int)bus - 1;
211+
spi_t * spi = &_spi_bus_array[spi_num];
188212
if(spi->miso != -1){
189-
log_d("SPI detach MISO pin %d",spi->miso);
190-
spiDetachMISO(spi,spi->miso);
213+
spiDetachMISO(spi);
214+
spiDetachBus(bus);
191215
}
216+
return true;
217+
}
218+
219+
static bool spiDetachBus_MOSI(void * bus){
220+
uint8_t spi_num = (int)bus - 1;
221+
spi_t * spi = &_spi_bus_array[spi_num];
192222
if(spi->mosi != -1){
193-
log_d("SPI detach MOSI pin %d",spi->mosi);
194-
spiDetachMOSI(spi,spi->mosi);
223+
spiDetachMOSI(spi);
224+
spiDetachBus(bus);
195225
}
226+
return true;
227+
}
228+
229+
static bool spiDetachBus_SS(void * bus){
230+
uint8_t spi_num = (int)bus - 1;
231+
spi_t * spi = &_spi_bus_array[spi_num];
196232
if(spi->ss != -1){
197-
log_d("SPI detach SS pin %d",spi->ss);
198-
spiDetachSS(spi,spi->ss);
233+
spiDetachSS(spi);
234+
spiDetachBus(bus);
199235
}
200-
//set SPI to NULL, as all pins are already detached
201-
if(spi->sck == -1 && spi->miso == -1 && spi->mosi == -1 && spi->ss == -1){
202-
log_d("Set spi handle to NULL");
203-
spi = NULL;
204-
return true;
205-
}
206-
return false;
236+
return true;
207237
}
208238

209-
210239
bool spiAttachSCK(spi_t * spi, int8_t sck)
211240
{
212241
if(!spi || sck < 0) {
@@ -220,7 +249,7 @@ bool spiAttachSCK(spi_t * spi, int8_t sck)
220249
pinMatrixOutAttach(sck, SPI_CLK_IDX(spi->num), false, false);
221250
spi->sck = sck;
222251
if(!perimanSetPinBus(sck, ESP32_BUS_TYPE_SPI_MASTER_SCK, (void *)(spi->num+1), spi->num, -1)){
223-
spiDetachBus((void *)(spi->num+1));
252+
spiDetachBus_SCK((void *)(spi->num+1));
224253
log_e("Failed to set pin bus to SPI for pin %d", sck);
225254
return false;
226255
}
@@ -236,13 +265,11 @@ bool spiAttachMISO(spi_t * spi, int8_t miso)
236265
if(bus != NULL && !perimanClearPinBus(miso)){
237266
return false;
238267
}
239-
SPI_MUTEX_LOCK();
240268
pinMode(miso, INPUT);
241269
pinMatrixInAttach(miso, SPI_MISO_IDX(spi->num), false);
242270
spi->miso = miso;
243-
SPI_MUTEX_UNLOCK();
244271
if(!perimanSetPinBus(miso, ESP32_BUS_TYPE_SPI_MASTER_MISO, (void *)(spi->num+1), spi->num, -1)){
245-
spiDetachBus((void *)(spi->num+1));
272+
spiDetachBus_MISO((void *)(spi->num+1));
246273
log_e("Failed to set pin bus to SPI for pin %d", miso);
247274
return false;
248275
}
@@ -262,102 +289,114 @@ bool spiAttachMOSI(spi_t * spi, int8_t mosi)
262289
pinMatrixOutAttach(mosi, SPI_MOSI_IDX(spi->num), false, false);
263290
spi->mosi = mosi;
264291
if(!perimanSetPinBus(mosi, ESP32_BUS_TYPE_SPI_MASTER_MOSI, (void *)(spi->num+1), spi->num, -1)){
265-
spiDetachBus((void *)(spi->num+1));
292+
spiDetachBus_MOSI((void *)(spi->num+1));
266293
log_e("Failed to set pin bus to SPI for pin %d", mosi);
267294
return false;
268295
}
269296
return true;
270297
}
271298

272-
bool spiDetachSCK(spi_t * spi, int8_t sck)
299+
bool spiDetachSCK(spi_t * spi)
273300
{
274-
if(!spi || sck < 0) {
301+
if(!spi) {
275302
return false;
276303
}
277-
pinMatrixOutDetach(sck, false, false);
278-
spi->sck = -1;
279-
perimanClearPinBus(sck);
304+
int8_t sck = spi->sck;
305+
if(sck != -1) {
306+
pinMatrixOutDetach(sck, false, false);
307+
spi->sck = -1;
308+
perimanClearPinBus(sck);
309+
}
280310
return true;
281311
}
282312

283-
bool spiDetachMISO(spi_t * spi, int8_t miso)
313+
bool spiDetachMISO(spi_t * spi)
284314
{
285-
if(!spi || miso < 0) {
315+
if(!spi) {
286316
return false;
287317
}
288-
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
289-
spi->miso = -1;
290-
perimanClearPinBus(miso);
318+
int8_t miso = spi->miso;
319+
if(miso != -1) {
320+
pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false);
321+
spi->miso = -1;
322+
perimanClearPinBus(miso);
323+
}
291324
return true;
292325
}
293326

294-
bool spiDetachMOSI(spi_t * spi, int8_t mosi)
327+
bool spiDetachMOSI(spi_t * spi)
295328
{
296-
if(!spi || mosi < 0) {
329+
if(!spi) {
297330
return false;
298331
}
299-
pinMatrixOutDetach(mosi, false, false);
300-
spi->mosi = -1;
301-
perimanClearPinBus(mosi);
332+
int8_t mosi = spi->mosi;
333+
if(mosi != -1) {
334+
pinMatrixOutDetach(mosi, false, false);
335+
spi->mosi = -1;
336+
perimanClearPinBus(mosi);
337+
}
302338
return true;
303339
}
304340

305-
bool spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
341+
bool spiAttachSS(spi_t * spi, uint8_t ss_num, int8_t ss)
306342
{
307-
if(!spi || ss < 0 || cs_num > 2) {
343+
if(!spi || ss < 0 || ss_num > 2) {
308344
return false;
309345
}
310-
void * bus = perimanGetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_CS);
346+
void * bus = perimanGetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_SS);
311347
if(bus != NULL && !perimanClearPinBus(ss)){
312348
return false;
313349
}
314350
pinMode(ss, OUTPUT);
315-
pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, cs_num), false, false);
316-
spiEnableSSPins(spi, (1 << cs_num));
351+
pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, ss_num), false, false);
352+
spiEnableSSPins(spi, (1 << ss_num));
317353
spi->ss = ss;
318-
if(!perimanSetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_CS, (void *)(spi->num+1), spi->num, -1)){
319-
spiDetachBus((void *)(spi->num+1));
354+
if(!perimanSetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_SS, (void *)(spi->num+1), spi->num, -1)){
355+
spiDetachBus_SS((void *)(spi->num+1));
320356
log_e("Failed to set pin bus to SPI for pin %d", ss);
321357
return false;
322358
}
323359
return true;
324360
}
325361

326-
bool spiDetachSS(spi_t * spi, int8_t ss)
362+
bool spiDetachSS(spi_t * spi)
327363
{
328-
if(!spi || ss < 0) {
364+
if(!spi) {
329365
return false;
330366
}
331-
pinMatrixOutDetach(ss, false, false);
332-
spi->ss = -1;
333-
perimanClearPinBus(ss);
367+
int8_t ss = spi->ss;
368+
if(ss != -1) {
369+
pinMatrixOutDetach(ss, false, false);
370+
spi->ss = -1;
371+
perimanClearPinBus(ss);
372+
}
334373
return true;
335374
}
336375

337-
void spiEnableSSPins(spi_t * spi, uint8_t cs_mask)
376+
void spiEnableSSPins(spi_t * spi, uint8_t ss_mask)
338377
{
339378
if(!spi) {
340379
return;
341380
}
342381
SPI_MUTEX_LOCK();
343382
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
344-
spi->dev->misc.val &= ~(cs_mask & SPI_CS_MASK_ALL);
383+
spi->dev->misc.val &= ~(ss_mask & SPI_SS_MASK_ALL);
345384
#else
346-
spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL);
385+
spi->dev->pin.val &= ~(ss_mask & SPI_SS_MASK_ALL);
347386
#endif
348387
SPI_MUTEX_UNLOCK();
349388
}
350389

351-
void spiDisableSSPins(spi_t * spi, uint8_t cs_mask)
390+
void spiDisableSSPins(spi_t * spi, uint8_t ss_mask)
352391
{
353392
if(!spi) {
354393
return;
355394
}
356395
SPI_MUTEX_LOCK();
357396
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
358-
spi->dev->misc.val |= (cs_mask & SPI_CS_MASK_ALL);
397+
spi->dev->misc.val |= (ss_mask & SPI_SS_MASK_ALL);
359398
#else
360-
spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL);
399+
spi->dev->pin.val |= (ss_mask & SPI_SS_MASK_ALL);
361400
#endif
362401
SPI_MUTEX_UNLOCK();
363402
}
@@ -578,10 +617,10 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
578617
return NULL;
579618
}
580619

581-
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_SCK, spiDetachBus);
582-
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_MISO, spiDetachBus);
583-
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_MOSI, spiDetachBus);
584-
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_CS, spiDetachBus);
620+
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_SCK, spiDetachBus_SCK);
621+
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_MISO, spiDetachBus_MISO);
622+
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_MOSI, spiDetachBus_MOSI);
623+
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_SS, spiDetachBus_SS);
585624

586625
spi_t * spi = &_spi_bus_array[spi_num];
587626

Diff for: cores/esp32/esp32-hal-spi.h

+16-16
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ extern "C" {
5454
#define SPI_MODE2 2
5555
#define SPI_MODE3 3
5656

57-
#define SPI_CS0 0
58-
#define SPI_CS1 1
59-
#define SPI_CS2 2
60-
#define SPI_CS_MASK_ALL 0x7
57+
#define SPI_SS0 0
58+
#define SPI_SS1 1
59+
#define SPI_SS2 2
60+
#define SPI_SS_MASK_ALL 0x7
6161

6262
#define SPI_LSBFIRST 0
6363
#define SPI_MSBFIRST 1
@@ -72,25 +72,25 @@ void spiStopBus(spi_t * spi);
7272
bool spiAttachSCK(spi_t * spi, int8_t sck);
7373
bool spiAttachMISO(spi_t * spi, int8_t miso);
7474
bool spiAttachMOSI(spi_t * spi, int8_t mosi);
75-
bool spiDetachSCK(spi_t * spi, int8_t sck);
76-
bool spiDetachMISO(spi_t * spi, int8_t miso);
77-
bool spiDetachMOSI(spi_t * spi, int8_t mosi);
75+
bool spiDetachSCK(spi_t * spi);
76+
bool spiDetachMISO(spi_t * spi);
77+
bool spiDetachMOSI(spi_t * spi);
7878

79-
//Attach/Detach SS pin to SPI_CSx signal
80-
bool spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss);
81-
bool spiDetachSS(spi_t * spi, int8_t ss);
79+
//Attach/Detach SS pin to SPI_SSx signal
80+
bool spiAttachSS(spi_t * spi, uint8_t ss_num, int8_t ss);
81+
bool spiDetachSS(spi_t * spi);
8282

83-
//Enable/Disable SPI_CSx pins
84-
void spiEnableSSPins(spi_t * spi, uint8_t cs_mask);
85-
void spiDisableSSPins(spi_t * spi, uint8_t cs_mask);
83+
//Enable/Disable SPI_SSx pins
84+
void spiEnableSSPins(spi_t * spi, uint8_t ss_mask);
85+
void spiDisableSSPins(spi_t * spi, uint8_t ss_mask);
8686

87-
//Enable/Disable hardware control of SPI_CSx pins
87+
//Enable/Disable hardware control of SPI_SSx pins
8888
void spiSSEnable(spi_t * spi);
8989
void spiSSDisable(spi_t * spi);
9090

91-
//Activate enabled SPI_CSx pins
91+
//Activate enabled SPI_SSx pins
9292
void spiSSSet(spi_t * spi);
93-
//Deactivate enabled SPI_CSx pins
93+
//Deactivate enabled SPI_SSx pins
9494
void spiSSClear(spi_t * spi);
9595

9696
void spiWaitReady(spi_t * spi);

Diff for: libraries/SPI/src/SPI.cpp

+7-9
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,13 @@ void SPIClass::end()
124124
if(!_spi) {
125125
return;
126126
}
127-
spiDetachSCK(_spi, _sck);
128-
if(_miso >= 0){
129-
spiDetachMISO(_spi, _miso);
130-
}
131-
if(_mosi >= 0){
132-
spiDetachMOSI(_spi, _mosi);
133-
}
127+
spiDetachSCK(_spi);
128+
spiDetachMISO(_spi);
129+
spiDetachMOSI(_spi);
134130
setHwCs(false);
135-
spiStopBus(_spi);
131+
if(spiGetClockDiv(_spi) != 0) {
132+
spiStopBus(_spi);
133+
}
136134
_spi = NULL;
137135
}
138136

@@ -146,7 +144,7 @@ void SPIClass::setHwCs(bool use)
146144
spiSSEnable(_spi);
147145
} else if(!use && _use_hw_ss) {
148146
spiSSDisable(_spi);
149-
spiDetachSS(_spi, _ss);
147+
spiDetachSS(_spi);
150148
}
151149
_use_hw_ss = use;
152150
}

0 commit comments

Comments
 (0)