STM32F4 Audio Buffer Glitch
Moderator: RoccoMarco
STM32F4 Audio Buffer Glitch
Hi all, i'm fresh new to this forum and relatively new to embedded programming (learning it by myself)
It's been a few months now that i'm stuck on a noise coming out of the jack plug whenever the STM32 Discovery Board is powered on and connected (via the audio jack) to my audio interface, even if the board's output is not routed to the speakers.
This 6kHz noise is related to the audio buffer size, since i'm working with a sample rate of 48kHz and the buffer is 8 elements long, 48000 / 8 = 6000.
I also tried to double the buffer size and as expected the noise frequency fell down by half of its initial value.
I uploaded a reduced version of the source code.
I removed all the unnecessary code to avoid getting you guys lost in what has nothing to do with hardware and peripherals configuration.
My guess is that whenever the codec reaches the end of the buffer, it outputs an extra sample that produces this glitch.
Since i'm not very confident with all the peripheral configurations involved in the code, i ask you guys help.
If not resolving this mind twisting bug, at least help me isolate the problem to a specific driver configuration so that i can work on it by myself.
I'll copy the content of the Readme.md in the repository to give you some instructions on how the code is distributed across the project.
globals.h - contains the global declarations and definitions (such as the buffer size)
codec.h - is where the codec is initialized and all the relative peripherals are configured
processing.h - contains the function called by the DMA interrupt callback (located in codec.h), this produces just a simple sine wave.
main.cpp - well, as you can guess it's where all is initialized (main thread and DSP thread)
Thank you in advance for your time, i understand my question is not specific and immediate but i think the problem is strictly related to some bad configurations of mine, and this is really twisting my mind.
Hope I have given you all the necessary information, if not, please let me know and i'll provide more.
Thank you again.
/giorgio
It's been a few months now that i'm stuck on a noise coming out of the jack plug whenever the STM32 Discovery Board is powered on and connected (via the audio jack) to my audio interface, even if the board's output is not routed to the speakers.
This 6kHz noise is related to the audio buffer size, since i'm working with a sample rate of 48kHz and the buffer is 8 elements long, 48000 / 8 = 6000.
I also tried to double the buffer size and as expected the noise frequency fell down by half of its initial value.
I uploaded a reduced version of the source code.
I removed all the unnecessary code to avoid getting you guys lost in what has nothing to do with hardware and peripherals configuration.
My guess is that whenever the codec reaches the end of the buffer, it outputs an extra sample that produces this glitch.
Since i'm not very confident with all the peripheral configurations involved in the code, i ask you guys help.
If not resolving this mind twisting bug, at least help me isolate the problem to a specific driver configuration so that i can work on it by myself.
I'll copy the content of the Readme.md in the repository to give you some instructions on how the code is distributed across the project.
globals.h - contains the global declarations and definitions (such as the buffer size)
codec.h - is where the codec is initialized and all the relative peripherals are configured
processing.h - contains the function called by the DMA interrupt callback (located in codec.h), this produces just a simple sine wave.
main.cpp - well, as you can guess it's where all is initialized (main thread and DSP thread)
Thank you in advance for your time, i understand my question is not specific and immediate but i think the problem is strictly related to some bad configurations of mine, and this is really twisting my mind.
Hope I have given you all the necessary information, if not, please let me know and i'll provide more.
Thank you again.
/giorgio
Re: STM32F4 Audio Buffer Glitch
Not sure how often the I2C is involved, but could see some issues in that area:
1. You don't need to use chSysLock() and chSysUnlock() - in simplistic terms they're roughly equivalent to disabling interrupts.
2. i2cStart() is usually a one-time operation during initialisation (along with the pin setup); it sets up the peripheral, DMA etc. You would only need to use i2cStop() if you're sharing DMA channels with some other peripheral device.
3. You may not need i2cAcquireBus() and i2cReleaseBus() - they use mutexes to manage access to the i2c peripheral. So if your code has only a single thread which may access the i2c, you don't need them.
There's more info here - including somewhere (I couldn't find it on a quick look!) an article covering system locks etc
1. You don't need to use chSysLock() and chSysUnlock() - in simplistic terms they're roughly equivalent to disabling interrupts.
2. i2cStart() is usually a one-time operation during initialisation (along with the pin setup); it sets up the peripheral, DMA etc. You would only need to use i2cStop() if you're sharing DMA channels with some other peripheral device.
3. You may not need i2cAcquireBus() and i2cReleaseBus() - they use mutexes to manage access to the i2c peripheral. So if your code has only a single thread which may access the i2c, you don't need them.
There's more info here - including somewhere (I couldn't find it on a quick look!) an article covering system locks etc
Re: STM32F4 Audio Buffer Glitch
steved wrote:Not sure how often the I2C is involved, but could see some issues in that area:
1. You don't need to use chSysLock() and chSysUnlock() - in simplistic terms they're roughly equivalent to disabling interrupts.
2. i2cStart() is usually a one-time operation during initialisation (along with the pin setup); it sets up the peripheral, DMA etc. You would only need to use i2cStop() if you're sharing DMA channels with some other peripheral device.
3. You may not need i2cAcquireBus() and i2cReleaseBus() - they use mutexes to manage access to the i2c peripheral. So if your code has only a single thread which may access the i2c, you don't need them.
There's more info here - including somewhere (I couldn't find it on a quick look!) an article covering system locks etc
Thanks very much for the answer, for pointing me in the right direction.
I'll sure check out the wiki article again for a deeper read.
Re: STM32F4 Audio Buffer Glitch
So i removed the functions you told me weren't supposed to be there, updated the repository (added the build folder with the .bin and .hex files) so you can check the thing out without building the whole project yourself.
I set the buffer size to 64 (to lower down the noise to a more clear audible frequency) and here it is again.
At the moment the sine wave is muted so that the noise is the only signal coming out.
Here are some screenshots of what it looks like in the audio spectrum (and scope).


Any idea on how i can get rid of this?
Thanks again.
I set the buffer size to 64 (to lower down the noise to a more clear audible frequency) and here it is again.
At the moment the sine wave is muted so that the noise is the only signal coming out.
Here are some screenshots of what it looks like in the audio spectrum (and scope).


Any idea on how i can get rid of this?
Thanks again.
- Giovanni
- Site Admin
- Posts: 14893
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 997 times
Re: STM32F4 Audio Buffer Glitch
Hi,
It looks like the DMA is reading beyond your buffer and outputting random data, could you try putting a zeroed zone after the I2S buffer? that would confirm that it is DMA-related.
Giovanni
It looks like the DMA is reading beyond your buffer and outputting random data, could you try putting a zeroed zone after the I2S buffer? that would confirm that it is DMA-related.
Giovanni
Re: STM32F4 Audio Buffer Glitch
Giovanni wrote:Hi,
It looks like the DMA is reading beyond your buffer and outputting random data, could you try putting a zeroed zone after the I2S buffer? that would confirm that it is DMA-related.
Giovanni
Hi Giovanni, thanks for the interest towards my problem here.
As for now, it's quite difficult for me to know how to align memory blocks within the ARM context, by the way, i tried to make the buffer longer by declaring it with:
Code: Select all
// was BUFSIZE * 2
static int32_t buffer1[BUFSIZE * 3];and changed the clearbuffer methord accordingly:
Code: Select all
void clearBuffer(int32_t* buffer) {
// was BUFSIZE * 2
for (int i = 0; i < BUFSIZE * 3; ++i) {
buffer[i] = 0;
}
}The noise is still present, at this point i don't even know if it's me not being able to put a zeroed zone after the array or the bug being somewhere else (not the DMA)
By the way, the noise sounds and looks exactly the same as shown in the pics from my last reply.
Could you suggest me a way to properly clear the zone right after the buffer?
Thanks again for the help.
- Giovanni
- Site Admin
- Posts: 14893
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 997 times
Re: STM32F4 Audio Buffer Glitch
Hi,
Extending the buffer should be fine, it is zeroed by startup files so you don't even need to clear it.
Have you tried the I2S driver in HAL? I never tested it in that scenario.
Giovanni
Extending the buffer should be fine, it is zeroed by startup files so you don't even need to clear it.
Have you tried the I2S driver in HAL? I never tested it in that scenario.
Giovanni
Re: STM32F4 Audio Buffer Glitch
Giovanni wrote:Hi,
Extending the buffer should be fine, it is zeroed by startup files so you don't even need to clear it.
Have you tried the I2S driver in HAL? I never tested it in that scenario.
Giovanni
Hi Giovanni, never tested I2S driver myself, given my unexperience i can barely understand what you are asking me to do.
I know this is bothering you a little, with a little more knowledge in the matter i could give you a more accurate answer and try myself, do you think we should move this to a private (maybe email) conversation?
By the way, the I2S driver is not even configured "the standard way"
Code: Select all
i2sStart(&driver, &config);Maybe this could be the problem?
Code: Select all
bool codec_i2s_init() {
palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOA, 4, PAL_MODE_ALTERNATE(6));
palSetPadMode(GPIOC, 10, PAL_MODE_ALTERNATE(6));
palSetPadMode(GPIOC, 12, PAL_MODE_ALTERNATE(6));
CODEC_I2S_ENABLE;
CODEC_I2S->I2SCFGR = SPI_I2SCFGR_I2SMOD
| SPI_I2SCFGR_I2SCFG_1
| SPI_I2SCFGR_DATLEN_1;
CODEC_I2S->I2SPR = SPI_I2SPR_MCKOE
| SPI_I2SPR_ODD
| 3;
bool statinit = codec_dma_init();
CODEC_I2S->CR2 = SPI_CR2_TXDMAEN;
CODEC_I2S->I2SCFGR |= SPI_I2SCFGR_I2SE;
return statinit;
}Thanks again for your time (and the anwer speed!)
- Giovanni
- Site Admin
- Posts: 14893
- Joined: Wed May 27, 2009 8:48 am
- Has thanked: 1202 times
- Been thanked: 997 times
Re: STM32F4 Audio Buffer Glitch
Hi,
The HAL I2S driver is initialized like all others, clocks are enabled and DMAs allocated in the start function, I don't understand what you mean with non standard.
Giovanni
The HAL I2S driver is initialized like all others, clocks are enabled and DMAs allocated in the start function, I don't understand what you mean with non standard.
Giovanni
Re: STM32F4 Audio Buffer Glitch
Giovanni wrote:Hi,
The HAL I2S driver is initialized like all others, clocks are enabled and DMAs allocated in the start function, I don't understand what you mean with non standard.
Giovanni
Hi, sorry
I just meant the driver is not initialized by calling the i2sStart() function, that configuration is passed piece after piece and not wrapped into an I2SConfig struct. but from what you just stated i know it doesn't matter.
Have you any idea on how this noise problem can be solved?
Thanks in advance