Browse Source

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>
Purdea Andrei 2 years ago
parent
commit
408d61dcfb
2 changed files with 60 additions and 17 deletions
  1. 5 0
      docs/spi_driver.md
  2. 55 17
      platforms/chibios/drivers/spi_master.c

+ 5 - 0
docs/spi_driver.md

@@ -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

+ 55 - 17
platforms/chibios/drivers/spi_master.c

@@ -18,14 +18,14 @@
 
 #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) {
@@ -33,28 +33,45 @@ __attribute__((weak)) void spi_init(void) {
 
         // 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;
@@ -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;
 }
@@ -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;
     }
 }