2016-12-06 05:00 AM
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!
regardsJanThe 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-i2sSolved! Go to Solution.
2016-12-09 04:42 AM
Hi Walid,
I am well aware of that fact. But my problem is, that the callback function that should be called by IRQhandler are not called. So how i am supposed to get my data out of I2S buffer? I know i should do it in callback function, but it is not called. Am I missing something? Do i need to manually enable specific interrupt sources 1/2 RxCplt and so on? Thanks Jan2016-12-09 04:57 AM
Another point i just found out on this issue is following:
In the HAL_I2S_Receive_DMA(); i have found something what i believe is callback function registration.
/* Set the I2S Rx DMA Half transfer complete callback */
hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt;
/* Set the I2S Rx DMA transfer complete callback */
hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt;
/* Set the DMA error callback */
hi2s->hdmarx->XferErrorCallback = I2S_DMAError;
But when i look into HAL_I2S_Receive_IT(); i cant see the same thing there. So this is why my callbacks are not called?
Please, is there any ST official who could give me answer on my issue?Thank you very much
Jan
2016-12-09 08:18 AM
Hi
Slavot_nek.Jan
,
,As indicated in the comments , these code lines are dedicated to enable the HT and TC of DMA .
In case of interrupt transfer, the call back is called inside the
HAL_I2S_IRQHandler().
If the handler is not reached means that is not configured in the NVIC registers. You should add the NVIC configuration of the SPI/I2S IRQ as example below:
HAL_NVIC_SetPriority(SPIx_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPIx_IRQn); where x =1 or 2Another thing should be doneas best practice : Before starting a new communication transfer, you need to check the current state of the peripheral; if it’s busy you need to wait for the end of current
transfer before starting a new one.while (HAL_I2S_GetState(&I2sHandle) != HAL_I2s_STATE_READY)
{ }Hope everything is clear now for you.
Note: ST engineer in this community as the ST badge near to their names.
-Walid F-
2016-12-09 10:21 AM
The thing is that i am using CubeMX to configure. So everything is actually done already. Even NVIC setup is done automatically, i have double checked the settings made by Cube NVIC, GPIOs, clock, everything seems to be configured.
I might didnt mention that i was planning to use pure interrupt to get my PDM data. I thought that this interrupt style would be easier to implement. But now i am considering using DMA style to handle that, because it is done this way in the example from ST. But again here example is actually not so much helpful when i want to use CubeMX to configure. I have never used DMA before, so i am not so sure how link my memory buffer to DMA and how setup everything.
2016-12-09 01:19 PM
So i have configure everything just the very same way as it is in audio example. But my DMA interrupt callback HAL_I2S_RxCpltCallback() jsut dont occure.
#define DEFAULT_AUDIO_IN_FREQ 16000
#define DEFAULT_AUDIO_IN_CHANNEL_NBR 1
#define INTERNAL_BUFF_SIZE 128 * DEFAULT_AUDIO_IN_FREQ / 16000 * DEFAULT_AUDIO_IN_CHANNEL_NBR
uint16_t InternalBuffer[INTERNAL_BUFF_SIZE];
I am calling HAL_I2S_Receive_DMA(&hi2s2, InternalBuffer, INTERNAL_BUFF_SIZE); to start the process.
2016-12-12 01:44 AM
Hello there,
I am again working on my project. And during todays debugging i have found very strange behavior.
So in driver file''stm32f4xx_hal_i2s.c''
there are two functions that are setting up DMA Rx Callbacks:/* Set the I2S Rx DMA Half transfer complete callback */
hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt;
/* Set the I2S Rx DMA transfer complete callback */
hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt;
If i go to
I2S_DMARxHalfCplt()
it brings me to the same file''stm32f4xx_hal_i2s.c'' and this function is directly called
HAL_I2S_RxHalfCpltCallback(hi2s);
that is declared in my own .c file (it is weak ...) . This really works, this halp cplt callback is called and when debugging i get into my .c file where i define my version ofHAL_I2S_RxHalfCpltCallback(hi2s);
Problem is in case of
I2S_DMARxCplt()
. If i go to definition of that, it brings me to file''stm32f4xx_hal_i2s_ex.c''
. Here i can see some code lines (i guess it has something to do with handeling of buffer and so on) and at the end of function there isHAL_I2S_RxCpltCallback(hi2s);
. Great but when debugging, i get to this lineHAL_I2S_RxCpltCallback(hi2s);
and then program doesnt goes to my definition ofHAL_I2S_RxCpltCallback(hi2s);
, but it says ''no source code availible forHAL_I2S_RxCpltCallback(hi2s);
. When i look to disassembly, i can see that actually there is code for my implementation of that callback. So this is explenation why i never ''catch'' the code with breakpoint inserted to myRxCpltCallback
.Its like compiler would remove my RxCpltCallback, but in disassembly i can see it.
Any Ideas? Thanks Jan
2016-12-12 02:32 AM
Ok so now both callbacks stops when breakpoint is inserted. I needed to make both callbacks different, so when i added ++Data_Status; to halfCplt now i can observe how both callbacks are comming alternately.
2016-12-12 09:57 AM
OK so now i got to the point, where i can record full buffer on RAM of PCM data and store on flash drive in .wav in one shot.
I have made a discovery: When i have set up i2s 'audio frequency' = 16 KHz, that means i2s is gonna make 16 000 * 64 PDM stream, that will result in 16KHz PCM sampling rate that means actual audio frequency tha i must fill to .wav header is 16/2 = 8KHz right? At leaset that is what i have observed. Can anyone confirm that? Thanks Jan2016-12-13 09:06 AM
Lets consider this thread to be solved. Original questions about not calling interrupt callbacks seems to be solved right now. But another serious problems occured when i want to simultaneously run i2s data aquisition process and storing data to my flesh drive:
Thanks in advance for any answers on that topic.2016-12-13 09:09 AM
Probably code didnt went into the callbacks because compiler removed them during optimalization as it seemed to be unnecessary code ...