From aeca9a52c6bd8361db24128aaa39133c6b82360c Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Thu, 15 Feb 2024 18:42:30 +0100 Subject: [PATCH] cpu/stm32: implement periph_spi_reconfigure Fixes https://github.com/RIOT-OS/RIOT/issues/20227 --- cpu/stm32/Makefile.features | 11 ++++--- cpu/stm32/include/periph/cpu_spi.h | 12 +++++++ cpu/stm32/periph/spi.c | 53 ++++++++++++++++++++++++++---- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/cpu/stm32/Makefile.features b/cpu/stm32/Makefile.features index 314e36380a..4757210cf3 100644 --- a/cpu/stm32/Makefile.features +++ b/cpu/stm32/Makefile.features @@ -7,11 +7,6 @@ endif FEATURES_PROVIDED += cpu_stm32$(CPU_FAM) FEATURES_PROVIDED += periph_cpuid FEATURES_PROVIDED += periph_gpio periph_gpio_irq -FEATURES_PROVIDED += periph_timer_periodic -FEATURES_PROVIDED += periph_timer_query_freqs -FEATURES_PROVIDED += periph_rtt_overflow -FEATURES_PROVIDED += periph_uart_modecfg -FEATURES_PROVIDED += periph_uart_nonblocking FEATURES_PROVIDED += periph_gpio_ll FEATURES_PROVIDED += periph_gpio_ll_disconnect FEATURES_PROVIDED += periph_gpio_ll_input_pull_down @@ -20,6 +15,12 @@ FEATURES_PROVIDED += periph_gpio_ll_irq FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_high FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_low FEATURES_PROVIDED += periph_gpio_ll_open_drain +FEATURES_PROVIDED += periph_rtt_overflow +FEATURES_PROVIDED += periph_spi_reconfigure +FEATURES_PROVIDED += periph_timer_periodic +FEATURES_PROVIDED += periph_timer_query_freqs +FEATURES_PROVIDED += periph_uart_modecfg +FEATURES_PROVIDED += periph_uart_nonblocking ifneq (f1,$(CPU_FAM)) FEATURES_PROVIDED += periph_gpio_ll_open_drain_pull_up diff --git a/cpu/stm32/include/periph/cpu_spi.h b/cpu/stm32/include/periph/cpu_spi.h index 2ead5233e0..5d8c1a675d 100644 --- a/cpu/stm32/include/periph/cpu_spi.h +++ b/cpu/stm32/include/periph/cpu_spi.h @@ -32,6 +32,12 @@ extern "C" { #endif +#ifndef DOXYGEN +/* resolve circular dependency by declaring spi_t here */ +#define HAVE_SPI_T +typedef uint_fast8_t spi_t; +#endif + /** * @brief Define a magic number that tells us to use hardware chip select * @@ -119,6 +125,12 @@ typedef struct { #endif } spi_conf_t; +#ifndef DOXYGEN +gpio_t spi_pin_miso(spi_t bus); +gpio_t spi_pin_mosi(spi_t bus); +gpio_t spi_pin_clk(spi_t bus); +#endif + #ifdef __cplusplus } #endif diff --git a/cpu/stm32/periph/spi.c b/cpu/stm32/periph/spi.c index 408243b1c1..d5ee2edd0e 100644 --- a/cpu/stm32/periph/spi.c +++ b/cpu/stm32/periph/spi.c @@ -28,6 +28,7 @@ #include +#include "compiler_hints.h" #include "mutex.h" #include "periph/gpio.h" #include "periph/spi.h" @@ -94,17 +95,17 @@ static uint8_t _get_prescaler(const spi_conf_t *conf, uint32_t clock) * happen if this cannot be met. So let's have a blown assertion * rather than runtime failures that require a logic analyzer to * debug. */ - assert(prescaled_clock <= clock); + assume(prescaled_clock <= clock); return prescaler; } void spi_init(spi_t bus) { - assert(bus < SPI_NUMOF); + assume(bus < SPI_NUMOF); - /* initialize device lock */ - mutex_init(&locks[bus]); + /* initialize device lock (as locked, spi_init_pins() will unlock it */ + locks[bus] = (mutex_t)MUTEX_INIT_LOCKED; /* trigger pin initialization */ spi_init_pins(bus); @@ -120,6 +121,7 @@ void spi_init(spi_t bus) void spi_init_pins(spi_t bus) { + assume(bus < SPI_NUMOF); #ifdef CPU_FAM_STM32F1 if (gpio_is_valid(spi_config[bus].sclk_pin)) { @@ -149,6 +151,43 @@ void spi_init_pins(spi_t bus) gpio_init_af(spi_config[bus].sclk_pin, spi_config[bus].sclk_af); } #endif + mutex_unlock(&locks[bus]); +} + +void spi_deinit_pins(spi_t bus) +{ + assume(bus < SPI_NUMOF); + mutex_lock(&locks[bus]); + + if (gpio_is_valid(spi_config[bus].sclk_pin)) { + gpio_init(spi_config[bus].sclk_pin, GPIO_IN); + } + + if (gpio_is_valid(spi_config[bus].mosi_pin)) { + gpio_init(spi_config[bus].mosi_pin, GPIO_IN); + } + + if (gpio_is_valid(spi_config[bus].miso_pin)) { + gpio_init(spi_config[bus].miso_pin, GPIO_IN); + } +} + +gpio_t spi_pin_miso(spi_t bus) +{ + assume(bus < SPI_NUMOF); + return spi_config[bus].miso_pin; +} + +gpio_t spi_pin_mosi(spi_t bus) +{ + assume(bus < SPI_NUMOF); + return spi_config[bus].mosi_pin; +} + +gpio_t spi_pin_clk(spi_t bus) +{ + assume(bus < SPI_NUMOF); + return spi_config[bus].sclk_pin; } int spi_init_cs(spi_t bus, spi_cs_t cs) @@ -183,7 +222,7 @@ int spi_init_cs(spi_t bus, spi_cs_t cs) #ifdef MODULE_PERIPH_SPI_GPIO_MODE int spi_init_with_gpio_mode(spi_t bus, const spi_gpio_mode_t* mode) { - assert(bus < SPI_NUMOF); + assume(bus < SPI_NUMOF); int ret = 0; @@ -212,7 +251,7 @@ int spi_init_with_gpio_mode(spi_t bus, const spi_gpio_mode_t* mode) void spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) { - assert((unsigned)bus < SPI_NUMOF); + assume((unsigned)bus < SPI_NUMOF); /* lock bus */ mutex_lock(&locks[bus]); @@ -379,7 +418,7 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, const void *out, void *in, size_t len) { /* make sure at least one input or one output buffer is given */ - assert(out || in); + assume(out || in); /* active the given chip select line */ if ((cs != SPI_HWCS_MASK) && gpio_is_valid(cs)) {