diff --git a/platforms/avr/drivers/spi_master.c b/platforms/avr/drivers/spi_master.c index 74b847c71a..ba7d782ab0 100644 --- a/platforms/avr/drivers/spi_master.c +++ b/platforms/avr/drivers/spi_master.c @@ -36,9 +36,18 @@ # define SPI_TIMEOUT 100 #endif -static pin_t currentSlavePin = NO_PIN; -static uint8_t currentSlaveConfig = 0; -static bool currentSlave2X = false; +static pin_t current_slave_pin = NO_PIN; +static bool current_cs_active_low = true; +static uint8_t current_slave_config = 0; +static bool current_slave_2x = false; + +static inline void spi_select(void) { + gpio_write_pin(current_slave_pin, current_cs_active_low ? 0 : 1); +} + +static inline void spi_unselect(void) { + gpio_write_pin(current_slave_pin, current_cs_active_low ? 1 : 0); +} void spi_init(void) { gpio_write_pin_high(SPI_SS_PIN); @@ -50,63 +59,74 @@ void spi_init(void) { } bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { - if (currentSlavePin != NO_PIN || slavePin == NO_PIN) { + spi_start_config_t start_config = {0}; + start_config.slave_pin = slavePin; + start_config.lsb_first = lsbFirst; + start_config.mode = mode; + start_config.divisor = divisor; + start_config.cs_active_low = true; + return spi_start_extended(&start_config); +} + +bool spi_start_extended(spi_start_config_t *start_config) { + if (current_slave_pin != NO_PIN || start_config->slave_pin == NO_PIN) { return false; } - currentSlaveConfig = 0; + current_slave_config = 0; - if (lsbFirst) { - currentSlaveConfig |= _BV(DORD); + if (start_config->lsb_first) { + current_slave_config |= _BV(DORD); } - switch (mode) { + switch (start_config->mode) { case 1: - currentSlaveConfig |= _BV(CPHA); + current_slave_config |= _BV(CPHA); break; case 2: - currentSlaveConfig |= _BV(CPOL); + current_slave_config |= _BV(CPOL); break; case 3: - currentSlaveConfig |= (_BV(CPOL) | _BV(CPHA)); + current_slave_config |= (_BV(CPOL) | _BV(CPHA)); break; } uint16_t roundedDivisor = 1; - while (roundedDivisor < divisor) { + while (roundedDivisor < start_config->divisor) { roundedDivisor <<= 1; } switch (roundedDivisor) { case 16: - currentSlaveConfig |= _BV(SPR0); + current_slave_config |= _BV(SPR0); break; case 64: - currentSlaveConfig |= _BV(SPR1); + current_slave_config |= _BV(SPR1); break; case 128: - currentSlaveConfig |= (_BV(SPR1) | _BV(SPR0)); + current_slave_config |= (_BV(SPR1) | _BV(SPR0)); break; case 2: - currentSlave2X = true; + current_slave_2x = true; break; case 8: - currentSlave2X = true; - currentSlaveConfig |= _BV(SPR0); + current_slave_2x = true; + current_slave_config |= _BV(SPR0); break; case 32: - currentSlave2X = true; - currentSlaveConfig |= _BV(SPR1); + current_slave_2x = true; + current_slave_config |= _BV(SPR1); break; } - SPCR |= currentSlaveConfig; - if (currentSlave2X) { + SPCR |= current_slave_config; + if (current_slave_2x) { SPSR |= _BV(SPI2X); } - currentSlavePin = slavePin; - gpio_set_pin_output(currentSlavePin); - gpio_write_pin_low(currentSlavePin); + current_slave_pin = start_config->slave_pin; + current_cs_active_low = start_config->cs_active_low; + gpio_set_pin_output(current_slave_pin); + spi_select(); return true; } @@ -168,13 +188,13 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) { } void spi_stop(void) { - if (currentSlavePin != NO_PIN) { - gpio_set_pin_output(currentSlavePin); - gpio_write_pin_high(currentSlavePin); - currentSlavePin = NO_PIN; + if (current_slave_pin != NO_PIN) { + gpio_set_pin_output(current_slave_pin); + spi_unselect(); + current_slave_pin = NO_PIN; SPSR &= ~(_BV(SPI2X)); - SPCR &= ~(currentSlaveConfig); - currentSlaveConfig = 0; - currentSlave2X = false; + SPCR &= ~(current_slave_config); + current_slave_config = 0; + current_slave_2x = false; } } diff --git a/platforms/avr/drivers/spi_master.h b/platforms/avr/drivers/spi_master.h index 8a30f47ae4..ebbf7ddeab 100644 --- a/platforms/avr/drivers/spi_master.h +++ b/platforms/avr/drivers/spi_master.h @@ -41,9 +41,18 @@ typedef int16_t spi_status_t; #ifdef __cplusplus extern "C" { #endif +typedef struct spi_start_config_t { + pin_t slave_pin; + bool lsb_first; + uint8_t mode; + uint16_t divisor; + bool cs_active_low; +} spi_start_config_t; + void spi_init(void); bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); +bool spi_start_extended(spi_start_config_t *start_config); spi_status_t spi_write(uint8_t data); 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 @@ #include "timer.h" static bool spiStarted = false; - #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE -static pin_t currentSlavePin; +static pin_t current_slave_pin = NO_PIN; +static bool current_cs_active_low = true; #endif static SPIConfig spiConfig; +static inline void spi_select(void) { + spiSelect(&SPI_DRIVER); + +#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE + if (current_slave_pin != NO_PIN) { + gpio_write_pin(current_slave_pin, current_cs_active_low ? 0 : 1); + } +#endif +} + +static inline void spi_unselect(void) { +#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE + if (current_slave_pin != NO_PIN) { + gpio_write_pin(current_slave_pin, current_cs_active_low ? 1 : 0); + } +#endif + + spiUnselect(&SPI_DRIVER); +} + __attribute__((weak)) void spi_init(void) { static bool is_initialised = false; if (!is_initialised) { @@ -63,7 +83,7 @@ __attribute__((weak)) void spi_init(void) { } } -bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { +bool spi_start_extended(spi_start_config_t *start_config) { #if (SPI_USE_MUTUAL_EXCLUSION == TRUE) spiAcquireBus(&SPI_DRIVER); #endif // (SPI_USE_MUTUAL_EXCLUSION == TRUE) @@ -71,16 +91,15 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { if (spiStarted) { return false; } - #if SPI_SELECT_MODE != SPI_SELECT_MODE_NONE - if (slavePin == NO_PIN) { + if (start_config->slave_pin == NO_PIN) { return false; } #endif #if !(defined(WB32F3G71xx) || defined(WB32FQ95xx)) uint16_t roundedDivisor = 2; - while (roundedDivisor < divisor) { + while (roundedDivisor < start_config->divisor) { roundedDivisor <<= 1; } @@ -92,11 +111,11 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { #if defined(K20x) || defined(KL2x) spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1); - if (lsbFirst) { + if (start_config->lsb_first) { spiConfig.tar0 |= SPIx_CTARn_LSBFE; } - switch (mode) { + switch (start_config->mode) { case 0: break; case 1: @@ -141,11 +160,11 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { spiConfig.cr0 = SPI_CR0_SELOEN; spiConfig.cr1 = SPI_CR1_MODE | 8; // 8 bits and in master mode - if (lsbFirst) { + if (start_config->lsb_first) { spiConfig.cr1 |= SPI_CR1_FIRSTBIT; } - switch (mode) { + switch (start_config->mode) { case 0: spiConfig.cr1 |= SPI_CR1_FORMAT_MODE0; break; @@ -163,17 +182,17 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { spiConfig.cpr = (roundedDivisor - 1) >> 1; #elif defined(WB32F3G71xx) || defined(WB32FQ95xx) - if (!lsbFirst) { - osalDbgAssert(lsbFirst != FALSE, "unsupported lsbFirst"); + if (!start_config->lsb_first) { + osalDbgAssert(start_config->lsb_first != FALSE, "unsupported lsb_first"); } - if (divisor < 1) { + if (start_config->divisor < 1) { return false; } - spiConfig.SPI_BaudRatePrescaler = (divisor << 2); + spiConfig.SPI_BaudRatePrescaler = (start_config->divisor << 2); - switch (mode) { + switch (start_config->mode) { case 0: spiConfig.SPI_CPHA = SPI_CPHA_1Edge; spiConfig.SPI_CPOL = SPI_CPOL_Low; @@ -192,8 +211,8 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { break; } #elif defined(MCU_RP) - if (lsbFirst) { - osalDbgAssert(lsbFirst == false, "RP2040s PrimeCell SPI implementation does not support sending LSB first."); + if (start_config->lsb_first) { + osalDbgAssert(start_config->lsb_first == false, "RP2040s PrimeCell SPI implementation does not support sending LSB first."); } // 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) { // passed divisor to be the only value to divide the input clock by. spiConfig.SSPCPSR = roundedDivisor; // Even number from 2 to 254 - switch (mode) { + switch (start_config->mode) { case 0: spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPO; // Clock polarity: low 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) { #else spiConfig.cr1 = 0; - if (lsbFirst) { + if (start_config->lsb_first) { spiConfig.cr1 |= SPI_CR1_LSBFIRST; } - switch (mode) { + switch (start_config->mode) { case 0: break; case 1: @@ -271,31 +290,37 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { spiStarted = true; #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE - currentSlavePin = slavePin; + current_slave_pin = start_config->slave_pin; + current_cs_active_low = start_config->cs_active_low; #endif #if SPI_SELECT_MODE == SPI_SELECT_MODE_PAD - spiConfig.ssport = PAL_PORT(slavePin); - spiConfig.sspad = PAL_PAD(slavePin); - gpio_set_pin_output(slavePin); + spiConfig.ssport = PAL_PORT(start_config->slave_pin); + spiConfig.sspad = PAL_PAD(start_config->slave_pin); + gpio_set_pin_output(start_config->slave_pin); #elif SPI_SELECT_MODE == SPI_SELECT_MODE_NONE - if (slavePin != NO_PIN) { - gpio_set_pin_output(slavePin); + if (start_config->slave_pin != NO_PIN) { + gpio_set_pin_output(start_config->slave_pin); } #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) { - gpio_write_pin_low(slavePin); - } -#endif + spi_select(); return true; } +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { + spi_start_config_t start_config = {0}; + start_config.slave_pin = slavePin; + start_config.lsb_first = lsbFirst; + start_config.mode = mode; + start_config.divisor = divisor; + start_config.cs_active_low = true; + return spi_start_extended(&start_config); +} + spi_status_t spi_write(uint8_t data) { uint8_t rxData; spiExchange(&SPI_DRIVER, 1, &data, &rxData); @@ -322,12 +347,7 @@ spi_status_t spi_receive(uint8_t *data, uint16_t length) { void spi_stop(void) { if (spiStarted) { -#if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE - if (currentSlavePin != NO_PIN) { - gpio_write_pin_high(currentSlavePin); - } -#endif - spiUnselect(&SPI_DRIVER); + spi_unselect(); spiStop(&SPI_DRIVER); spiStarted = false; } 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; #ifdef __cplusplus extern "C" { #endif +typedef struct spi_start_config_t { + pin_t slave_pin; + bool lsb_first; + uint8_t mode; + uint16_t divisor; + bool cs_active_low; +} spi_start_config_t; + void spi_init(void); bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); +bool spi_start_extended(spi_start_config_t *start_config); spi_status_t spi_write(uint8_t data);