cancel
Showing results for 
Search instead for 
Did you mean: 

64 bit timer with 4 TIMx cascaded timers

zomirp
Associate II
Posted on March 09, 2009 at 10:30

64 bit timer with 4 TIMx cascaded timers

4 REPLIES 4
fastmapper
Associate II
Posted on May 17, 2011 at 13:03

Quote:

And this is timer capture and read:

Code:

TIM_GenerateEvent(TIM2, TIM_EventSource_CC1);

uSeconds = TIM_GetCapture1(TIM2) |

(TIM_GetCapture1(TIM3) << 16) |

(TIM_GetCapture1(TIM4) << 32) |

(TIM_GetCapture1(TIM5) << 48);

One thing to consider is that no matter how synchronized the timers, the reading of multiple timer registers will not be performed at the same time. In other words, it it definitely possible for some of the timers to change counts over the course of time it takes to read them. When such a change occurs, the values read from the multiple timers cannot be combined to produce a count that is the same as you would get if you had a single counter. With 16-bit counters, this can result in two immediately successive values where the second value is either less than the first or greater than the first by roughly 65536 counts.

I suggest that you read the least significant counter first, then read the other counters, then read the least significant counter again. Then you can compare the two reads of the least significant counter. If the most significant bit in the two least significant counter values are not the same, then repeat the entire process until they are. When both least significant counter values have the same most significant bit, then all of the counter values can be combined to produce a consistent aggregate result. Please note that if your CPU frequency is high enough relative to your timer frequency, more of the most significant bits (even up to all counter bits) can be compared.

zomirp
Associate II
Posted on May 17, 2011 at 13:03

The question is HOW TO READ 64 BIT VALUE? Or further, how to to make synchronous software capture?

The problem I'm experiencing is that slave doesn't capture correct value if capturing near master rollover.

This is my setup:

Code:

TIM_TimeBaseStructure.TIM_Period = 0xFFFF;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Prescaler = 72;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);

TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);

TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);

TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Update);

TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1);

TIM_SelectInputTrigger(TIM4, TIM_TS_ITR2);

TIM_SelectInputTrigger(TIM5, TIM_TS_ITR2);

TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_External1);

TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_External1);

TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_External1);

TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;

TIM_ICInitStructure.TIM_ICPolarity = TIM_ICSelection_DirectTI;

TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_TRC;

TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

TIM_ICInitStructure.TIM_ICFilter = 0;

TIM_ICInit(TIM2, &TIM_ICInitStructure);

TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

TIM_ICInit(TIM3, &TIM_ICInitStructure);

TIM_ICInit(TIM4, &TIM_ICInitStructure);

TIM_ICInit(TIM5, &TIM_ICInitStructure);

TIM_Cmd(TIM2, ENABLE);

TIM_Cmd(TIM3, ENABLE);

TIM_Cmd(TIM4, ENABLE);

TIM_Cmd(TIM5, ENABLE);

And this is timer capture and read:

Code:

TIM_GenerateEvent(TIM2, TIM_EventSource_CC1);

uSeconds = TIM_GetCapture1(TIM2) |

(TIM_GetCapture1(TIM3) << 16) |

(TIM_GetCapture1(TIM4) << 32) |

(TIM_GetCapture1(TIM5) << 48);

Counters seem to work OK. They are just not captured correctly.

Any idea? Am I doing something wrong?

zomirp
Associate II
Posted on May 17, 2011 at 13:03

Now, it seems slave doesn't get advanced every now and then...

zomirp
Associate II
Posted on May 17, 2011 at 13:03

I'm aware of the problem with non-atomic reads. That's why I was trying to latch all timers at once. Since they are cascaded I thought/hopped they will get captured with capture event on TIM2. As turned out they aren't (or I did something wrong - there are some mistakes in original code in first post, but I fixed them and tried it in couple of ways without success).

Following is my solution in fashion also suggested by fastmapper

Code:

static unsigned long long s_uSeconds;

static void GetTime()

{

WORD wQuickieFirst, wQuickieSecond;

do

{

wQuickieFirst = TIM_GetCounter(TIM2);

s_uSeconds = wQuickieFirst |

(TIM_GetCounter(TIM3) << 16) |

(TIM_GetCounter(TIM4) << 32) |

(TIM_GetCounter(TIM5) << 48);

wQuickieSecond = TIM_GetCounter(TIM2);

}

while ( wQuickieSecond < wQuickieFirst );