diff --git a/drivers/i2s/Kconfig.stm32 b/drivers/i2s/Kconfig.stm32 index 697aee3b08462..68961d873f491 100644 --- a/drivers/i2s/Kconfig.stm32 +++ b/drivers/i2s/Kconfig.stm32 @@ -35,6 +35,7 @@ menuconfig I2S_STM32_SAI select USE_STM32_HAL_DMA select USE_STM32_HAL_DMA_EX select USE_STM32_HAL_SAI + select USE_STM32_HAL_SAI_EX if SOC_SERIES_STM32F4X help Enable SAI support on the STM32 family of processors. diff --git a/drivers/i2s/i2s_stm32_sai.c b/drivers/i2s/i2s_stm32_sai.c index e80fdd41dc425..9a5ee27d10d3b 100644 --- a/drivers/i2s/i2s_stm32_sai.c +++ b/drivers/i2s/i2s_stm32_sai.c @@ -283,11 +283,17 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) } hdma->Instance = STM32_DMA_GET_INSTANCE(stream->reg, stream->dma_channel); +#if defined(CONFIG_SOC_SERIES_STM32F4X) + hdma->Init.Channel = dma_cfg.dma_slot * DMA_CHANNEL_1; +#else hdma->Init.Request = dma_cfg.dma_slot; +#endif hdma->Init.Mode = DMA_NORMAL; #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32G4X) || defined(CONFIG_SOC_SERIES_STM32L5X) + defined(CONFIG_SOC_SERIES_STM32G4X) || defined(CONFIG_SOC_SERIES_STM32L5X) || \ + defined(CONFIG_SOC_SERIES_STM32F4X) + hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma->Init.Priority = DMA_PRIORITY_HIGH; @@ -304,7 +310,7 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) hdma->Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER; #endif -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32F4X) hdma->Init.FIFOMode = DMA_FIFOMODE_DISABLE; #endif @@ -312,7 +318,8 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; #if !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_SOC_SERIES_STM32L4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) + !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) && \ + !defined(CONFIG_SOC_SERIES_STM32F4X) hdma->Init.SrcInc = DMA_SINC_INCREMENTED; hdma->Init.DestInc = DMA_DINC_FIXED; #endif @@ -322,7 +329,8 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; #if !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_SOC_SERIES_STM32L4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) + !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) && \ + !defined(CONFIG_SOC_SERIES_STM32F4X) hdma->Init.SrcInc = DMA_SINC_FIXED; hdma->Init.DestInc = DMA_DINC_INCREMENTED; #endif @@ -342,7 +350,8 @@ static int i2s_stm32_sai_dma_init(const struct device *dev) return -EIO; } #elif !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_SOC_SERIES_STM32L4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) + !defined(CONFIG_SOC_SERIES_STM32G4X) && !defined(CONFIG_SOC_SERIES_STM32L5X) && \ + !defined(CONFIG_SOC_SERIES_STM32F4X) if (HAL_DMA_ConfigChannelAttributes(&dev_data->hdma, DMA_CHANNEL_NPRIV) != HAL_OK) { LOG_ERR("HAL_DMA_ConfigChannelAttributes: "); return -EIO; @@ -458,7 +467,7 @@ static int i2s_stm32_sai_configure(const struct device *dev, enum i2s_dir dir, } /* Control of MCLK output from SAI configuration is not possible on STM32L4xx MCUs */ -#if !defined(CONFIG_SOC_SERIES_STM32L4X) +#if !defined(CONFIG_SOC_SERIES_STM32L4X) && !defined(CONFIG_SOC_SERIES_STM32F4X) if (cfg->mclk_enable && stream->master) { hsai->Init.MckOutput = SAI_MCK_OUTPUT_ENABLE; } else { @@ -472,7 +481,7 @@ static int i2s_stm32_sai_configure(const struct device *dev, enum i2s_dir dir, hsai->Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; /* MckOverSampling is not supported by all STM32L4xx MCUs */ -#if !defined(CONFIG_SOC_SERIES_STM32L4X) +#if !defined(CONFIG_SOC_SERIES_STM32L4X) && !defined(CONFIG_SOC_SERIES_STM32F4X) if (cfg->mclk_div == (enum mclk_divider)MCLK_DIV_256) { hsai->Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE; } else { diff --git a/dts/arm/st/f4/stm32f413.dtsi b/dts/arm/st/f4/stm32f413.dtsi index 4cfe6a4587c8a..a410152e7a263 100644 --- a/dts/arm/st/f4/stm32f413.dtsi +++ b/dts/arm/st/f4/stm32f413.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Florian Vaussard, HEIG-VD + * Copyright (c) 2025 Mario Paja * * SPDX-License-Identifier: Apache-2.0 */ @@ -80,5 +81,27 @@ clocks = <&rcc STM32_CLOCK(APB1, 27)>; status = "disabled"; }; + + sai1_a: sai1@40015804 { + compatible = "st,stm32-sai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40015804 0x20>; + clocks = <&rcc STM32_CLOCK(APB2, 22)>; + dmas = <&dma2 1 0 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | + STM32_DMA_16BITS) 0>; + status = "disabled"; + }; + + sai1_b: sai1@40015824 { + compatible = "st,stm32-sai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40015824 0x20>; + clocks = <&rcc STM32_CLOCK(APB2, 22)>; + dmas = <&dma2 5 0 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | + STM32_DMA_16BITS) 0>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/st/f4/stm32f427.dtsi b/dts/arm/st/f4/stm32f427.dtsi index 4baf3a1f8317e..0ce973cc21228 100644 --- a/dts/arm/st/f4/stm32f427.dtsi +++ b/dts/arm/st/f4/stm32f427.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Linaro Limited + * Copyright (c) 2025 Mario Paja * * SPDX-License-Identifier: Apache-2.0 */ @@ -111,6 +112,28 @@ status = "disabled"; }; }; + + sai1_a: sai1@40015804 { + compatible = "st,stm32-sai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40015804 0x20>; + clocks = <&rcc STM32_CLOCK(APB2, 22)>; + dmas = <&dma2 1 0 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | + STM32_DMA_16BITS) 0>; + status = "disabled"; + }; + + sai1_b: sai1@40015824 { + compatible = "st,stm32-sai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40015824 0x20>; + clocks = <&rcc STM32_CLOCK(APB2, 22)>; + dmas = <&dma2 5 0 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | + STM32_DMA_16BITS) 0>; + status = "disabled"; + }; }; die_temp: dietemp { diff --git a/dts/arm/st/f4/stm32f446.dtsi b/dts/arm/st/f4/stm32f446.dtsi index fb5ec329579b4..2ed9145bc09d4 100644 --- a/dts/arm/st/f4/stm32f446.dtsi +++ b/dts/arm/st/f4/stm32f446.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Philémon Jaermann + * Copyright (c) 2025 Mario Paja * * SPDX-License-Identifier: Apache-2.0 */ @@ -169,6 +170,28 @@ status = "disabled"; }; }; + + sai1_a: sai1@40015804 { + compatible = "st,stm32-sai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40015804 0x20>; + clocks = <&rcc STM32_CLOCK(APB2, 22)>; + dmas = <&dma2 1 0 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | + STM32_DMA_16BITS) 0>; + status = "disabled"; + }; + + sai1_b: sai1@40015824 { + compatible = "st,stm32-sai"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40015824 0x20>; + clocks = <&rcc STM32_CLOCK(APB2, 22)>; + dmas = <&dma2 5 0 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | + STM32_DMA_16BITS) 0>; + status = "disabled"; + }; }; die_temp: dietemp { diff --git a/samples/drivers/i2s/output/boards/nucleo_f429zi.conf b/samples/drivers/i2s/output/boards/nucleo_f429zi.conf new file mode 100644 index 0000000000000..4f3f73a1e06a5 --- /dev/null +++ b/samples/drivers/i2s/output/boards/nucleo_f429zi.conf @@ -0,0 +1 @@ +CONFIG_HEAP_MEM_POOL_SIZE=4192 diff --git a/samples/drivers/i2s/output/boards/nucleo_f429zi.overlay b/samples/drivers/i2s/output/boards/nucleo_f429zi.overlay new file mode 100644 index 0000000000000..edb91c5bbc090 --- /dev/null +++ b/samples/drivers/i2s/output/boards/nucleo_f429zi.overlay @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Mario Paja + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + i2s-tx = &sai1_b; + }; +}; + +/* 43.836KHz (-0.37% Error) */ +&pllsai{ + div-m = <8>; + mul-n = <101>; + div-q = <9>; + div-divq = <1>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&sai1_b { + pinctrl-0 = <&sai1_mclk_b_pf7 &sai1_sd_b_pe3 &sai1_fs_b_pf9 &sai1_sck_b_pf8>; + pinctrl-names = "default"; + status = "okay"; + mclk-enable; + mclk-divider = "div-256"; + dma-names = "tx"; +}; + +&dma2 { + status = "okay"; +};