Chibios SPI driver: allow some SPI pins to be left unassigned (#20315)

Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
Co-authored-by: Nick Brassel <nick@tzarc.org>
master
Purdea Andrei 2023-09-25 05:54:22 +03:00 committed by GitHub
parent e0eb90aba1
commit 408d61dcfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 17 deletions

View File

@ -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()`. 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 ## API :id=api
### `void spi_init(void)` :id=api-spi-init ### `void spi_init(void)` :id=api-spi-init

View File

@ -18,14 +18,14 @@
#include "timer.h" #include "timer.h"
static pin_t currentSlavePin = NO_PIN; static bool spiStarted = false;
#if defined(K20x) || defined(KL2x) || defined(RP2040) #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
static SPIConfig spiConfig = {NULL, 0, 0, 0}; static pin_t currentSlavePin;
#else
static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0};
#endif #endif
static SPIConfig spiConfig;
__attribute__((weak)) void spi_init(void) { __attribute__((weak)) void spi_init(void) {
static bool is_initialised = false; static bool is_initialised = false;
if (!is_initialised) { if (!is_initialised) {
@ -33,28 +33,45 @@ __attribute__((weak)) void spi_init(void) {
// Try releasing special pins for a short time // Try releasing special pins for a short time
setPinInput(SPI_SCK_PIN); setPinInput(SPI_SCK_PIN);
setPinInput(SPI_MOSI_PIN); if (SPI_MOSI_PIN != NO_PIN) {
setPinInput(SPI_MISO_PIN); setPinInput(SPI_MOSI_PIN);
}
if (SPI_MISO_PIN != NO_PIN) {
setPinInput(SPI_MISO_PIN);
}
chThdSleepMilliseconds(10); chThdSleepMilliseconds(10);
#if defined(USE_GPIOV1) #if defined(USE_GPIOV1)
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_PAL_MODE); 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); if (SPI_MOSI_PIN != NO_PIN) {
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE); 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 #else
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_FLAGS); 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); if (SPI_MOSI_PIN != NO_PIN) {
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_FLAGS); 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 #endif
spiStop(&SPI_DRIVER); spiStop(&SPI_DRIVER);
currentSlavePin = NO_PIN; spiStarted = false;
} }
} }
bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { 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; return false;
} }
#if SPI_SELECT_MODE != SPI_SELECT_MODE_NONE
if (slavePin == NO_PIN) {
return false;
}
#endif
#if !(defined(WB32F3G71xx) || defined(WB32FQ95xx)) #if !(defined(WB32F3G71xx) || defined(WB32FQ95xx))
uint16_t roundedDivisor = 2; uint16_t roundedDivisor = 2;
@ -247,13 +264,29 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
} }
#endif #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.ssport = PAL_PORT(slavePin);
spiConfig.sspad = PAL_PAD(slavePin); spiConfig.sspad = PAL_PAD(slavePin);
setPinOutput(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); spiStart(&SPI_DRIVER, &spiConfig);
spiSelect(&SPI_DRIVER); spiSelect(&SPI_DRIVER);
#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE
if (slavePin != NO_PIN) {
writePinLow(slavePin);
}
#endif
return true; return true;
} }
@ -283,9 +316,14 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) {
} }
void spi_stop(void) { 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); spiUnselect(&SPI_DRIVER);
spiStop(&SPI_DRIVER); spiStop(&SPI_DRIVER);
currentSlavePin = NO_PIN; spiStarted = false;
} }
} }