Skip to content

Commit

Permalink
Chibios SPI driver: allow some SPI pins to be left unassigned (qmk#20315
Browse files Browse the repository at this point in the history
)

Co-authored-by: Sergey Vlasov <[email protected]>
Co-authored-by: Nick Brassel <[email protected]>
  • Loading branch information
3 people authored and mechlovin committed Oct 25, 2023
1 parent a4a0c18 commit aa68c41
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 17 deletions.
5 changes: 5 additions & 0 deletions docs/spi_driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ Configuration-wise, you'll need to set up the peripheral as per your MCU's datas

As per the AVR configuration, you may choose any other standard GPIO as a slave select pin, which should be supplied to `spi_start()`.

If a complete SPI interface is not required, then the following can be done to disable certain SPI pins, so they don't occupy a GPIO unnecessarily:
- in `config.h`: `#define SPI_MISO_PIN NO_PIN`
- in `config.h`: `#define SPI_MOSI_PIN NO_PIN`
- in `mcuconf.h`: `#define SPI_SELECT_MODE SPI_SELECT_MODE_NONE`, in this case the `slavePin` argument passed to `spi_start()` may be `NO_PIN` if the slave select pin is not used.
## API :id=api
### `void spi_init(void)` :id=api-spi-init
Expand Down
72 changes: 55 additions & 17 deletions platforms/chibios/drivers/spi_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,60 @@

#include "timer.h"

static pin_t currentSlavePin = NO_PIN;
static bool spiStarted = false;

#if defined(K20x) || defined(KL2x) || defined(RP2040)
static SPIConfig spiConfig = {NULL, 0, 0, 0};
#else
static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0};
#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
static pin_t currentSlavePin;
#endif

static SPIConfig spiConfig;

__attribute__((weak)) void spi_init(void) {
static bool is_initialised = false;
if (!is_initialised) {
is_initialised = true;

// Try releasing special pins for a short time
setPinInput(SPI_SCK_PIN);
setPinInput(SPI_MOSI_PIN);
setPinInput(SPI_MISO_PIN);
if (SPI_MOSI_PIN != NO_PIN) {
setPinInput(SPI_MOSI_PIN);
}
if (SPI_MISO_PIN != NO_PIN) {
setPinInput(SPI_MISO_PIN);
}

chThdSleepMilliseconds(10);
#if defined(USE_GPIOV1)
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_PAL_MODE);
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_PAL_MODE);
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE);
if (SPI_MOSI_PIN != NO_PIN) {
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_PAL_MODE);
}
if (SPI_MISO_PIN != NO_PIN) {
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE);
}
#else
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_FLAGS);
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_FLAGS);
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_FLAGS);
if (SPI_MOSI_PIN != NO_PIN) {
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_FLAGS);
}
if (SPI_MISO_PIN != NO_PIN) {
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_FLAGS);
}
#endif
spiStop(&SPI_DRIVER);
currentSlavePin = NO_PIN;
spiStarted = false;
}
}

bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
if (currentSlavePin != NO_PIN || slavePin == NO_PIN) {
if (spiStarted) {
return false;
}
#if SPI_SELECT_MODE != SPI_SELECT_MODE_NONE
if (slavePin == NO_PIN) {
return false;
}
#endif

#if !(defined(WB32F3G71xx) || defined(WB32FQ95xx))
uint16_t roundedDivisor = 2;
Expand Down Expand Up @@ -247,13 +264,29 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
}
#endif

currentSlavePin = slavePin;
spiStarted = true;
#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
currentSlavePin = slavePin;
#endif
#if SPI_SELECT_MODE == SPI_SELECT_MODE_PAD
spiConfig.ssport = PAL_PORT(slavePin);
spiConfig.sspad = PAL_PAD(slavePin);

setPinOutput(slavePin);
#elif SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
if (slavePin != NO_PIN) {
setPinOutput(slavePin);
}
#else
# error "Unsupported SPI_SELECT_MODE"
#endif

spiStart(&SPI_DRIVER, &spiConfig);
spiSelect(&SPI_DRIVER);
#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
if (slavePin != NO_PIN) {
writePinLow(slavePin);
}
#endif

return true;
}
Expand Down Expand Up @@ -283,9 +316,14 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) {
}

void spi_stop(void) {
if (currentSlavePin != NO_PIN) {
if (spiStarted) {
#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
if (currentSlavePin != NO_PIN) {
writePinHigh(currentSlavePin);
}
#endif
spiUnselect(&SPI_DRIVER);
spiStop(&SPI_DRIVER);
currentSlavePin = NO_PIN;
spiStarted = false;
}
}

0 comments on commit aa68c41

Please sign in to comment.