From bb9f17fc687c17d7bfdfd1a2e8d8f6121edee014 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 28 Feb 2023 16:40:08 +0100 Subject: [PATCH 1/2] drivers: spi: stm32 spi driver supporting DMA in asynchronous mode Acts the SPI asynchronous mode on the stm32 devices, when DMA is activated or not for SPI transfer. Signed-off-by: Francois Ramu --- drivers/spi/spi_ll_stm32.c | 49 +++++++++++++++++++++++++------------- drivers/spi/spi_ll_stm32.h | 2 +- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 8590cc6fd580..2cdb14119595 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -84,6 +84,7 @@ static void dma_callback(const struct device *dev, void *arg, k_sem_give(&data->status_sem); } +#if !defined(CONFIG_SPI_STM32_INTERRUPT) && !defined(CONFIG_SPI_ASYNC) static int spi_stm32_dma_tx_load(const struct device *dev, const uint8_t *buf, size_t len) { @@ -220,6 +221,7 @@ static int spi_dma_move_buffers(const struct device *dev, size_t len) return ret; } +#endif /* !defined(CONFIG_SPI_STM32_INTERRUPT) && !defined(CONFIG_SPI_ASYNC) */ #endif /* CONFIG_SPI_STM32_DMA */ @@ -386,7 +388,7 @@ static void spi_stm32_complete(const struct device *dev, int status) { const struct spi_stm32_config *cfg = dev->config; SPI_TypeDef *spi = cfg->spi; -#ifdef CONFIG_SPI_STM32_INTERRUPT +#if defined(CONFIG_SPI_STM32_INTERRUPT) || defined(CONFIG_SPI_ASYNC) struct spi_stm32_data *data = dev->data; ll_func_disable_int_tx_empty(spi); @@ -415,12 +417,12 @@ static void spi_stm32_complete(const struct device *dev, int status) ll_func_disable_spi(spi); -#ifdef CONFIG_SPI_STM32_INTERRUPT +#if defined(CONFIG_SPI_STM32_INTERRUPT) || defined(CONFIG_SPI_ASYNC) spi_context_complete(&data->ctx, dev, status); #endif } -#ifdef CONFIG_SPI_STM32_INTERRUPT +#if defined(CONFIG_SPI_STM32_INTERRUPT) || defined(CONFIG_SPI_ASYNC) static void spi_stm32_isr(const struct device *dev) { const struct spi_stm32_config *cfg = dev->config; @@ -616,12 +618,6 @@ static int transceive(const struct device *dev, return 0; } -#ifndef CONFIG_SPI_STM32_INTERRUPT - if (asynchronous) { - return -ENOTSUP; - } -#endif - spi_context_lock(&data->ctx, asynchronous, cb, userdata, config); ret = spi_stm32_configure(dev, config); @@ -656,7 +652,7 @@ static int transceive(const struct device *dev, /* This is turned off in spi_stm32_complete(). */ spi_stm32_cs_control(dev, true); -#ifdef CONFIG_SPI_STM32_INTERRUPT +#if defined(CONFIG_SPI_STM32_INTERRUPT) || defined(CONFIG_SPI_ASYNC) ll_func_enable_int_errors(spi); if (rx_bufs) { @@ -689,6 +685,7 @@ static int transceive(const struct device *dev, #ifdef CONFIG_SPI_STM32_DMA +#if !defined(CONFIG_SPI_STM32_INTERRUPT) && !defined(CONFIG_SPI_ASYNC) static int wait_dma_rx_tx_done(const struct device *dev) { struct spi_stm32_data *data = dev->data; @@ -722,6 +719,7 @@ static int wait_dma_rx_tx_done(const struct device *dev) return res; } +#endif static int transceive_dma(const struct device *dev, const struct spi_config *config, @@ -740,10 +738,6 @@ static int transceive_dma(const struct device *dev, return 0; } - if (asynchronous) { - return -ENOTSUP; - } - spi_context_lock(&data->ctx, asynchronous, cb, userdata, config); k_sem_reset(&data->status_sem); @@ -776,6 +770,18 @@ static int transceive_dma(const struct device *dev, /* This is turned off in spi_stm32_complete(). */ spi_stm32_cs_control(dev, true); +#if defined(CONFIG_SPI_STM32_INTERRUPT) || defined(CONFIG_SPI_ASYNC) + ll_func_enable_int_errors(spi); + + if (rx_bufs) { + ll_func_enable_int_rx_not_empty(spi); + } + + ll_func_enable_int_tx_empty(spi); + + ret = spi_context_wait_for_completion(&data->ctx); + +#else while (data->ctx.rx_len > 0 || data->ctx.tx_len > 0) { size_t dma_len; @@ -842,6 +848,8 @@ static int transceive_dma(const struct device *dev, } #endif /* CONFIG_SPI_SLAVE */ +#endif + end: spi_context_release(&data->ctx, ret); @@ -874,6 +882,15 @@ static int spi_stm32_transceive_async(const struct device *dev, spi_callback_t cb, void *userdata) { +#ifdef CONFIG_SPI_STM32_DMA + struct spi_stm32_data *data = dev->data; + + if ((data->dma_tx.dma_dev != NULL) + && (data->dma_rx.dma_dev != NULL)) { + return transceive_dma(dev, config, tx_bufs, rx_bufs, + true, cb, userdata); + } +#endif /* CONFIG_SPI_STM32_DMA */ return transceive(dev, config, tx_bufs, rx_bufs, true, cb, userdata); } #endif /* CONFIG_SPI_ASYNC */ @@ -935,7 +952,7 @@ static int spi_stm32_init(const struct device *dev) } } -#ifdef CONFIG_SPI_STM32_INTERRUPT +#if defined(CONFIG_SPI_STM32_INTERRUPT) || defined(CONFIG_SPI_ASYNC) cfg->irq_config(dev); #endif @@ -966,7 +983,7 @@ static int spi_stm32_init(const struct device *dev) return 0; } -#ifdef CONFIG_SPI_STM32_INTERRUPT +#if defined(CONFIG_SPI_STM32_INTERRUPT) || defined(CONFIG_SPI_ASYNC) #define STM32_SPI_IRQ_HANDLER_DECL(id) \ static void spi_stm32_irq_config_func_##id(const struct device *dev) #define STM32_SPI_IRQ_HANDLER_FUNC(id) \ diff --git a/drivers/spi/spi_ll_stm32.h b/drivers/spi/spi_ll_stm32.h index 4785d3e9895e..970f2d190155 100644 --- a/drivers/spi/spi_ll_stm32.h +++ b/drivers/spi/spi_ll_stm32.h @@ -22,7 +22,7 @@ typedef void (*irq_config_func_t)(const struct device *port); struct spi_stm32_config { SPI_TypeDef *spi; const struct pinctrl_dev_config *pcfg; -#ifdef CONFIG_SPI_STM32_INTERRUPT +#if defined(CONFIG_SPI_STM32_INTERRUPT) || defined(CONFIG_SPI_ASYNC) irq_config_func_t irq_config; #endif #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_subghz) From 1a099d37be079cfbe2e1bab646d07a3798e7e1b3 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 28 Feb 2023 16:44:20 +0100 Subject: [PATCH 2/2] tests: drivers: spi loopback in async mode with or w/o DMA Add the overlay and config to run the spi loopback test transfer with DMA and also in async mode with DMA on any stm32 platform. New target disco_l475_iot1 Signed-off-by: Francois Ramu --- .../boards/disco_l475_iot1.overlay | 21 +++++++++++++++++++ tests/drivers/spi/spi_loopback/testcase.yaml | 21 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/drivers/spi/spi_loopback/boards/disco_l475_iot1.overlay diff --git a/tests/drivers/spi/spi_loopback/boards/disco_l475_iot1.overlay b/tests/drivers/spi/spi_loopback/boards/disco_l475_iot1.overlay new file mode 100644 index 000000000000..906db32d9b45 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/disco_l475_iot1.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi1 { + dmas = <&dma1 1 3 STM32_DMA_PERIPH_TX + &dma1 1 2 STM32_DMA_PERIPH_RX>; + dma-names = "tx", "rx"; + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/testcase.yaml b/tests/drivers/spi/spi_loopback/testcase.yaml index 42e649fed226..ec368aaf5ced 100644 --- a/tests/drivers/spi/spi_loopback/testcase.yaml +++ b/tests/drivers/spi/spi_loopback/testcase.yaml @@ -33,9 +33,28 @@ tests: integration_platforms: - sam_e70_xplained drivers.spi.stm32_spi_dma.loopback: - extra_args: OVERLAY_CONFIG="overlay-stm32-spi-dma.conf" + extra_configs: + - CONFIG_SPI_STM32_DMA=y + - CONFIG_SPI_ASYNC=n + filter: CONFIG_SOC_FAMILY_STM32 + platform_allow: + - disco_l475_iot1 + - nucleo_g474re + - nucleo_f207zg + - nucleo_f429zi + - nucleo_f746zg + - nucleo_wb55rg + - nucleo_l152re + - nucleo_wl55jc + - nucleo_h743zi + integration_platforms: + - nucleo_g474re + drivers.spi.stm32_spi_async_dma.loopback: + extra_configs: + - CONFIG_SPI_STM32_DMA=y filter: CONFIG_SOC_FAMILY_STM32 platform_allow: + - disco_l475_iot1 - nucleo_g474re - nucleo_f207zg - nucleo_f429zi