Page 1 of 2

STM32F4 Audio Buffer Glitch

Posted: Wed May 10, 2017 8:11 pm
by everdrone
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

Re: STM32F4 Audio Buffer Glitch

Posted: Thu May 11, 2017 9:21 am
by steved
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

Re: STM32F4 Audio Buffer Glitch

Posted: Thu May 11, 2017 1:31 pm
by everdrone
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

Posted: Fri May 12, 2017 1:55 am
by everdrone
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).

Image
Image

Any idea on how i can get rid of this?

Thanks again.

Re: STM32F4 Audio Buffer Glitch

Posted: Sat May 13, 2017 7:36 am
by Giovanni
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

Re: STM32F4 Audio Buffer Glitch

Posted: Sat May 13, 2017 3:18 pm
by everdrone
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.

Re: STM32F4 Audio Buffer Glitch

Posted: Sat May 13, 2017 3:24 pm
by Giovanni
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

Re: STM32F4 Audio Buffer Glitch

Posted: Sat May 13, 2017 3:40 pm
by everdrone
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);
, but it is enabled and configured along with the DMA driver.
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!)

Re: STM32F4 Audio Buffer Glitch

Posted: Sat May 13, 2017 4:55 pm
by Giovanni
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

Re: STM32F4 Audio Buffer Glitch

Posted: Sat May 13, 2017 6:38 pm
by everdrone
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