cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f4 discovery mems microphone over i2s cant get it running

Posted on December 06, 2016 at 14:00

Hi community! 

Jan Here, Cezch Republic. 

I am working on my project where i need to process audio for further uses. My first step is obviously get my data from mic. I have decided to use the MP45DT02 MEMS mic that is present on my stm32f4 discovery board. 

I have already successfully got working example (Audio_playback_and_record). I used that example to help me understand basics of .wav and also pdm lib. I have also observed settings necessary for setting up i2s2. I replicated those settings using CubeMX and created project. Now i am facing following problem:

I never receive interrupt when debugging ( SPI2_IRQHandler(); is never called). So what am I missing? I have thoroughlly read through comments at stm32f4xx_hal_i2s.c librarry. I believe most of the actions (settings) were actually made by CubeMX so i dont need to do anyting. I would expect i2c start generating clock for the MEMS mic and i would expect pdm stream to start flowing. But its not. So i said to my self, that it is necesarrry to call some kind of start function to get the peripherral running (like when using ADC's one need to call HAL_ADC_Start_IT(&hadcx)), but i cant find any 'i2s_start()' function at the library. 

Any help would be appreciated!

regards

Jan

The I2S HAL driver can be used as follow:

(♯) Declare a I2S_HandleTypeDef handle structure.

(♯) Initialize the I2S low level resources by implement the HAL_I2S_MspInit() API:

(♯♯) Enable the SPIx interface clock.

(♯♯) I2S pins configuration:

(+++) Enable the clock for the I2S GPIOs.

(+++) Configure these I2S pins as alternate function pull-up.

(♯♯) NVIC configuration if you need to use interrupt process (HAL_I2S_Transmit_IT()

and HAL_I2S_Receive_IT() APIs).

(+++) Configure the I2Sx interrupt priority.

(+++) Enable the NVIC I2S IRQ handle.

(♯♯) DMA Configuration if you need to use DMA process (HAL_I2S_Transmit_DMA()

and HAL_I2S_Receive_DMA() APIs:

(+++) Declare a DMA handle structure for the Tx/Rx stream.

(+++) Enable the DMAx interface clock.

(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.

(+++) Configure the DMA Tx/Rx Stream.

(+++) Associate the initialized DMA handle to the I2S DMA Tx/Rx handle.

(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the

DMA Tx/Rx Stream.

(♯) Program the Mode, Standard, Data Format, MCLK Output, Audio frequency and Polarity

using HAL_I2S_Init() function.

-@- The specific I2S interrupts (Transmission complete interrupt,

RXNE interrupt and Error Interrupts) will be managed using the macros

__I2S_ENABLE_IT() and __I2S_DISABLE_IT() inside the transmit and receive process.

-@- Make sure that either:

(+@) I2S PLL is configured or

(+@) External clock source is configured after setting correctly

the define constant EXTERNAL_CLOCK_VALUE in the stm32f4xx_hal_conf.h file.

#pdm #i2s #stm32f4-discovery #programming-i2s
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on December 13, 2016 at 18:09

Probably code didnt went into the callbacks because compiler removed them during optimalization as it seemed to be unnecessary code ...

View solution in original post

19 REPLIES 19
Walid FTITI_O
Senior II
Posted on December 06, 2016 at 18:04

Hi

slav3k

,

You should start your transfer by using the transmit and receive start functions in the driver either you use polling or DMA or interruption:

  • Polling mode:

HAL_I2S_Transmit()

HAL_I2S_Receive()

  • DMA mode:

HAL_I2S_Transmit_DMA()

HAL_I2S_

Receive

_DMA()

  • Interruption mode:

HAL_I2S_Transmit_IT()

HAL_I2S_Transmit_IT()

I recommend that you check the ready-to-use example 'I2S_Audio' in

http://www.st.com/en/embedded-software/stm32cubef4.html

at this path:STM32Cube_FW_F4_V1.0\Projects\STM324xG_EVAL\Examples\I2S\I2S_Audio

Note that in the example, the I2S transmit/receive start function are putted inside the BSP Audio driverstm324xg_eval_audio.c

-Walid FTITI-

Ifthe response is useful, you would mention that by clicking the correct botton. Thank you for the contribution

Posted on December 07, 2016 at 10:14

Hi Walid!

So i took a look at the example you are reffering to. 

First thing that supprised me is, that in that example, there is newer version of 'stm32f4xx_hal_i2s.c'. It is  V1.6.0 with date 04-November-2016. The one i am using (ono that was 'given' to me by CubeMX) is V1.5.2 from 22-September-2016. I am wondering, why my cube doesnt have updated libs. Do i have to force update or smthing ? 

The difference between those two seems to be considerable. The 

V1.6.0 has a lot mor functions in it then V1.5.2 . Never mind.

In example you are reffering to, i can find, that they are using DMA option for handeling I2S date. Therfore for starting the process, they use  HAL_I2S_Receive_DMA(&hAudioInI2s, pbuf, size);. Ok no problem, i can use IT equivalent HAL_I2S_Receive_IT();. There i suppose the first date this function return is dummy date right? Or does it return anything, when i will call that function out of the blue without previous interrupt event?

In the example, for stopping or pausing the process they use HAL_I2S_DMAStop(&hAudioInI2s); function, that is availible in V1.6.0 of library. Unfortunately, it is availible only for DMA. Not for IT. So what should use as equivalent for me, when i would like to stop/pause the proces using IT variant of I2S handling? 

Thank you very much

Have a nice day

Jan 

EDIT: My I2S interrupt when i call HAL_I2S_Receive_IT(); at start come once, but then it is not comming continuously. 
Posted on December 07, 2016 at 12:29

Hi

Slavot_nek.Jan

,

You shoudl always check for update in the CubeMx tool and update/ download the latest versions.

-Walid F-

Posted on December 07, 2016 at 13:53

Hey there,

I would recommend to get familiar a bit with the HAL library first... The IT functions are designed that way, that you need to call the Receive_IT() functions in advance to be able to receive something. These functions actually enable the reception of the peripheral. Now I'm talking in general. After the peripheral receives some data, an interrupt is generated, where the Rx-IT is stopped (an IT flag for reception is cleared) and a callback function can be called. These callback functions are in general __weak, so if you don't redefine them, the HAL won't complain, but you won't receive next messages. So in the callback function it's advised to call the Receive_IT flag again or call it somewhere else in your code.

Hope this helps a bit! Have a nice day,

Renegade

Posted on December 08, 2016 at 10:49

Hi!

So, i have updated my cube and now i have my libs up to date.

I am now using HAL_I2S_Receive_IT(); to iniciate reception of data. It causes my interrupt callback HAL_I2S_RxCpltCallback(); to be called once. That is ok. So inside callback i read the data HAL_I2S_Receive_IT(hi2s, &app, 1) and was hoping, that this read will initiate another data reception. But unfortunatelly, it is not. Another words: It goes only once to callback HAL_I2S_RxCpltCallback();. So now i am bit confused. I use HAL_I2S_Receive_IT(); but it seems like reception is not repeating. Why? 

Thanks 

Jan

For initiation u use my func: 

void I2S_PeriphStart(void){

uint16_t u16Buff = 0;

HAL_I2S_Receive_IT(&hi2s2, &u16Buff, 1);

}

And there is callback:

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)

{

uint16_t volume = 0;

uint16_t app = 0;

u8DebugVar = 1;

if(HAL_I2S_Receive_IT(hi2s, &app, 1) != HAL_OK){

while(1){

}

}

}

Posted on December 09, 2016 at 09:05

 

My Further studies of example of audio application by STM shows, that i probably dont understand how I2S works. I dont understand, why they are using both HalfTransfer_CallBack and TransferComplete_CallBack. I mean, isnt it enough wait till transfer complete comes and take data to buffer? What am I supposed to do when HalfTransfer is done anywway? Why should i take half the data? Or is it the problem, that the buffer is small and cpu cant guarantee that it can take whole data word in time, so its safer to take data in two halves? 

Can anyone advice me on that matter? 

Thanks

Jan 
Posted on December 09, 2016 at 10:57

I have made new observation. HAL_I2S_IRQHandler();  interrupt is actually occurring after i start process with

HAL_I2S_Receive_IT()

! Inside the handler i can see I2S_Receive_IT(hi2s); to be used, but i cant see that the handler would actually call the callbacks (

TransferComplete_CallBack AND/OR 

HalfTransfer_CallBack). Why is that? So am i supposed to write my code directly into HAL_I2S_IRQHandler()? This seems t obe really odd...

Another confusion for me is, that there are two 2 driver files: 'stm32f4xx_hal_i2s.c' and 'stm32f4xx_hal_i2s_ex.c'. Most of the functions are just duplicated in the 'ex' version. I have noticed when i was debugging that by default HAL_I2S_IRQHandler(); leads into 'ex' version ...
Posted on December 09, 2016 at 12:22

Hi JAn, 

There is a low livel driver packages which ST is delivering by device series to give user more easy and flexible user with HAL.

For STM32F4 is not yet delivred, other devices are already published like F0, L1, L4.

Meanwhile, you can disable the unwanted transfer interrupt like the half transfer by adding a defined macros located in DMA header file just after the transfer function like following :

/*Disable the HT interrupt */

__HAL_DMA_DISABLE_IT(DMA_IT_HT);

-Walid F-

Posted on December 09, 2016 at 12:28

Hi Jan , 

With HAl architecture, User is allowed to add his code inside the call back function called inside the predefined IRQHandler. the state machine

implemented

make from IRQhandler a fixed driver function shouldn't modified which calls the relevant callback to do a specific ISR processing .

-WalidF-