From 00ef3941a143891ac0145e174f660fe610ef541c Mon Sep 17 00:00:00 2001 From: Yannis Damigos Date: Wed, 13 Dec 2017 13:46:27 +0200 Subject: [PATCH 1/3] drivers: spi_ll_stm32: Enable SPI driver for F1 family Enables SPI driver for STM32F1 SoCs Signed-off-by: Yannis Damigos --- arch/arm/soc/st_stm32/stm32f1/soc.h | 4 ++ drivers/pinmux/stm32/pinmux_stm32f1.h | 62 ++++++++++++------- drivers/spi/Kconfig | 1 - drivers/spi/spi_ll_stm32.c | 14 ++++- include/dt-bindings/pinctrl/stm32-pinctrlf1.h | 33 ++++++++-- 5 files changed, 86 insertions(+), 28 deletions(-) diff --git a/arch/arm/soc/st_stm32/stm32f1/soc.h b/arch/arm/soc/st_stm32/stm32f1/soc.h index bb892ab87040e..9f8f49f58c72c 100644 --- a/arch/arm/soc/st_stm32/stm32f1/soc.h +++ b/arch/arm/soc/st_stm32/stm32f1/soc.h @@ -48,6 +48,10 @@ #include #endif +#ifdef CONFIG_SPI_STM32 +#include +#endif + #ifdef CONFIG_IWDG_STM32 #include #endif diff --git a/drivers/pinmux/stm32/pinmux_stm32f1.h b/drivers/pinmux/stm32/pinmux_stm32f1.h index 3de1fb7a2be6b..bf6c0dd74e6f3 100644 --- a/drivers/pinmux/stm32/pinmux_stm32f1.h +++ b/drivers/pinmux/stm32/pinmux_stm32f1.h @@ -11,26 +11,46 @@ * @file Header for STM32F1 pin multiplexing helper */ -#define STM32F1_PINMUX_FUNC_PA9_USART1_TX STM32_PIN_USART_TX -#define STM32F1_PINMUX_FUNC_PA10_USART1_RX STM32_PIN_USART_RX - -#define STM32F1_PINMUX_FUNC_PA2_USART2_TX STM32_PIN_USART_TX -#define STM32F1_PINMUX_FUNC_PA3_USART2_RX STM32_PIN_USART_RX - -#define STM32F1_PINMUX_FUNC_PD5_USART2_TX STM32_PIN_USART_TX -#define STM32F1_PINMUX_FUNC_PD6_USART2_RX STM32_PIN_USART_RX - -#define STM32F1_PINMUX_FUNC_PB6_I2C1_SCL STM32_PIN_I2C -#define STM32F1_PINMUX_FUNC_PB7_I2C1_SDA STM32_PIN_I2C -#define STM32F1_PINMUX_FUNC_PB8_I2C1_SCL STM32_PIN_I2C -#define STM32F1_PINMUX_FUNC_PB9_I2C1_SDA STM32_PIN_I2C - -#define STM32F1_PINMUX_FUNC_PB10_USART3_TX STM32_PIN_USART_TX -#define STM32F1_PINMUX_FUNC_PB11_USART3_RX STM32_PIN_USART_RX - -#define STM32F1_PINMUX_FUNC_PB10_I2C2_SCL STM32_PIN_I2C -#define STM32F1_PINMUX_FUNC_PB11_I2C2_SDA STM32_PIN_I2C - -#define STM32F1_PINMUX_FUNC_PA8_PWM1_CH1 STM32_PIN_PWM +#define STM32F1_PINMUX_FUNC_PA9_USART1_TX STM32_PIN_USART_TX +#define STM32F1_PINMUX_FUNC_PA10_USART1_RX STM32_PIN_USART_RX + +#define STM32F1_PINMUX_FUNC_PA2_USART2_TX STM32_PIN_USART_TX +#define STM32F1_PINMUX_FUNC_PA3_USART2_RX STM32_PIN_USART_RX + +#define STM32F1_PINMUX_FUNC_PA4_SPI1_MASTER_NSS STM32_PIN_SPI_MASTER_NSS +#define STM32F1_PINMUX_FUNC_PA4_SPI1_MASTER_NSS_OE STM32_PIN_SPI_MASTER_NSS_OE +#define STM32F1_PINMUX_FUNC_PA4_SPI1_SLAVE_NSS STM32_PIN_SPI_SLAVE_NSS +#define STM32F1_PINMUX_FUNC_PA5_SPI1_MASTER_SCK STM32_PIN_SPI_MASTER_SCK +#define STM32F1_PINMUX_FUNC_PA5_SPI1_SLAVE_SCK STM32_PIN_SPI_SLAVE_SCK +#define STM32F1_PINMUX_FUNC_PA6_SPI1_MASTER_MISO STM32_PIN_SPI_MASTER_MISO +#define STM32F1_PINMUX_FUNC_PA6_SPI1_SLAVE_MISO STM32_PIN_SPI_SLAVE_MISO +#define STM32F1_PINMUX_FUNC_PA7_SPI1_MASTER_MOSI STM32_PIN_SPI_MASTER_MOSI +#define STM32F1_PINMUX_FUNC_PA7_SPI1_SLAVE_MOSI STM32_PIN_SPI_SLAVE_MOSI + +#define STM32F1_PINMUX_FUNC_PD5_USART2_TX STM32_PIN_USART_TX +#define STM32F1_PINMUX_FUNC_PD6_USART2_RX STM32_PIN_USART_RX + +#define STM32F1_PINMUX_FUNC_PB6_I2C1_SCL STM32_PIN_I2C +#define STM32F1_PINMUX_FUNC_PB7_I2C1_SDA STM32_PIN_I2C +#define STM32F1_PINMUX_FUNC_PB8_I2C1_SCL STM32_PIN_I2C +#define STM32F1_PINMUX_FUNC_PB9_I2C1_SDA STM32_PIN_I2C + +#define STM32F1_PINMUX_FUNC_PB10_USART3_TX STM32_PIN_USART_TX +#define STM32F1_PINMUX_FUNC_PB11_USART3_RX STM32_PIN_USART_RX + +#define STM32F1_PINMUX_FUNC_PB10_I2C2_SCL STM32_PIN_I2C +#define STM32F1_PINMUX_FUNC_PB11_I2C2_SDA STM32_PIN_I2C + +#define STM32F1_PINMUX_FUNC_PB12_SPI2_MASTER_NSS STM32_PIN_SPI_MASTER_NSS +#define STM32F1_PINMUX_FUNC_PB12_SPI2_MASTER_NSS_OE STM32_PIN_SPI_MASTER_NSS_OE +#define STM32F1_PINMUX_FUNC_PB12_SPI2_SLAVE_NSS STM32_PIN_SPI_SLAVE_NSS +#define STM32F1_PINMUX_FUNC_PB13_SPI2_MASTER_SCK STM32_PIN_SPI_MASTER_SCK +#define STM32F1_PINMUX_FUNC_PB13_SPI2_SLAVE_SCK STM32_PIN_SPI_SLAVE_SCK +#define STM32F1_PINMUX_FUNC_PB14_SPI2_MASTER_MISO STM32_PIN_SPI_MASTER_MISO +#define STM32F1_PINMUX_FUNC_PB14_SPI2_SLAVE_MISO STM32_PIN_SPI_SLAVE_MISO +#define STM32F1_PINMUX_FUNC_PB15_SPI2_MASTER_MOSI STM32_PIN_SPI_MASTER_MOSI +#define STM32F1_PINMUX_FUNC_PB15_SPI2_SLAVE_MOSI STM32_PIN_SPI_SLAVE_MOSI + +#define STM32F1_PINMUX_FUNC_PA8_PWM1_CH1 STM32_PIN_PWM #endif /* _STM32F1_PINMUX_H_ */ diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b95d0f323aaed..3bc0fc784667c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -54,7 +54,6 @@ config SPI_STM32 bool prompt "STM32 MCU SPI controller driver" depends on SPI && SOC_FAMILY_STM32 - depends on SOC_SERIES_STM32L4X || SOC_SERIES_STM32F0X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32F4X select HAS_DTS_SPI select USE_STM32_LL_SPI default n diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index afd9acbd00b69..ff7eb8d7d1927 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -25,12 +25,19 @@ #define CONFIG_DATA(cfg) \ ((struct spi_stm32_data * const)(cfg)->dev->driver_data) -#ifdef LL_SPI_SR_UDR +/* + * Check for SPI_SR_FRE to determine support for TI mode frame format + * error flag, because STM32F1 SoCs do not support it and STM32CUBE + * for F1 family defines an unused LL_SPI_SR_FRE. + */ +#if defined(LL_SPI_SR_UDR) #define SPI_STM32_ERR_MSK (LL_SPI_SR_UDR | LL_SPI_SR_CRCERR | LL_SPI_SR_MODF | \ LL_SPI_SR_OVR | LL_SPI_SR_FRE) -#else +#elif defined(SPI_SR_FRE) #define SPI_STM32_ERR_MSK (LL_SPI_SR_CRCERR | LL_SPI_SR_MODF | \ LL_SPI_SR_OVR | LL_SPI_SR_FRE) +#else +#define SPI_STM32_ERR_MSK (LL_SPI_SR_CRCERR | LL_SPI_SR_MODF | LL_SPI_SR_OVR) #endif /* Value to shift out when no application data needs transmitting. */ @@ -313,7 +320,10 @@ static int spi_stm32_configure(struct spi_config *config) #if defined(CONFIG_SPI_STM32_HAS_FIFO) LL_SPI_SetRxFIFOThreshold(spi, LL_SPI_RX_FIFO_TH_QUARTER); #endif + +#ifndef CONFIG_SOC_SERIES_STM32F1X LL_SPI_SetStandard(spi, LL_SPI_PROTOCOL_MOTOROLA); +#endif /* At this point, it's mandatory to set this on the context! */ data->ctx.config = config; diff --git a/include/dt-bindings/pinctrl/stm32-pinctrlf1.h b/include/dt-bindings/pinctrl/stm32-pinctrlf1.h index 9ed305b1d66b0..8fdf44e10a01b 100644 --- a/include/dt-bindings/pinctrl/stm32-pinctrlf1.h +++ b/include/dt-bindings/pinctrl/stm32-pinctrlf1.h @@ -75,10 +75,35 @@ * registers for particular pin. */ -#define STM32_PIN_USART_TX (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_PUSH_PULL) -#define STM32_PIN_USART_RX (STM32_MODE_INPUT | STM32_CNF_IN_FLOAT) -#define STM32_PIN_I2C (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_OPEN_DRAIN) -#define STM32_PIN_PWM (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_PUSH_PULL) +#define STM32_PIN_USART_TX (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_PUSH_PULL) +#define STM32_PIN_USART_RX (STM32_MODE_INPUT | STM32_CNF_IN_FLOAT) +#define STM32_PIN_I2C (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_OPEN_DRAIN) +#define STM32_PIN_PWM (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_PUSH_PULL) +#define STM32_PIN_SPI_MASTER_SCK (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_PUSH_PULL) +#define STM32_PIN_SPI_SLAVE_SCK (STM32_MODE_INPUT | STM32_CNF_IN_FLOAT) +#define STM32_PIN_SPI_MASTER_MOSI (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_PUSH_PULL) +#define STM32_PIN_SPI_SLAVE_MOSI (STM32_MODE_INPUT | STM32_CNF_IN_FLOAT) +#define STM32_PIN_SPI_MASTER_MISO (STM32_MODE_INPUT | STM32_CNF_IN_FLOAT) +#define STM32_PIN_SPI_SLAVE_MISO (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_PUSH_PULL) +/* + * Reference manual (RM0008) + * Section 25.3.1: Slave select (NSS) pin management + * + * Hardware NSS management: + * - NSS output disabled: allows multimaster capability for devices operating + * in master mode. + * - NSS output enabled: used only when the device operates in master mode. + * + * Software NSS management: + * - External NSS pin remains free for other application uses. + * + */ + +/* Hardware master NSS output disabled */ +#define STM32_PIN_SPI_MASTER_NSS (STM32_MODE_INPUT | STM32_CNF_IN_FLOAT) +/* Hardware master NSS output enabled */ +#define STM32_PIN_SPI_MASTER_NSS_OE (STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC | STM32_CNF_PUSH_PULL) +#define STM32_PIN_SPI_SLAVE_NSS (STM32_MODE_INPUT | STM32_CNF_IN_FLOAT) #endif /* _STM32_PINCTRLF1_H_ */ From c7a170b3731f5c46793aac2dfa6b9ae04533f1a3 Mon Sep 17 00:00:00 2001 From: Yannis Damigos Date: Wed, 13 Dec 2017 13:49:11 +0200 Subject: [PATCH 2/3] boards: arm: olimexino_stm32: Enable SPI1 port Enable SPI1 port on olimexino_stm32. Signed-off-by: Yannis Damigos --- arch/arm/soc/st_stm32/stm32f1/dts.fixup | 5 +++++ boards/arm/olimexino_stm32/Kconfig.defconfig | 10 ++++++++++ boards/arm/olimexino_stm32/doc/olimexino_stm32.rst | 12 ++++++++++++ boards/arm/olimexino_stm32/olimexino_stm32.dts | 4 ++++ boards/arm/olimexino_stm32/olimexino_stm32_defconfig | 3 +++ boards/arm/olimexino_stm32/pinmux.c | 6 ++++++ 6 files changed, 40 insertions(+) diff --git a/arch/arm/soc/st_stm32/stm32f1/dts.fixup b/arch/arm/soc/st_stm32/stm32f1/dts.fixup index 9011342813dfe..c52acd94b2aae 100644 --- a/arch/arm/soc/st_stm32/stm32f1/dts.fixup +++ b/arch/arm/soc/st_stm32/stm32f1/dts.fixup @@ -28,4 +28,9 @@ #define CONFIG_I2C_2_ERROR_IRQ ST_STM32_I2C_V1_40005800_IRQ_ERROR #define CONFIG_I2C_2_BITRATE ST_STM32_I2C_V1_40005800_CLOCK_FREQUENCY +#define CONFIG_SPI_1_BASE_ADDRESS ST_STM32_SPI_40013000_BASE_ADDRESS +#define CONFIG_SPI_1_IRQ_PRI ST_STM32_SPI_40013000_IRQ_0_PRIORITY +#define CONFIG_SPI_1_NAME ST_STM32_SPI_40013000_LABEL +#define CONFIG_SPI_1_IRQ ST_STM32_SPI_40013000_IRQ_0 + /* End of SoC Level DTS fixup file */ diff --git a/boards/arm/olimexino_stm32/Kconfig.defconfig b/boards/arm/olimexino_stm32/Kconfig.defconfig index 2c34ec8c9351c..5eac13f298096 100644 --- a/boards/arm/olimexino_stm32/Kconfig.defconfig +++ b/boards/arm/olimexino_stm32/Kconfig.defconfig @@ -24,4 +24,14 @@ config I2C_2 endif # I2C +if SPI + +config SPI_STM32_INTERRUPT + default y + +config SPI_1 + default y + +endif # SPI + endif # BOARD_OLIMEXINO_STM32 diff --git a/boards/arm/olimexino_stm32/doc/olimexino_stm32.rst b/boards/arm/olimexino_stm32/doc/olimexino_stm32.rst index d6c1168ea61f2..0d1e04e55e41c 100644 --- a/boards/arm/olimexino_stm32/doc/olimexino_stm32.rst +++ b/boards/arm/olimexino_stm32/doc/olimexino_stm32.rst @@ -43,6 +43,8 @@ hardware features: +-----------+------------+----------------------+ | I2C | on-chip | i2c | +-----------+------------+----------------------+ +| SPI | on-chip | spi | ++-----------+------------+----------------------+ Other hardware features are not supported by the Zephyr kernel. @@ -299,6 +301,16 @@ Serial Port OLIMEXINO-STM32 board has up to 3 U(S)ARTs. The Zephyr console output is assigned to USART1. Default settings are 115200 8N1. +SPI +=== + +OLIMEXINO-STM32 board has up to 2 SPIs. The default SPI mapping for Zephyr is: + +- SPI1_NSS : PA4 +- SPI1_SCK : PA5 +- SPI1_MISO : PA6 +- SPI1_MOSI : PA7 + I2C === diff --git a/boards/arm/olimexino_stm32/olimexino_stm32.dts b/boards/arm/olimexino_stm32/olimexino_stm32.dts index ab705c2d8406b..fbd5c6b73eccb 100644 --- a/boards/arm/olimexino_stm32/olimexino_stm32.dts +++ b/boards/arm/olimexino_stm32/olimexino_stm32.dts @@ -41,3 +41,7 @@ status = "ok"; clock-frequency = ; }; + +&spi1 { + status = "ok"; +}; diff --git a/boards/arm/olimexino_stm32/olimexino_stm32_defconfig b/boards/arm/olimexino_stm32/olimexino_stm32_defconfig index 00bc5b61f522e..55214670a1c94 100644 --- a/boards/arm/olimexino_stm32/olimexino_stm32_defconfig +++ b/boards/arm/olimexino_stm32/olimexino_stm32_defconfig @@ -16,6 +16,9 @@ CONFIG_UART_CONSOLE=y # enable I2C driver CONFIG_I2C=y +# enable SPI +CONFIG_SPI=y + # enable pinmux CONFIG_PINMUX=y diff --git a/boards/arm/olimexino_stm32/pinmux.c b/boards/arm/olimexino_stm32/pinmux.c index ef6c082e3a0e7..56e6270437e91 100644 --- a/boards/arm/olimexino_stm32/pinmux.c +++ b/boards/arm/olimexino_stm32/pinmux.c @@ -30,6 +30,12 @@ static const struct pin_config pinconf[] = { {STM32_PIN_PB10, STM32F1_PINMUX_FUNC_PB10_I2C2_SCL}, {STM32_PIN_PB11, STM32F1_PINMUX_FUNC_PB11_I2C2_SDA}, #endif /* CONFIG_I2C_2 */ +#ifdef CONFIG_SPI_1 + {STM32_PIN_PA4, STM32F1_PINMUX_FUNC_PA4_SPI1_MASTER_NSS_OE}, + {STM32_PIN_PA5, STM32F1_PINMUX_FUNC_PA5_SPI1_MASTER_SCK}, + {STM32_PIN_PA6, STM32F1_PINMUX_FUNC_PA6_SPI1_MASTER_MISO}, + {STM32_PIN_PA7, STM32F1_PINMUX_FUNC_PA7_SPI1_MASTER_MOSI}, +#endif }; static int pinmux_stm32_init(struct device *port) From ef67f9888d92ca5ac3ceb373eb96e4f0c7416bb1 Mon Sep 17 00:00:00 2001 From: Yannis Damigos Date: Fri, 15 Dec 2017 23:06:10 +0200 Subject: [PATCH 3/3] drivers: spi_ll_stm32: Protect against null TX/RX buffer TX/RX buffer may be NULL, so check them before use. Signed-off-by: Yannis Damigos --- drivers/spi/spi_ll_stm32.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index ff7eb8d7d1927..29080d1802b8a 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -57,17 +57,16 @@ static int spi_stm32_get_err(SPI_TypeDef *spi) static inline u16_t spi_stm32_next_tx(struct spi_stm32_data *data) { - u16_t tx_frame; + u16_t tx_frame = SPI_STM32_TX_NOP; - if (spi_context_tx_on(&data->ctx)) { + if (spi_context_tx_buf_on(&data->ctx)) { if (SPI_WORD_SIZE_GET(data->ctx.config->operation) == 8) { tx_frame = UNALIGNED_GET((u8_t *)(data->ctx.tx_buf)); } else { tx_frame = UNALIGNED_GET((u16_t *)(data->ctx.tx_buf)); } - } else { - tx_frame = SPI_STM32_TX_NOP; } + return tx_frame; } @@ -97,16 +96,16 @@ static void spi_stm32_shift_m(SPI_TypeDef *spi, struct spi_stm32_data *data) if (SPI_WORD_SIZE_GET(data->ctx.config->operation) == 8) { rx_frame = LL_SPI_ReceiveData8(spi); - if (spi_context_rx_on(&data->ctx)) { + if (spi_context_rx_buf_on(&data->ctx)) { UNALIGNED_PUT(rx_frame, (u8_t *)data->ctx.rx_buf); - spi_context_update_rx(&data->ctx, 1, 1); } + spi_context_update_rx(&data->ctx, 1, 1); } else { rx_frame = LL_SPI_ReceiveData16(spi); - if (spi_context_rx_on(&data->ctx)) { + if (spi_context_rx_buf_on(&data->ctx)) { UNALIGNED_PUT(rx_frame, (u16_t *)data->ctx.rx_buf); - spi_context_update_rx(&data->ctx, 2, 1); } + spi_context_update_rx(&data->ctx, 2, 1); } } @@ -132,18 +131,18 @@ static void spi_stm32_shift_s(SPI_TypeDef *spi, struct spi_stm32_data *data) if (LL_SPI_IsActiveFlag_RXNE(spi)) { if (SPI_WORD_SIZE_GET(data->ctx.config->operation) == 8) { rx_frame = LL_SPI_ReceiveData8(spi); - if (spi_context_rx_on(&data->ctx)) { + if (spi_context_rx_buf_on(&data->ctx)) { UNALIGNED_PUT(rx_frame, (u8_t *)data->ctx.rx_buf); - spi_context_update_rx(&data->ctx, 1, 1); } + spi_context_update_rx(&data->ctx, 1, 1); } else { rx_frame = LL_SPI_ReceiveData16(spi); - if (spi_context_rx_on(&data->ctx)) { + if (spi_context_rx_buf_on(&data->ctx)) { UNALIGNED_PUT(rx_frame, (u16_t *)data->ctx.rx_buf); - spi_context_update_rx(&data->ctx, 2, 1); } + spi_context_update_rx(&data->ctx, 2, 1); } } }