cancel
Showing results for 
Search instead for 
Did you mean: 

[Novice] Unable to get I2S data from F407G-DISC1 onboard microphone

APara.6
Associate II

I've tried so much stuff from official examples, unofficial examples, AI, debugging, forum posts, etc., that at this point I think it might be best to describe my understanding of what should be necessary to access the onboard microphone, and hope that there's an expert out there who can correct my mistake.
~~~~

The goal is to set up an I2S channel to receive Pulse-Density-Modulated data from the microphone, which is then written by Direct Memory Access to a buffer in the main memory. Interrupt Requests must be configured to fire when the buffer is filled, because “Polling Mode” is deprecated.

The I2S driver file instructs that the following must be done:

  • Create an I2S handle to be used as a parameter in DMA-related functions.

  • Call HAL_I2S_MspInit() to configure a DMA/SPI handle, among other things.

  • Call HAL_I2S_Init()

  • Call HAL_I2S_Receive_DMA(), specifying a destination buffer as a parameter.

The DMA driver file instructs that the following must be done:

  • “Enable and configure the peripheral to be connected to the DMA Stream.” No instructions are given for this, but I am guessing that this is what’s done in the I2S setup.

  • Create a DMA handle to be used as a parameter in DMA-related functions.

  • Call __HAL_RCC_DMA1_CLK_ENABLE() {Can’t completely verify, because it is defined in a preprocessor conditional segment.}

  • Call HAL_DMA_Init()

  • Call HAL_NVIC_SetPriority() {Breakpoint trips several times?}

  • Call HAL_NVIC_EnableIRQ() {Breakpoint trips several times?}

  • Call HAL_DMA_Start_IT()

I have verified as far as I can that all of the above steps are reached, according to debug break points. Here are what my I2S and DMA handles look like:

 

  hi2s2.Instance = SPI2;
  hi2s2.Init.Mode = I2S_MODE_SLAVE_RX;
  hi2s2.Init.Standard = I2S_STANDARD_MSB;
  hi2s2.Init.DataFormat = I2S_DATAFORMAT_24B;
  hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
  hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_48K;
  hi2s2.Init.CPOL = I2S_CPOL_LOW;
  hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
  hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
    hdma_spi2_rx.Instance = DMA1_Stream3;
    hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
    hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;
    hdma_spi2_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

 

If everything is successful, the callback HAL_DMA_IRQHandler() should fire when a DMA operation is complete.

The current implementation leaves the I2S handle’s state as HAL_I2S_STATE_BUSY_RX, and the DMA handle's state as HAL_DMA_STATE_BUSY which I’m pretty sure is what it’s supposed to be for ongoing reception. However, HAL_DMA_IRQHandler() is never called, and the destination buffer remains empty. Note that I'm not trying to actually do anything with the data, not even convert the PDM to PCM; at this point I just want to see it arriving in the buffer.

 

I was hoping to be teaching myself some DSP techniques by now, but it seems that I'm stuck at the starting line! I've uploaded my project, minus the large "debug" directory, for you to investigate. Any help would be greatly appreciated.

1 REPLY 1
SofLit
ST Employee

Hello,

Why don't you use the board BSP from F4 CubeHAL?:

https://github.com/STMicroelectronics/stm32f4discovery-bsp/blob/49fcaf442e7d9b5970567eb0c833d66d1333e726/stm32f4_discovery_audio.c

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.