Dear All,
I've implemented a firmware that is running well but sometimes I have an issue.
I've implemented a sleep routine like this:
void sleep_us(uint us) { uint target; uchar overflow; uint now; TIM_TFLG2_TOF = 1; target = TIM_TCNT + us; if (TIM_TCNT > target) { while(TIM_TFLG2_TOF == 0); TIM_TFLG2_TOF = 1; } while(TIM_TCNT < target); }
This routine is used to sleep a specified amouth of microseconds.
It is then used to implement the sleep_ms routine that is like this:
void sleep_ms(uint ms) { uint i; for (i = 0; i < ms; i++) sleep_us(1000); }
Everything seems to go just fine, but sometimes the sleep_ms sleeps for more time than required. For example, even if I require a sleep of 1000 ms it could happen that the sleep_ms blocks for some seconds.
While calling the sleep_us and sleep_ms there are two PIT active along with their interrupt service routine, but I don't think that they could justify the so-long sleep interval.
The timer init configuration is set using a prescaler in order to have a 1us period.
void timer_init() { TIM_TSCR1_PRNT = 1; TIM_PTPSR = 0x2f; TIM_OCPD = 0xff; TIM_TSCR1_TEN = 1; }
I cannot figure out why the sleep should wait more time than expected. Can someone give me some hints on how to solve this problem?
Thanks in advance,
ale
IM_
PTPSR = tim_prescaler;
TIM_TSCR1_TEN = 0; TIM_OCPD = 0xff; // scollego tutti dalle uscite. TIM_TSCR1_TEN = 1;
Hi Allessandro,
I could see a potential issue in the case of any interrupt. Any interrupt between commands “target = TIM_TCNT + us;” and “if (TIM_TCNT > target)” could lead to the wrong result of this branch - especially when this interrupt is periodical.
Could you please try this small modification?:
uint test;
//…
test= TIM_TCNT;
target = test + us;
if (test > target) {
//…
Additionally there is additional overhead in some instructions from sleep_ms() and sleep_us() functions. This overhead (time for processing instructions out of the main interval) is multiplied by 1000 (and additionally multiplied by another 1000)
In general, you have two basic options for generating long delays by ECT timer.
In the attachment, you could find two very simple example codes where I generate 1 min intervals via ECT.
I hope it helps you.
Have a great day,
RadekS
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
sleep_us() doesn't look right. TOF should be used only for measuring long time difference. You could use it also for periodic interrupt source. TOF is useless to produce fine resolution delays. For pulse generation with t > 2^16 timer ticks, you should skip required number N = t / (2^16) of timer compare interrupts (equivalent to timer overflows) and prepare timer pin to toggle on last timer compare + t % (2^16). Small t % (2^16), which could be shorter than interrupt latency, like t=0x10010, can be handled dividing t into two intervals, for example t1=0x8000 and t2 = t - 0x8000.
Simple routine to delay for up to 2^15 timer ticks. 2^15, because short int sign is involved. TOF is not used:
void delay(int ticks)
{
int target = TCNT + ticks;
while ( (signed int)(TCNT - target) < 0)
{
}
}