Skip to content

Commit 9113ede

Browse files
committed
Add SPI slave mode support
1 parent 1c9f884 commit 9113ede

File tree

3 files changed

+44
-15
lines changed

3 files changed

+44
-15
lines changed

libraries/SPI/src/SPI.cpp

+28-13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ SPIClass::SPIClass() : _CSPinConfig(NO_CONFIG)
2222
_spi.pin_mosi = digitalPinToPinName(MOSI);
2323
_spi.pin_sclk = digitalPinToPinName(SCK);
2424
_spi.pin_ssel = NC;
25+
_device = SPI_MASTER;
2526
}
2627

2728
/**
@@ -49,27 +50,36 @@ SPIClass::SPIClass(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel) :
4950
_spi.pin_mosi = digitalPinToPinName(mosi);
5051
_spi.pin_sclk = digitalPinToPinName(sclk);
5152
_spi.pin_ssel = digitalPinToPinName(ssel);
53+
_device = SPI_MASTER;
5254
}
5355

5456
/**
5557
* @brief Initialize the SPI instance.
5658
* @param _pin: chip select pin (optional). If this parameter is filled,
5759
* it gives the management of the CS pin to the SPI class. In this case
5860
* do not manage the CS pin outside of the SPI class.
61+
* @param device: device mode (optional), master or slave. Default is master.
5962
*/
60-
void SPIClass::begin(uint8_t _pin)
63+
void SPIClass::begin(uint8_t _pin, SPIDeviceMode device)
6164
{
65+
_device = device;
66+
6267
uint8_t idx = pinIdx(_pin, ADD_NEW_PIN);
6368
if (idx >= NB_SPI_SETTINGS) {
6469
return;
6570
}
6671

6772
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
68-
pinMode(_pin, OUTPUT);
69-
digitalWrite(_pin, HIGH);
73+
if (_device == SPI_MASTER) {
74+
pinMode(_pin, OUTPUT);
75+
digitalWrite(_pin, HIGH);
76+
} else {
77+
pinMode(_pin, INPUT_PULLUP);
78+
}
7079
}
7180

7281
_spi.handle.State = HAL_SPI_STATE_RESET;
82+
_spi.handle.Init.Mode = (_device == SPI_MASTER) ? SPI_MODE_MASTER : SPI_MODE_SLAVE;
7383
spi_init(&_spi, spiSettings[idx].clk,
7484
spiSettings[idx].dMode,
7585
spiSettings[idx].bOrder);
@@ -106,10 +116,15 @@ void SPIClass::beginTransaction(uint8_t _pin, SPISettings settings)
106116
spiSettings[idx].noReceive = settings.noReceive;
107117

108118
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
109-
pinMode(_pin, OUTPUT);
110-
digitalWrite(_pin, HIGH);
119+
if (_device == SPI_MASTER) {
120+
pinMode(_pin, OUTPUT);
121+
digitalWrite(_pin, HIGH);
122+
} else {
123+
pinMode(_pin, INPUT_PULLUP);
124+
}
111125
}
112126

127+
_spi.handle.Init.Mode = (_device == SPI_MASTER) ? SPI_MODE_MASTER : SPI_MODE_SLAVE;
113128
spi_init(&_spi, spiSettings[idx].clk,
114129
spiSettings[idx].dMode,
115130
spiSettings[idx].bOrder);
@@ -244,13 +259,13 @@ byte SPIClass::transfer(uint8_t _pin, uint8_t data, SPITransferMode _mode)
244259
_CSPinConfig = _pin;
245260
}
246261

247-
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
262+
if ((_device == SPI_MASTER) && (_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
248263
digitalWrite(_pin, LOW);
249264
}
250265

251266
spi_transfer(&_spi, &data, &rx_buffer, sizeof(uint8_t), SPI_TRANSFER_TIMEOUT, spiSettings[idx].noReceive);
252267

253-
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) {
268+
if ((_device == SPI_MASTER) && (_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) {
254269
digitalWrite(_pin, HIGH);
255270
}
256271

@@ -292,14 +307,14 @@ uint16_t SPIClass::transfer16(uint8_t _pin, uint16_t data, SPITransferMode _mode
292307
data = tmp;
293308
}
294309

295-
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
310+
if ((_device == SPI_MASTER) && (_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
296311
digitalWrite(_pin, LOW);
297312
}
298313

299314
spi_transfer(&_spi, (uint8_t *)&data, (uint8_t *)&rx_buffer, sizeof(uint16_t),
300315
SPI_TRANSFER_TIMEOUT, spiSettings[idx].noReceive);
301316

302-
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) {
317+
if ((_device == SPI_MASTER) && (_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) {
303318
digitalWrite(_pin, HIGH);
304319
}
305320

@@ -342,14 +357,14 @@ void SPIClass::transfer(uint8_t _pin, void *_buf, size_t _count, SPITransferMode
342357
_CSPinConfig = _pin;
343358
}
344359

345-
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
360+
if ((_device == SPI_MASTER) && (_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
346361
digitalWrite(_pin, LOW);
347362
}
348363

349364
spi_transfer(&_spi, ((uint8_t *)_buf), ((uint8_t *)_buf), _count,
350365
SPI_TRANSFER_TIMEOUT, spiSettings[idx].noReceive);
351366

352-
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) {
367+
if ((_device == SPI_MASTER) && (_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) {
353368
digitalWrite(_pin, HIGH);
354369
}
355370
}
@@ -386,14 +401,14 @@ void SPIClass::transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, S
386401
_CSPinConfig = _pin;
387402
}
388403

389-
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
404+
if ((_device == SPI_MASTER) && (_pin != CS_PIN_CONTROLLED_BY_USER) && (_spi.pin_ssel == NC)) {
390405
digitalWrite(_pin, LOW);
391406
}
392407

393408
spi_transfer(&_spi, ((uint8_t *)_bufout), ((uint8_t *)_bufin), _count,
394409
SPI_TRANSFER_TIMEOUT, spiSettings[idx].noReceive);
395410

396-
if ((_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) {
411+
if ((_device == SPI_MASTER) && (_pin != CS_PIN_CONTROLLED_BY_USER) && (_mode == SPI_LAST) && (_spi.pin_ssel == NC)) {
397412
digitalWrite(_pin, HIGH);
398413
}
399414
}

libraries/SPI/src/SPI.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ enum SPITransferMode {
5353
SPI_LAST /* Transfer ended: CS pin released */
5454
};
5555

56+
// Device mode
57+
enum SPIDeviceMode {
58+
SPI_MASTER, /* Device is master */
59+
SPI_SLAVE /* Device is slave */
60+
};
61+
5662
// Indicates the user controls himself the CS pin outside of the spi class
5763
#define CS_PIN_CONTROLLED_BY_USER NUM_DIGITAL_PINS
5864

@@ -148,7 +154,7 @@ class SPIClass {
148154
_spi.pin_ssel = (ssel);
149155
};
150156

151-
virtual void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
157+
virtual void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER, SPIDeviceMode device = SPI_MASTER);
152158
void end(void);
153159

154160
/* This function should be used to configure the SPI instance in case you
@@ -230,9 +236,18 @@ class SPIClass {
230236
return &(_spi.handle);
231237
}
232238

239+
void attachSlaveInterrupt(uint8_t pin, callback_function_t callback) {
240+
::attachInterrupt(pin, callback, FALLING);
241+
}
242+
243+
void detachSlaveInterrupt(uint8_t pin) {
244+
::detachInterrupt(pin);
245+
}
246+
233247
protected:
234248
// spi instance
235249
spi_t _spi;
250+
SPIDeviceMode _device;
236251

237252
private:
238253
/* Contains various spiSettings for the same spi instance. Each spi spiSettings

libraries/SPI/src/utility/spi_com.c

-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
280280

281281
/* Fill default value */
282282
handle->Instance = obj->spi;
283-
handle->Init.Mode = SPI_MODE_MASTER;
284283

285284
spi_freq = spi_getClkFreqInst(obj->spi);
286285
/* For SUBGHZSPI, 'SPI_BAUDRATEPRESCALER_*' == 'SUBGHZSPI_BAUDRATEPRESCALER_*' */

0 commit comments

Comments
 (0)