From 7031202e7c2c7f96eb351399f629d718e7733388 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sat, 31 Aug 2019 19:51:51 -0400 Subject: [PATCH] stm32: Add support for SPI1 and SPI3 busses Signed-off-by: Kevin O'Connor --- src/stm32/gpio.h | 2 +- src/stm32/spi.c | 46 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/stm32/gpio.h b/src/stm32/gpio.h index 0fe17596..13ab74bd 100644 --- a/src/stm32/gpio.h +++ b/src/stm32/gpio.h @@ -31,7 +31,7 @@ uint16_t gpio_adc_read(struct gpio_adc g); void gpio_adc_cancel_sample(struct gpio_adc g); struct spi_config { - void *spidev; + void *spi; uint32_t spi_cr1; }; struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate); diff --git a/src/stm32/spi.c b/src/stm32/spi.c index 77072958..c5e36022 100644 --- a/src/stm32/spi.c +++ b/src/stm32/spi.c @@ -9,49 +9,71 @@ #include "internal.h" // gpio_peripheral #include "sched.h" // sched_shutdown +struct spi_info { + void *spi; + uint8_t miso_pin, mosi_pin, sck_pin, function; +}; + DECL_ENUMERATION("spi_bus", "spi2", 0); DECL_CONSTANT_STR("BUS_PINS_spi2", "PB14,PB15,PB13"); +DECL_ENUMERATION("spi_bus", "spi1", 1); +DECL_CONSTANT_STR("BUS_PINS_spi1", "PA6,PA7,PA5"); +#ifdef SPI3 +DECL_ENUMERATION("spi_bus", "spi3", 2); +DECL_CONSTANT_STR("BUS_PINS_spi3", "PB4,PB5,PB3"); +#endif + +static const struct spi_info spi_bus[] = { + { SPI2, GPIO('B', 14), GPIO('B', 15), GPIO('B', 13), GPIO_FUNCTION(5) }, + { SPI1, GPIO('A', 6), GPIO('A', 7), GPIO('A', 5), GPIO_FUNCTION(5) }, +#ifdef SPI3 + { SPI3, GPIO('B', 4), GPIO('B', 5), GPIO('B', 3), GPIO_FUNCTION(6) }, +#endif +}; struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate) { - if (bus) + if (bus >= ARRAY_SIZE(spi_bus)) shutdown("Invalid spi bus"); // Enable SPI - if (!is_enabled_pclock(SPI2_BASE)) { - enable_pclock(SPI2_BASE); - gpio_peripheral(GPIO('B', 14), GPIO_FUNCTION(5), 1); - gpio_peripheral(GPIO('B', 15), GPIO_FUNCTION(5), 0); - gpio_peripheral(GPIO('B', 13), GPIO_FUNCTION(5), 0); + SPI_TypeDef *spi = spi_bus[bus].spi; + if (!is_enabled_pclock((uint32_t)spi)) { + enable_pclock((uint32_t)spi); + gpio_peripheral(spi_bus[bus].miso_pin, spi_bus[bus].function, 1); + gpio_peripheral(spi_bus[bus].mosi_pin, spi_bus[bus].function, 0); + gpio_peripheral(spi_bus[bus].sck_pin, spi_bus[bus].function, 0); } // Calculate CR1 register - uint32_t pclk = get_pclock_frequency(SPI2_BASE); + uint32_t pclk = get_pclock_frequency((uint32_t)spi); uint32_t div = 0; while ((pclk >> (div + 1)) > rate && div < 7) div++; uint32_t cr1 = ((mode << SPI_CR1_CPHA_Pos) | (div << SPI_CR1_BR_Pos) | SPI_CR1_SPE | SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI); - return (struct spi_config){ .spi_cr1 = cr1 }; + return (struct spi_config){ .spi = spi, .spi_cr1 = cr1 }; } void spi_prepare(struct spi_config config) { - SPI2->CR1 = config.spi_cr1; + SPI_TypeDef *spi = config.spi; + spi->CR1 = config.spi_cr1; } void spi_transfer(struct spi_config config, uint8_t receive_data, uint8_t len, uint8_t *data) { + SPI_TypeDef *spi = config.spi; while (len--) { - SPI2->DR = *data; - while (!(SPI2->SR & SPI_SR_RXNE)) + spi->DR = *data; + while (!(spi->SR & SPI_SR_RXNE)) ; - uint8_t rdata = SPI2->DR; + uint8_t rdata = spi->DR; if (receive_data) *data = rdata; data++;