2021-11-28 09:41 AM
I have tried different browsers.
It was started by me and there have been some responses because I got notifications.
2021-11-28 09:47 AM
Yes, two answer seem to have been deleted would be my guess
https://community.st.com/s/global-search/weird%20jitter
2021-11-28 10:14 AM
I posted some detail about a project, with DSO screenshots, in the hope that someone may have an idea. I won't do it again; don't have a copy, and having spent a day or two on it I did eventually find a usable solution. I posted it at the end of here
The reason for the jitter is now fairly obvious but why the solution works I have no idea. The 32F4 is so complex...
2021-11-28 10:55 AM
I write response, but i repeat here, you plan generate clean sine with variable freq, simple way is DAC DMA circular on sine table. You cant stop DMA or DAC you need only manage timer that triggers DMA sample rate. Try this as first.
2021-11-28 11:13 AM
Yes that's exactly what I am doing. TIM4 triggers both DACs (actually I think only one DAC actually needs triggering) and one of them triggers DMA1 stream 5 to load the data, which goes into both DACs in the dual (32 bit) mode.
The challenge - see the eevblog link above - was to sync the generated waveform to the zero crossings of an input reference waveform. I have nan ISR which occurs very accurately on the reference waveform edges and is very short - a few us. This ISR a) resets the DMA pointers (DMA is in circular double buffer mode) and transfer count and b) zeroes TIM4.
b) is not totally necessary if you have lots of samples per cycle, otherwise just resetting the DMA will make the output drift around within 1 sample period, which is very visible with say 64 samples per cycle, hence I am resetting TIM4 as well.
When I started doing the TIM4 bit, I found strange effects. After much experimentation I got it all going nicely but the solution doesn't make sense - it involves not zeroing TIM4 but loading a fairly large value into it.
2021-11-28 11:19 AM
This ISR a) resets the DMA this is first fail dma can be reconfigured only in dma transfer complete ISR
try as i write setup dma circular and dont touch his config
touch only TRG source for DAC
2021-11-28 12:00 PM
The RM says DMA has to be disabled (and you wait for the EN bit to go to 0) before you can change the registers. I am doing that, hopefully correctly.
/*
* TIM1 input compare event interrupt handler. Used by waveform period measurement function.
* Process TIM1 CC1IE (CH1 capture) interrupt, generated by CH1 capture of CNT into CCR1, which
* is generated from a +ve edge on PE9.
* There was a problem with jitter in the first two samples after the TIM1 interrupt occurs, which
* is probably related to the zeroing of TIM4 count which is itself necessary to get the subsequent
* output to have the first sample output with the proper constant width.
* Much time was spent on it and the /8L CNT fix below magically works but no idea why.
*
*/
void TIM1_IC_CaptureISR(void)
{
if ( (TIM4->CR1 && ~1) == 1 ) // check wavegen (basically TIM4) is enabled!
{
// Reset TIM4 prescaler+counter chain, to avoid 1-sample-width jitter on output
TIM4->PSC = isr_tim_pre;
// This should obviously be 0 but that produces jitter. This value was determined experimentally
// Works 42Hz (the KDE_config_TIM1_period_measure lower limit) to >1kHz.
TIM4->CNT = isr_tim_tc/8L;
// Update period of wave gen derived from input reference (period=TIM1->CCR1)
// This doesn't need doing often; it is only to track variations in the input frequency but
// here we do it every cycle because it doesn't produce any jitter etc.
// The full formula if pclk1 != pclk2 is wave_tc = (pclk1*2L*(ccr1/((pclk2*2)/32)))/SPC
// The simpler one if pclk1=pclk2 is (ccr1*32)/SPC
// 32 is the prescaler in the measuring code (chosen at 32 to support 50Hz)
TIM4->ARR = (( (TIM1->CCR1-1) * 32 )/isr_num_values);
// Reset DMA pointers and transfer count
dma_s5_copy &= ~1; // disable DMA (to access its cfg regs) & avoiding RMW
DMA1_Stream5->CR = dma_s5_copy;
hang_around_us(1); // wait for DMA to stop (delay not actually needed)
DMA1->HISR = 0x0F40; // 1111 0100 0000 - clear pending int flags (per RM)
DMA1_Stream5->NDTR = isr_num_values; // buffer size
DMA1_Stream5->M0AR = isr_buffer0; // base of table 0
DMA1_Stream5->M1AR = isr_buffer1; // base of table 1
dma_s5_copy |= 1; // re-enable DMA
DMA1_Stream5->CR = dma_s5_copy;
}
TIM1->SR = 0; // Clear CC1IF & UIF - clear pending interrupt
}
My original post was PMd to me - not sure how he found it : - ) It is here:
Hi All,
I am building a sinewave generator which needs to track an input square wave (just the zero crossings of it). The frequency range is 50-500Hz.
I prefill two RAM buffers with sin(x) - using the double buffer DMA mode so that, later on, another RTOS task can modify the amplitude values while the system is running.
I have a frequency meter. I am feeding the input to TIM1 CH1 (PE9) and on +ve edges the counter value gets stored in CCR1. The counter is then zeroed (automatic process). The waveform period can be obtained anytime by reading TIM1-CCR1 and this is done entirely in hardware; no CPU involvement. Typical value in CCR1 is 6560 for 400Hz so the resolution is very good. However, I also interrupt from the event; the ISR is used as described below.
Then I have the waveform generator, which is TIM4 triggering both DACs, and they trigger DMA1 Stream 5 which loads both DACs together in 32 bit mode. I am running with 64 samples per cycle.
The above mentioned ISR does three things:
1) it resets TIM4 (prescaler and counter) to phase-lock the generator to the input. TIM4 is disabled during this counter load (but that doesn't seem to be needed).
2) it resets the DMA buffer pointers and the byte count to the buffer start. DMA is disabled during this counter load, per the RM and it doesn't work otherwise.
3) it uses the TIM1 CCR1 value to update TIM4 speed (ARR), to maintain a frequency match. This needs to happen only every ~1000 cycles but actually I am now doing it on every interrupt because is not the source of the issue described here.
It is all running, but I have (had) two problems:
a) There is amplitude jitter at the +ve going zero crossing of the output sinewave. This extends over the first two DAC samples; about 80us - much longer than the duration of the ISR which I have verified (by waggling an output pin) takes about 4us. The jitter is obviously the previous DAC value along the table being repeated, so it is as if the DMA was taking a long time to get going. More likely the delay is further back i.e. TIM4 taking time to restart counting, or the DACs taking time to generate the DMA request.
b) there is a general phase shift in the output, relative to the input. This is fixed in degrees (around 5 deg) over the whole frequency range. It is actually two DAC sample periods i.e. two TIM4 periods. The ISR is all done in a miniscule fraction of that time, however, and it happens very fast after the input waveform +ve edge, as it should. It is as if there was a two-sample FIFO somewhere. I can program around this by shifting the RAM tables back...
The obvious questions might be:
Q1) Is there any obvious gotcha in this scheme?
Q2) What should be the right way to reset TIM4? It isn't clear that it should be disabled, and it works without that
Q3) Is there a "FIFO" somewhere which is two TIM4 cycles (two whole ARR to CNT reload cycles, not two input clocks etc) long?
The image below shows the jitter around zero, as well as the 2-sample phase lag. Obviously, with 256 samples per cycle the issue becomes insignificant, especially with a lowpass filter, but then I get perf issues with recomputing the larger table. The bottom sinewave is inverted because I am using DAC2 to generate -sin(x) and it shows the same jitter. Below is the ISR.
As mentioned in the comments, after days of experimenting and YES reading the RM I found that resetting TIM4 with CNT value a lot bigger than zero avoids the jitter. It needs to be at least 1/10 of the ARR reload value, and if = or > than ARR that obviously breaks it. But this is the only workaround I found for the jitter. It introduces an issue in that the sync frequency range is a lot more limited but it still does the job I need.
===
I now know there is indeed a FIFO on the DACs, which explains 1 of the sample delays. The other one is explained by "wek" in that eevblog thread.
2021-11-28 01:30 PM
> The RM says DMA has to be disabled (and you wait for the EN bit to go to 0) before you can change the registers.
Yes, but MM said, leave DMA alone.
JW
2021-11-28 01:48 PM
How do I do that, when it is a circular buffer?
Do you mean allowing the transfer count to be exhausted, and then DMA should stop? I am wondering what that would give me, in the context of implementing frequency tracking, when the next cycle could be shorter or longer.
The process of stopping DMA seems to be well documented, while the requirements for updating or zeroing TIM4 don't appear to be.
2021-11-29 03:40 AM
I try be simply: