Skip to content

Conversation

@mariopaja
Copy link
Contributor

@mariopaja mariopaja commented Aug 26, 2025

This PR enables SAI on STM32L4xx series by:

  1. Adding SAI1 A/B nodes
  2. Update DMA & SAI configurations for STM32L4xx
  3. Adding nucleo_l432kc in samples/drivers/i2s/output
stm32l4xx_sai

@mariopaja mariopaja mentioned this pull request Aug 26, 2025
21 tasks
@evgeniy-paltsev
Copy link
Contributor

evgeniy-paltsev commented Aug 27, 2025

Logs from my side:

Could not trigger I2S tx
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: Clock Control Device: <OK>
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: I2S clock Enable: <OK>
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: I2S domain clock configuration: <OK>
[00:00:00.000,000] <inf> i2s_stm32_sai: sai1@40015404 inited
*** Booting Zephyr OS build v4.2.0-rc2-2503-g4e322a40c201 ***
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_configure: SAI_STEREOMODE
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_trigger: I2S_TRIGGER_START
[00:00:01.001,000] <err> i2s_stm32_sai: HAL_SAI_Transmit_DMA: <FAILED>
[00:00:01.001,000] <err> i2s_stm32_sai: START trigger failed -5

We stuck waiting for this:

    /* Wait until FIFO is not empty */
    while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)

@evgeniy-paltsev
Copy link
Contributor

evgeniy-paltsev commented Aug 27, 2025

Instance seems to be correct (DMA2_Channel1)
Request number (DMA_REQUEST_1) seems to be correct.
DMA2_CSELR->CSELR == 1 - seems to be correct.

As I understand dma_slot = 37 from dmas = <&dma2 1 37 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | is not really affect any HW configuration (in case of current L4 code).

@mariopaja
Copy link
Contributor Author

mariopaja commented Aug 27, 2025

Logs from my side:

Could not trigger I2S tx
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: Clock Control Device: <OK>
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: I2S clock Enable: <OK>
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: I2S domain clock configuration: <OK>
[00:00:00.000,000] <inf> i2s_stm32_sai: sai1@40015404 inited
*** Booting Zephyr OS build v4.2.0-rc2-2503-g4e322a40c201 ***
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_configure: SAI_STEREOMODE
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_trigger: I2S_TRIGGER_START
[00:00:01.001,000] <err> i2s_stm32_sai: HAL_SAI_Transmit_DMA: <FAILED>
[00:00:01.001,000] <err> i2s_stm32_sai: START trigger failed -5

We stuck waiting for this:

    /* Wait until FIFO is not empty */
    while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)

This is the same behaviour that I also get

Instance seems to be correct (DMA2_Channel1) Request number (DMA_REQUEST_1) seems to be correct. DMA2_CSELR->CSELR == 1 - seems to be correct.

As I understand dma_slot = 37 from dmas = <&dma2 1 37 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH | is not really affect any HW configuration (in case of current L4 code).

dma_slot = 37 is an arbitrary number set by me, but as you said it has no affect to the DMA configuration. To tell the truth I dont know why dma_slot is required in the binding, or why it is implemented at the first place.

However dma_cfg.dma_slot return 0x25 and I dont know where this value comes from, this is the reason why I am setting the request number to DMA_REQUEST_1

@evgeniy-paltsev
Copy link
Contributor

Now I have

[00:00:30.002,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_trigger: I2S_TRIGGER_DRAIN
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: Clock Control Device: <OK>
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: I2S clock Enable: <OK>
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: I2S domain clock configuration: <OK>
[00:00:00.000,000] <inf> i2s_stm32_sai: sai1@40015404 inited
*** Booting Zephyr OS build v4.2.0-rc2-2503-g4e322a40c201 ***
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_configure: dma_src_size 2
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_configure: SAI_STEREOMODE
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_trigger: I2S_TRIGGER_START
[00:00:02.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:04.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:06.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:08.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:10.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:12.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:14.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:16.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:18.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:20.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:22.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:24.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:26.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:28.002,000] <err> i2s_stm32_sai: TX queue full
All I2S blocks written
[00:00:30.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:30.002,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_trigger: I2S_TRIGGER_DRAIN

@mariopaja
Copy link
Contributor Author

Now I have

[00:00:30.002,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_trigger: I2S_TRIGGER_DRAIN
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: Clock Control Device: <OK>
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: I2S clock Enable: <OK>
[00:00:00.000,000] <dbg> i2s_stm32_sai: stm32_sai_enable_clock: I2S domain clock configuration: <OK>
[00:00:00.000,000] <inf> i2s_stm32_sai: sai1@40015404 inited
*** Booting Zephyr OS build v4.2.0-rc2-2503-g4e322a40c201 ***
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_configure: dma_src_size 2
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_configure: SAI_STEREOMODE
[00:00:00.000,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_trigger: I2S_TRIGGER_START
[00:00:02.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:04.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:06.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:08.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:10.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:12.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:14.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:16.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:18.001,000] <err> i2s_stm32_sai: TX queue full
[00:00:20.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:22.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:24.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:26.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:28.002,000] <err> i2s_stm32_sai: TX queue full
All I2S blocks written
[00:00:30.002,000] <err> i2s_stm32_sai: TX queue full
[00:00:30.002,000] <dbg> i2s_stm32_sai: i2s_stm32_sai_trigger: I2S_TRIGGER_DRAIN

From an inital look without going into details seems like HAL_SAI_TxCpltCallback() is not called. I will have a look into it 😄

@mariopaja mariopaja force-pushed the stm32l4_sai branch 5 times, most recently from 53efd8a to f195c5b Compare August 29, 2025 12:16
@mariopaja
Copy link
Contributor Author

@evgeniy-paltsev Issue found, SAI should work now without problems

The issue was DMA Channel.

On STM32L4xx DMA channel is given from 0 - 7
On other platforms DMA channel given is given from 1 - 8

@evgeniy-paltsev
Copy link
Contributor

Haven't tried to connect real I2S peripheral yet - but at least DMA seems to be working now :)

Copy link
Contributor

@evgeniy-paltsev evgeniy-paltsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dma_slot = 37 is an arbitrary number set by me, but as you said it has no affect to the DMA configuration. To tell the truth I dont know why dma_slot is required in the binding, or why it is implemented at the first place.

However dma_cfg.dma_slot return 0x25 and I dont know where this value comes from, this is the reason why I am setting the request number to DMA_REQUEST_1

IMO, that's quite simple. We just need to use request number in slot field in dts.

Proof: https://github.com/zephyrproject-rtos/zephyr/blob/main/dts/bindings/dma/st%2Cstm32-dma-v2.yaml#L16

@evgeniy-paltsev
Copy link
Contributor

It's alive :)
image

However I see another issue now. We put stream in I2S_STATE_STOPPING state - but we never turn HW off - so SAI just keep working and generate FS and CLK (with data = 0).

You can check other I2S drivers (i.e. i2s_ll_stm32.c) - they turn hardware off when transmit is finished.

@mariopaja
Copy link
Contributor Author

@evgeniy-paltsev

You can check other I2S drivers (i.e. i2s_ll_stm32.c) - they turn hardware off when transmit is finished.

I wrote it down. I will check it and open a dedicated PR for that 😄

Since there are two issues with the H7 DMA I will open a new PR:

hdma->Init.PeriphInc = DMA_PINC_DISABLE;
hdma->Init.MemInc = DMA_MINC_ENABLE;
hdma->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

@mariopaja mariopaja force-pushed the stm32l4_sai branch 8 times, most recently from dba4b52 to 3bf0129 Compare September 3, 2025 12:56
@mariopaja mariopaja marked this pull request as ready for review September 3, 2025 13:03
Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM aside some minor issues.

#address-cells = <1>;
#size-cells = <0>;
reg = <0x40015404 0x20>;
clocks = <&rcc STM32_CLOCK(APB2, 21U)>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency in STM32 SoCs DTSI files (be kind my @mathieuchopstm, see #93912):

Suggested change
clocks = <&rcc STM32_CLOCK(APB2, 21U)>,
clocks = <&rcc STM32_CLOCK(APB2, 21)>,

Ditto for sai1_b below.

return -EINVAL;
}

/* STM32L4xx not possible to control MCLK output from SAI configuration */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* STM32L4xx not possible to control MCLK output from SAI configuration */
/* Control of MCLK output from SAI configuration is not possible on STM32L4xx MCUs */

4);

DT_INST_FOREACH_STATUS_OKAY(I2S_STM32_SAI_INIT)
DT_INST_FOREACH_STATUS_OKAY(I2S_STM32_SAI_INIT)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please discard this change straight from commit "drivers: i2s: i2s_stm32_sai add support for stm32l4xx".

Comment on lines 579 to 580
dmas = <&dma2 1 1 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH |
STM32_DMA_16BITS)>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking on indentation. Would be better as:

		dmas = <&dma2 1 1 (STM32_DMA_MODE_NORMAL | STM32_DMA_PRIORITY_HIGH |
				   STM32_DMA_16BITS)>;

Add SAI1 A & B nodes for STM32L4xx series

Signed-off-by: Mario Paja <[email protected]>
STM32L4xx series shares several SAI & DMA configurations with
the other platforms. These changes aim to remove specific
DMA & SAI configurations which are not used by STM32L4xx

Signed-off-by: Mario Paja <[email protected]>
Add nucleo_l432kc in samples/drivers/i2s/output

Signed-off-by: Mario Paja <[email protected]>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Sep 3, 2025

Copy link
Contributor

@evgeniy-paltsev evgeniy-paltsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on STM32L431RCT6 + max98357a.

NOTE: tested TX part only on sai1_a.

@kartben kartben merged commit faf1919 into zephyrproject-rtos:main Sep 5, 2025
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants