cancel
Showing results for 
Search instead for 
Did you mean: 

Full Duplex I2S (SPI/I2S1) DMA Issues

michaelg643
Associate

Hello,

I'm working on an audio application using a NUCLEO-H723ZG, where I am trying to setup two DMA channels for full duplex audio. I am using the Zephyr RTOS with a modified I2S driver I am writing since the one in mainline zephyr is non-functional for duplex I2S (and I haven't seen it work for transmit I2S either). However, I am encountering FIFO errors in the DMA block while using direct mode, and I am not sure what is causing them. Unfortunately, I am not sure I can share this code publicly, but I can give the states of the registers in the peripherals.

Issue:

  • I get a FIFO error in the DMA peripheral immediately after re-enabling the DMA peripheral at the end of the first TX callback. I am using DMA in direct mode.
    • I get 0x31 in DMA1_LISR
      • Stream 0 FIFO error interrupt flag
      • Stream 0 half transfer flag
      • Stream 0 transfer complete
  • I do not get the FIFO error when servicing the TX callback the first time.
  • Registers show appropriate configurations, and clocks are enabled and stable.

Current Configuration (At the breakpoint right before the error):

  1. DMA Streams:

    • TX DMA Stream (DMA1 Stream 0):

      • Peripheral Address (S0PAR): 0x40013020 (SPI1 Data Register)
      • Memory Address (S0M0AR): 0x24003100 (Valid memory region)
      • Number of Data Items (S0NDTR): 0x1
      • Control Register (S0CR): 0x25450
      • FIFO Control Register (S0FCR): 0x21
    • RX DMA Stream (DMA1 Stream 1):

      • Peripheral Address (S1PAR): 0x40013030 (SPI1 Data Register)
      • Memory Address (S1M0AR): 0x2400F100 (Valid memory region)
      • Number of Data Items (S1NDTR): 0x1
      • Control Register (S1CR): 0x25411
      • FIFO Control Register (S1FCR): 0x21
  2. DMAMUX configuration:
    1. DMAMUX_C0CR: 0x26
    2. DMAMUX_C1CR: 0x25
  3. I2S Configuration:

    • Configuration Register 1 (CFG1): 0x0007C067
      • FTHVL: 0x3
    • Configuration Register 2 (CFG2): 0x00000000
    • Control Register 2 (CR2): 0x00000000
    • I2S Configuration Register (I2SCFGR): 0x0200060B (32-bit data, Philips I2S standard, Full duplex mode)
  4. Clock Configuration:

    • System Clock: PLL1 is the system clock
    • DMA Clock: Enabled (RCC_AHB1ENR)
    • SPI1 Clock: Enabled (RCC_APB2ENR)

Debugging Steps Taken:

  1. Verified Clock Configuration:

    • Confirmed that PLL1 is the system clock.
    • Checked that DMA1 and SPI1 clocks are enabled.
  2. DMA and I2S Configuration:

    • Ensured that DMA is in direct mode.
    • Checked peripheral and memory addresses for alignment and correctness.
    • Verified data width configuration matches the 32-bit data format.
    • Cleared all DMA and FIFO error flags before re-enabling the stream.
  3. Synchronizing Clocks:

    • Confirmed that the I2S clock source is properly configured and stable.
    • Verified system clock (HCLK) and AHB/APB prescaler settings.
  4. Interrupt and Error Handling:

    • Cleared pending interrupts in the IFCR register before starting the DMA stream

Despite these efforts, the FIFO errors persist. Any insights or suggestions on additional steps to troubleshoot this issue would be greatly appreciated. Let me know if additional information is required, I feel like I'm pulling my hair out trying to figure out the issue

Thank you!

4 REPLIES 4
AScha.3
Chief

Hi,

i dont know Zephyr and your codec , you dont tell anything about it, but for audio -> DMA -> I2S you should use circular mode - do you ?

Because you start the stream only one time and then its running continuous until power off, just in half/full callbacks you put + get new data on the stream...i never had fifo problems (on H743 + H563 ).

And for first, switch off D-cache, except you are sure about your cache manegement...

If you feel a post has answered your question, please click "Accept as Solution".

> I get a FIFO error in the DMA peripheral immediately after re-enabling the DMA peripheral at the end of the first TX callback.

That means, that I2S "run dry" (underrun), due to the ISR taking too long (longer than transmitting one I2S frame).

As @AScha.3 said above, I2S is to be served by a circular DMA.

JW

 

Well I started by trying to modify the existing Zephyr stm32 I2S driver which does not use circular mode - in the DMA callback (either TX or RX), the driver is managing a set of memory blocks to point the DMA peripheral to. I will investigate adding circular mode to the driver.

 

A question for you - regarding your comment on switching off D-cache: is the a compiler setting? or is this a register setting?

 

Thanks,

Michael

Caches D/I you can switch on at start, in Cube set it:  (register setting done at start)

AScha3_0-1716448900784.png

Problem with D-cache : when anything else, than the core/cpu moves data , (the DMA), the core/cache dont know about this and will use its cached data, so you get data inconsistency, cpu/cache data no more same as in RAM.

So with D-cache on and DMA , you need cache management or MPU settings, to define not cachable areas (that are used by DMA). But at start, if not needing the top last 2% performance , that D-cache might improve speed, just leave it off. Using I-cache (program->Instruction cache) is more important and creates no problems, because program is always executed by the cpu and nothing else .

 

If you feel a post has answered your question, please click "Accept as Solution".