cancel
Showing results for 
Search instead for 
Did you mean: 

Interrupt Service Routine Jitter

DetlefS
Associate III

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

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

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.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

22 REPLIES 22
TDK
Guru

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.

 

If you feel a post has answered your question, please click "Accept as Solution".
DetlefS
Associate III

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

TDK
Guru

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.

If you feel a post has answered your question, please click "Accept as Solution".
DetlefS
Associate III

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

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.

If you feel a post has answered your question, please click "Accept as Solution".
Piranha
Chief II

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.

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

Piranha
Chief II

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?

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.