2023-12-04 01:17 PM
Hi,
I use a STM32F767 Nucleo-144 board with a STM32F767ZIT6 processor.
With CubeIDE I configure SPI1 as I2S1 input and pump the data via DMA2/Stream0 in a short 8x16Bit circular buffer. The clock of the SPI1 is at ~ 3MHz .I set up the HAL_I2S_RxHalfCpltCallback() and HAL_I2S_RxCpltCallback() routines. In both routines i toggle a GPIO and get a ~23.8kHz square wave. This all works as exspected.
But: The square wave suffers from a big jitter. First, there is a constant jitter in the range of 100ns. Second, sometimes the duty cycle (not the frequency) of the signal changes by ~330ns for some parts of a second. 330ns ist the reciprocal of my 3MHz clock.
How can I get rid of the jitter? I tried to slim down HAL_DMA_IRQHandler() to the necessary parts for my use case. That did not affect the jitter. I also changed the NVIC priorities with no effect.
How can I get rid of the jitter?
THX
Cheers
Detlef
Solved! Go to Solution.
2023-12-04 05:27 PM
Probably the SysTick occasionally adds a delay.
You can make a synchronous square wave by using another SPI slave, hooking up the SCK between then and outputting 0x00FF or similar on the MISO pin in a circular buffer.
2023-12-04 03:59 PM
You cannot eliminate the jitter entirely, at least not in the general case, but you can get it to within about 12 ticks. by discarding HAL (at least the interrupt portion) and writing your own interrupt routine and ensuring that particular interrupt has the highest priority.
Why is jitter critical here? There are likely other ways to achieve what you want. Square waves can be generated by a PWM signal on a timer, for instance. The SPI signal should be constant with a 3 MHz clock despite the jitter in the IRQ handler.
2023-12-04 05:09 PM
Hi, the uC runs at 192MHz, so 12 ticks result in a ~60ns jitter, which matches with the measured < 100ns jitter. But, as mentioned, I get these 1/3MHz~330ns jumps in the 'duty cycle' of the square wave.
The 23.8kHz ultrasonic signal ist sampled with the 3MHz MEMS-mic. The phase of the audio signal is resolved with 0.5° accuracy which results in ~59ns. So the 12ticks jitter is 'noise' for me but I clearly see the 330ns jumps as artefacts. I do understand the 12ticks jitter but I do not understand the 330ns jitter.
I also tried to generate a square wave with a timer, which is syncronous to the SPI clock. The datasheet claims '95238Hz' sample rate for '96k' I2S mode. The exact number could be 192E6/2016=95238.09524 Hz. So dividing the uC clock by 192E6/(4*2016) could result in a syncronous 23.80952381kHz clock :) . Until now I could not get the timer output syncronous to the SPI clock, but with the 4*2016 division it could work, worth a try.
THX Cheers Detlef
2023-12-04 05:27 PM
Probably the SysTick occasionally adds a delay.
You can make a synchronous square wave by using another SPI slave, hooking up the SCK between then and outputting 0x00FF or similar on the MISO pin in a circular buffer.
2023-12-05 01:29 PM
Hi, I managed to configure a timer so that the square wave is syncronous to the SPI interrupt, no phase slipping. I'm not happy with the solution, because I do not understand the origin of the 330ns jitter (It is not from the systick interrupt). I know that an issue you do not understand will fire up problems at the worst point in time :| .
THX
Cheers
Detlef
2023-12-05 02:33 PM
Glad you could get what you wanted.
If you wanted to chase it down, one way to understand what interrupts are happening is to, within your main loop, do __disable_irq(), wait a few seconds, then examine NVIC registers to see what interrupts are pending. That will show them all 100%.
Could be that you have DMA and I2S happening and they're not happening in the order that you want.
But the processor is a state machine and should behave the same given the same conditions. It is not prone to fickle behavior. The M7 core is complex and can vary by a few cycles due to various optimizations and internal shortcuts, but not by 330ns.
2023-12-05 03:19 PM
First, there is a constant jitter in the range of 100ns.
If you mean "constant delay", then that is not jitter, but latency. Jitter is a timing noise, not a constant offset. The same with the 12 clock cycles - that is an interrupt enter/exit latency.
On this MCU for I2S the SAI peripheral is preferred instead of the SPI peripheral. And you haven't explained what you are trying to achieve. For example, the two SAI peripherals can provide up to four synchronized I2S streams.
2023-12-05 04:30 PM
Hi, I mean jitter, not delay. A constant jitter of 100ns is timing noise of max 100ns. Stochastic timing noise for interrupts is normal, because the delay from interrupt happening to servicing is dependent on processor state.
I service a raw pulsetrain from a MEMS-MIC. I want to measure the ultrasonic time-of-flight by its phase.
Cheers Detlef
2023-12-05 06:32 PM
So basically you need to somehow count the 3 MHz pulses? The MEMS microphone outputs a digital PDM stream. Why don't you just count the bits in the captured bytes?
2023-12-06 12:43 AM
The bitstream is my broadband signal including my 23.8kHz audio signal of interest. I use Goertzel algorithm to calculate the phase ( and amplitude ) at that frequency. Goertzel is represented by a recursive 2.order IIR-filter. I pump the bits through that filter and get the phase. The sampling frequency ~3MHz and the audio 23.8kHz need a common, syncronous source, a single missing bit shows up as a jump in phase.