cancel
Showing results for 
Search instead for 
Did you mean: 

STMH743ZIT6: DMA + DFSDM configuration for MEMS microphones

MannyMarc35
Associate II

 

Hello everyone,

in my current project, I'm working with a Nucleo H743ZI2 (with an STMH743ZIT6). My goal is to read audio data from MEMS microphones using DMA and DFSDM filters. The ultimate aim is to build an 8-microphone array, but for the first step, I only want to read data from a single microphone. And this is exactly where my problem lies: currently, no data is being saved in RAM. I suspect the problem is with DMA, as I've observed the following:

DFSDM:

  • The following bits are set in the DFSDM control register: DFEN (DFSDM_FLT enabled), RCONT (continuous mode), and RDMAEN (DMA channel enabled to read data for the regular conversion).
  • The value of the RDATAR register changes continuously => data is being read by DFSDM.
  • In the ISR register, REOCF (end of regular conversion) is set, followed by ROVRF (regular conversion overrun) => REOCF should be cleared by DMA (it might be cleared and set again, which goes unnoticed during debugging, but i don´t think so as the DMA is not started correctly).

DMA:

  • The function HAL_DFSDM_FilterRegularStart_DMA() returns HAL_OK.
  • However, the EN bit in the configuration register is not set afterward.
  • The M0AR register (memory 0 address register) is correctly set => points to the address of the AudioBuffer.
  • The PAR register (peripheral address register) is correctly set => points to RDATAR of DFSDM.
  • The NDTR register (number of data register) does not change its value => no interrupt is triggered.

It seems to me that DMA is not starting correctly or that something in the configuration is incorrect. Even when I try to start the DMA manually by the following function, no interrupt is triggered:

 

void start_DMA1_Stream0(void)
{
  DMA1_Stream0->CR = 0;
  while (DMA1_Stream0->CR & DMA_SxCR_EN);

  DMA1_Stream0->PAR = (uint32_t)DFSDM1_FLT0_CR1; // Peripherie adress
  DMA1_Stream0->M0AR = (uint32_t)&audioBuffer; // buffer where the data shoul be stored
  DMA1_Stream0->NDTR = 1024; // Sample count

  DMAMUX1_Channel0->CCR = 101;

  DMA1_Stream0->CR =  (1 << 2)  | // Transfer error interrupt enable
                      (1 << 3)  | // Half transfer interrupt enable 
                      (1 << 4)  | // Transfer complete interrupt enable                      
                      (1 << 8)  | // Circular Mode 
                      (1 << 10) | // Memory increment
                      (1 << 12) | // Peripheral data size = word 
                      (1 << 14) | // Memory data size = word
                      (1 << 0);   // Enable
}

 

I have attached main.c below, maybe someone can help me with my problem. It also contains a few debugging functions that are not so important.

Thank you in advance.

 

 
1 ACCEPTED SOLUTION

Accepted Solutions
MannyMarc35
Associate II

Hi @Saket_Om 

Thanks for your reply but I solved it 2 hours ago :)

For the solution I had a look at these two posts: 
https://community.st.com/t5/stm32-mcus/dma-is-not-working-on-stm32h7-devices/ta-p/49498  https://en.eeworld.com.cn/mp/STM32/a60611.jspx 

I found that the actual problem was related to memory access: the buffer I used for the audio data (audioBuffer) was placed in DTCM RAM (starting at address 0x20000000) by default. However, DMA1 on the STM32H7 series cannot access DTCM. According to the reference manual (RM0433), DMA1 and DMA2 can only access specific RAM regions like AXI-SRAM, SRAM1-3 (D2 domain), and SRAM4 (D3 domain).

To solve the problem, I explicitly placed the buffer into RAM_D2, which is accessible by DMA1:

  •  I added an output section in the linker script to map variables tagged with .RamD2: 
/* Section for variables that must reside in RAM_D2 (for DMA) */
/* All variables marked with __attribute__((section(".RamD2"))) go here */
.RAM_D2 (NOLOAD) :
{
  . = ALIGN(4);
  *(.RamD2)       
  . = ALIGN(4);
} >RAM_D2​
  • In my source code, I added the attribute to the buffer:
__attribute__((section(".RamD2"))) int32_t audioBuffer[AUDIO_BUFFER_SIZE];​

After this change, the DMA transfer started working immediately — data is now written into the buffer, and the DMA complete callback is triggered as expected.

 

View solution in original post

2 REPLIES 2
Saket_Om
ST Employee

Hello @MannyMarc35 

Could you please share your files hal_msp.c and it.c then we can assist you more effectively. 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om
MannyMarc35
Associate II

Hi @Saket_Om 

Thanks for your reply but I solved it 2 hours ago :)

For the solution I had a look at these two posts: 
https://community.st.com/t5/stm32-mcus/dma-is-not-working-on-stm32h7-devices/ta-p/49498  https://en.eeworld.com.cn/mp/STM32/a60611.jspx 

I found that the actual problem was related to memory access: the buffer I used for the audio data (audioBuffer) was placed in DTCM RAM (starting at address 0x20000000) by default. However, DMA1 on the STM32H7 series cannot access DTCM. According to the reference manual (RM0433), DMA1 and DMA2 can only access specific RAM regions like AXI-SRAM, SRAM1-3 (D2 domain), and SRAM4 (D3 domain).

To solve the problem, I explicitly placed the buffer into RAM_D2, which is accessible by DMA1:

  •  I added an output section in the linker script to map variables tagged with .RamD2: 
/* Section for variables that must reside in RAM_D2 (for DMA) */
/* All variables marked with __attribute__((section(".RamD2"))) go here */
.RAM_D2 (NOLOAD) :
{
  . = ALIGN(4);
  *(.RamD2)       
  . = ALIGN(4);
} >RAM_D2​
  • In my source code, I added the attribute to the buffer:
__attribute__((section(".RamD2"))) int32_t audioBuffer[AUDIO_BUFFER_SIZE];​

After this change, the DMA transfer started working immediately — data is now written into the buffer, and the DMA complete callback is triggered as expected.