diff options
| author | Dasky <32983009+daskygit@users.noreply.github.com> | 2024-09-09 23:44:35 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-10 08:44:35 +1000 |
| commit | 2c7bf34d09247c2f306f0068e34a2a3a4f3f58e1 (patch) | |
| tree | 63052adc2c43f2e676bed9dc4957f961f3cb4eff /platforms/chibios | |
| parent | 3aaa086ac8a50ed7fc501c2dc93c1d195b63dcc3 (diff) | |
Allow for inverted SPI CS logic (#23699)
Diffstat (limited to 'platforms/chibios')
| -rw-r--r-- | platforms/chibios/drivers/spi_master.c | 96 | ||||
| -rw-r--r-- | platforms/chibios/drivers/spi_master.h | 9 |
2 files changed, 67 insertions, 38 deletions
diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c index fcdbc9ecf0..cbe765e233 100644 --- a/platforms/chibios/drivers/spi_master.c +++ b/platforms/chibios/drivers/spi_master.c | |||
| @@ -19,13 +19,33 @@ | |||
| 19 | #include "timer.h" | 19 | #include "timer.h" |
| 20 | 20 | ||
| 21 | static bool spiStarted = false; | 21 | static bool spiStarted = false; |
| 22 | |||
| 23 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE | 22 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE |
| 24 | static pin_t currentSlavePin; | 23 | static pin_t current_slave_pin = NO_PIN; |
| 24 | static bool current_cs_active_low = true; | ||
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| 27 | static SPIConfig spiConfig; | 27 | static SPIConfig spiConfig; |
| 28 | 28 | ||
| 29 | static inline void spi_select(void) { | ||
| 30 | spiSelect(&SPI_DRIVER); | ||
| 31 | |||
| 32 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE | ||
| 33 | if (current_slave_pin != NO_PIN) { | ||
| 34 | gpio_write_pin(current_slave_pin, current_cs_active_low ? 0 : 1); | ||
| 35 | } | ||
| 36 | #endif | ||
| 37 | } | ||
| 38 | |||
| 39 | static inline void spi_unselect(void) { | ||
| 40 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE | ||
| 41 | if (current_slave_pin != NO_PIN) { | ||
| 42 | gpio_write_pin(current_slave_pin, current_cs_active_low ? 1 : 0); | ||
| 43 | } | ||
| 44 | #endif | ||
| 45 | |||
| 46 | spiUnselect(&SPI_DRIVER); | ||
| 47 | } | ||
| 48 | |||
| 29 | __attribute__((weak)) void spi_init(void) { | 49 | __attribute__((weak)) void spi_init(void) { |
| 30 | static bool is_initialised = false; | 50 | static bool is_initialised = false; |
| 31 | if (!is_initialised) { | 51 | if (!is_initialised) { |
| @@ -63,7 +83,7 @@ __attribute__((weak)) void spi_init(void) { | |||
| 63 | } | 83 | } |
| 64 | } | 84 | } |
| 65 | 85 | ||
| 66 | bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | 86 | bool spi_start_extended(spi_start_config_t *start_config) { |
| 67 | #if (SPI_USE_MUTUAL_EXCLUSION == TRUE) | 87 | #if (SPI_USE_MUTUAL_EXCLUSION == TRUE) |
| 68 | spiAcquireBus(&SPI_DRIVER); | 88 | spiAcquireBus(&SPI_DRIVER); |
| 69 | #endif // (SPI_USE_MUTUAL_EXCLUSION == TRUE) | 89 | #endif // (SPI_USE_MUTUAL_EXCLUSION == TRUE) |
| @@ -71,16 +91,15 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | |||
| 71 | if (spiStarted) { | 91 | if (spiStarted) { |
| 72 | return false; | 92 | return false; |
| 73 | } | 93 | } |
| 74 | |||
| 75 | #if SPI_SELECT_MODE != SPI_SELECT_MODE_NONE | 94 | #if SPI_SELECT_MODE != SPI_SELECT_MODE_NONE |
| 76 | if (slavePin == NO_PIN) { | 95 | if (start_config->slave_pin == NO_PIN) { |
| 77 | return false; | 96 | return false; |
| 78 | } | 97 | } |
| 79 | #endif | 98 | #endif |
| 80 | 99 | ||
| 81 | #if !(defined(WB32F3G71xx) || defined(WB32FQ95xx)) | 100 | #if !(defined(WB32F3G71xx) || defined(WB32FQ95xx)) |
| 82 | uint16_t roundedDivisor = 2; | 101 | uint16_t roundedDivisor = 2; |
| 83 | while (roundedDivisor < divisor) { | 102 | while (roundedDivisor < start_config->divisor) { |
| 84 | roundedDivisor <<= 1; | 103 | roundedDivisor <<= 1; |
| 85 | } | 104 | } |
| 86 | 105 | ||
| @@ -92,11 +111,11 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | |||
| 92 | #if defined(K20x) || defined(KL2x) | 111 | #if defined(K20x) || defined(KL2x) |
| 93 | spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1); | 112 | spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1); |
| 94 | 113 | ||
| 95 | if (lsbFirst) { | 114 | if (start_config->lsb_first) { |
| 96 | spiConfig.tar0 |= SPIx_CTARn_LSBFE; | 115 | spiConfig.tar0 |= SPIx_CTARn_LSBFE; |
| 97 | } | 116 | } |
| 98 | 117 | ||
| 99 | switch (mode) { | 118 | switch (start_config->mode) { |
| 100 | case 0: | 119 | case 0: |
| 101 | break; | 120 | break; |
| 102 | case 1: | 121 | case 1: |
| @@ -141,11 +160,11 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | |||
| 141 | spiConfig.cr0 = SPI_CR0_SELOEN; | 160 | spiConfig.cr0 = SPI_CR0_SELOEN; |
| 142 | spiConfig.cr1 = SPI_CR1_MODE | 8; // 8 bits and in master mode | 161 | spiConfig.cr1 = SPI_CR1_MODE | 8; // 8 bits and in master mode |
| 143 | 162 | ||
| 144 | if (lsbFirst) { | 163 | if (start_config->lsb_first) { |
| 145 | spiConfig.cr1 |= SPI_CR1_FIRSTBIT; | 164 | spiConfig.cr1 |= SPI_CR1_FIRSTBIT; |
| 146 | } | 165 | } |
| 147 | 166 | ||
| 148 | switch (mode) { | 167 | switch (start_config->mode) { |
| 149 | case 0: | 168 | case 0: |
| 150 | spiConfig.cr1 |= SPI_CR1_FORMAT_MODE0; | 169 | spiConfig.cr1 |= SPI_CR1_FORMAT_MODE0; |
| 151 | break; | 170 | break; |
| @@ -163,17 +182,17 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | |||
| 163 | spiConfig.cpr = (roundedDivisor - 1) >> 1; | 182 | spiConfig.cpr = (roundedDivisor - 1) >> 1; |
| 164 | 183 | ||
| 165 | #elif defined(WB32F3G71xx) || defined(WB32FQ95xx) | 184 | #elif defined(WB32F3G71xx) || defined(WB32FQ95xx) |
| 166 | if (!lsbFirst) { | 185 | if (!start_config->lsb_first) { |
| 167 | osalDbgAssert(lsbFirst != FALSE, "unsupported lsbFirst"); | 186 | osalDbgAssert(start_config->lsb_first != FALSE, "unsupported lsb_first"); |
| 168 | } | 187 | } |
| 169 | 188 | ||
| 170 | if (divisor < 1) { | 189 | if (start_config->divisor < 1) { |
| 171 | return false; | 190 | return false; |
| 172 | } | 191 | } |
| 173 | 192 | ||
| 174 | spiConfig.SPI_BaudRatePrescaler = (divisor << 2); | 193 | spiConfig.SPI_BaudRatePrescaler = (start_config->divisor << 2); |
| 175 | 194 | ||
| 176 | switch (mode) { | 195 | switch (start_config->mode) { |
| 177 | case 0: | 196 | case 0: |
| 178 | spiConfig.SPI_CPHA = SPI_CPHA_1Edge; | 197 | spiConfig.SPI_CPHA = SPI_CPHA_1Edge; |
| 179 | spiConfig.SPI_CPOL = SPI_CPOL_Low; | 198 | spiConfig.SPI_CPOL = SPI_CPOL_Low; |
| @@ -192,8 +211,8 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | |||
| 192 | break; | 211 | break; |
| 193 | } | 212 | } |
| 194 | #elif defined(MCU_RP) | 213 | #elif defined(MCU_RP) |
| 195 | if (lsbFirst) { | 214 | if (start_config->lsb_first) { |
| 196 | osalDbgAssert(lsbFirst == false, "RP2040s PrimeCell SPI implementation does not support sending LSB first."); | 215 | osalDbgAssert(start_config->lsb_first == false, "RP2040s PrimeCell SPI implementation does not support sending LSB first."); |
| 197 | } | 216 | } |
| 198 | 217 | ||
| 199 | // Motorola frame format and 8bit transfer data size. | 218 | // Motorola frame format and 8bit transfer data size. |
| @@ -203,7 +222,7 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | |||
| 203 | // passed divisor to be the only value to divide the input clock by. | 222 | // passed divisor to be the only value to divide the input clock by. |
| 204 | spiConfig.SSPCPSR = roundedDivisor; // Even number from 2 to 254 | 223 | spiConfig.SSPCPSR = roundedDivisor; // Even number from 2 to 254 |
| 205 | 224 | ||
| 206 | switch (mode) { | 225 | switch (start_config->mode) { |
| 207 | case 0: | 226 | case 0: |
| 208 | spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPO; // Clock polarity: low | 227 | spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPO; // Clock polarity: low |
| 209 | spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPH; // Clock phase: sample on first edge | 228 | spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPH; // Clock phase: sample on first edge |
| @@ -224,11 +243,11 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | |||
| 224 | #else | 243 | #else |
| 225 | spiConfig.cr1 = 0; | 244 | spiConfig.cr1 = 0; |
| 226 | 245 | ||
| 227 | if (lsbFirst) { | 246 | if (start_config->lsb_first) { |
| 228 | spiConfig.cr1 |= SPI_CR1_LSBFIRST; | 247 | spiConfig.cr1 |= SPI_CR1_LSBFIRST; |
| 229 | } | 248 | } |
| 230 | 249 | ||
| 231 | switch (mode) { | 250 | switch (start_config->mode) { |
| 232 | case 0: | 251 | case 0: |
| 233 | break; | 252 | break; |
| 234 | case 1: | 253 | case 1: |
| @@ -271,31 +290,37 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | |||
| 271 | 290 | ||
| 272 | spiStarted = true; | 291 | spiStarted = true; |
| 273 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE | 292 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE |
| 274 | currentSlavePin = slavePin; | 293 | current_slave_pin = start_config->slave_pin; |
| 294 | current_cs_active_low = start_config->cs_active_low; | ||
| 275 | #endif | 295 | #endif |
| 276 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_PAD | 296 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_PAD |
| 277 | spiConfig.ssport = PAL_PORT(slavePin); | 297 | spiConfig.ssport = PAL_PORT(start_config->slave_pin); |
| 278 | spiConfig.sspad = PAL_PAD(slavePin); | 298 | spiConfig.sspad = PAL_PAD(start_config->slave_pin); |
| 279 | gpio_set_pin_output(slavePin); | 299 | gpio_set_pin_output(start_config->slave_pin); |
| 280 | #elif SPI_SELECT_MODE == SPI_SELECT_MODE_NONE | 300 | #elif SPI_SELECT_MODE == SPI_SELECT_MODE_NONE |
| 281 | if (slavePin != NO_PIN) { | 301 | if (start_config->slave_pin != NO_PIN) { |
| 282 | gpio_set_pin_output(slavePin); | 302 | gpio_set_pin_output(start_config->slave_pin); |
| 283 | } | 303 | } |
| 284 | #else | 304 | #else |
| 285 | # error "Unsupported SPI_SELECT_MODE" | 305 | # error "Unsupported SPI_SELECT_MODE" |
| 286 | #endif | 306 | #endif |
| 287 | 307 | ||
| 288 | spiStart(&SPI_DRIVER, &spiConfig); | 308 | spiStart(&SPI_DRIVER, &spiConfig); |
| 289 | spiSelect(&SPI_DRIVER); | 309 | spi_select(); |
| 290 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE | ||
| 291 | if (slavePin != NO_PIN) { | ||
| 292 | gpio_write_pin_low(slavePin); | ||
| 293 | } | ||
| 294 | #endif | ||
| 295 | 310 | ||
| 296 | return true; | 311 | return true; |
| 297 | } | 312 | } |
| 298 | 313 | ||
| 314 | bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | ||
| 315 | spi_start_config_t start_config = {0}; | ||
| 316 | start_config.slave_pin = slavePin; | ||
| 317 | start_config.lsb_first = lsbFirst; | ||
| 318 | start_config.mode = mode; | ||
| 319 | start_config.divisor = divisor; | ||
| 320 | start_config.cs_active_low = true; | ||
| 321 | return spi_start_extended(&start_config); | ||
| 322 | } | ||
| 323 | |||
| 299 | spi_status_t spi_write(uint8_t data) { | 324 | spi_status_t spi_write(uint8_t data) { |
| 300 | uint8_t rxData; | 325 | uint8_t rxData; |
| 301 | spiExchange(&SPI_DRIVER, 1, &data, &rxData); | 326 | spiExchange(&SPI_DRIVER, 1, &data, &rxData); |
| @@ -322,12 +347,7 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) { | |||
| 322 | 347 | ||
| 323 | void spi_stop(void) { | 348 | void spi_stop(void) { |
| 324 | if (spiStarted) { | 349 | if (spiStarted) { |
| 325 | #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE | 350 | spi_unselect(); |
| 326 | if (currentSlavePin != NO_PIN) { | ||
| 327 | gpio_write_pin_high(currentSlavePin); | ||
| 328 | } | ||
| 329 | #endif | ||
| 330 | spiUnselect(&SPI_DRIVER); | ||
| 331 | spiStop(&SPI_DRIVER); | 351 | spiStop(&SPI_DRIVER); |
| 332 | spiStarted = false; | 352 | spiStarted = false; |
| 333 | } | 353 | } |
diff --git a/platforms/chibios/drivers/spi_master.h b/platforms/chibios/drivers/spi_master.h index 6a3ce481f1..4ad6144091 100644 --- a/platforms/chibios/drivers/spi_master.h +++ b/platforms/chibios/drivers/spi_master.h | |||
| @@ -75,9 +75,18 @@ typedef int16_t spi_status_t; | |||
| 75 | #ifdef __cplusplus | 75 | #ifdef __cplusplus |
| 76 | extern "C" { | 76 | extern "C" { |
| 77 | #endif | 77 | #endif |
| 78 | typedef struct spi_start_config_t { | ||
| 79 | pin_t slave_pin; | ||
| 80 | bool lsb_first; | ||
| 81 | uint8_t mode; | ||
| 82 | uint16_t divisor; | ||
| 83 | bool cs_active_low; | ||
| 84 | } spi_start_config_t; | ||
| 85 | |||
| 78 | void spi_init(void); | 86 | void spi_init(void); |
| 79 | 87 | ||
| 80 | bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); | 88 | bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); |
| 89 | bool spi_start_extended(spi_start_config_t *start_config); | ||
| 81 | 90 | ||
| 82 | spi_status_t spi_write(uint8_t data); | 91 | spi_status_t spi_write(uint8_t data); |
| 83 | 92 | ||
