How to adjust a timer interval?

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

How to adjust a timer interval?

1,553 次查看
ARQuattr
Contributor IV

I have a timer running that was started using _timer_start_periodic_every, and I want to be able to make one-time adjustments to the interval, effectively causing the next event to occur early or late by a certain amount.  Following that it should continue at the originally specified interval.  I don't see an obvious way to do that through the MQX functions, other than canceling and restarting the timer.  Is there a better way to do this?

[Edit] Also, I tried doing this (cancel and restart), and it's not working.  I get a success return code when cancelling, but the timer keeps running so after starting a new one (for which I get a different id) I have two running.  It eventually stops working (presumably when I run out of stack space).

void restartTimer(uint16_t offsetMs)

{

    TIME_STRUCT offsetTime;

   

    offsetTime.SECONDS = 0;

    offsetTime.MILLISECONDS = offsetMs;

   

    //cancel current timer

    printf("\nCancelling timer id %d, result %d\n", oneHz_timer, _timer_cancel(oneHz_timer));

   

    //restart timer at a new offset

    oneHz_timer = _timer_start_periodic_at(timer1sEvent, 0, TIMER_ELAPSED_TIME_MODE, &offsetTime, 1000);

   

    printf("Timer restarted at %dms, timer id %d...\n", offsetMs, oneHz_timer);

}

The result is this:

Cancelling timer id 2, result 0

Timer restarted at 1000ms, timer id 3...

I am calling this from the same thread that started the timer initially.

标记 (2)
0 项奖励
回复
5 回复数

1,069 次查看
DavidS
NXP Employee
NXP Employee

You might need to give a little time delay between disabling and re-enabling the timer to same function.

Just a guess.

Regards,

David

0 项奖励
回复

1,071 次查看
ARQuattr
Contributor IV

Thanks David.  I added a 100ms delay between cancel and start, but it didn't change the problem.

I added a printf in the timer task to get a better picture of what was happening, and saw some bizarre behavior.  I'm wondering if there might be a bug in the timer module.

This is what the start of the timer function looks like:

static void timer1sEvent(_timer_id id, pointer data_ptr, uint32_t seconds, uint32_t milliseconds)

{

    static int count=0;

    printf("tick:id%d,count:%d\n", id, count++);

And this is the output after the first one is started done using _timer_start_periodic_every(), with a 1s interval:

tick:id2,count:0          (<-- at 1s)

tick:id2,count:1          (<-- at 2s)

tick:id2,count:2          (<-- at 3s)

tick:id2,count:3          (<-- at 4s)

...etc.

Then I issue a shell command to call the restartTimer(500) function, and this happens:

tick:id3,count:6          (<-- at 6s)

tick:id3,count:7          (<-- at 6s)

tick:id3,count:8          (<-- at 7s)

tick:id3,count:9          (<-- at 7s)

tick:id3,count:10        (<-- at 8s)

tick:id3,count:11        (<-- at 8s)

So the timer function is being called twice under the same task id.  Previously I though they were called from both the cancelled and new task, but apparently the cancelled task was actually cancelled, but now it runs the new one twice.

Now it gets really weird.  I changed the time interval of the new restarted task to 2s, and the new (doubled) timers are still called every second.  I then changed from calling _timer_start_periodic_at(), to _timer_start_periodic_every(), and the doubling stopped.

So I changed the initial timer start to _timer_start_periodic_at(), with the start time set to 0, and I would get double timer function calls right from powerup - without even doing a cancel/restart sequence.  By the way, changing the start time in the first or any subsequent timer start call didn't seem to make any difference, or even change the start time (although that's hard to know for sure).

Then, I realized that the doubled timer eventually stopped on it's own, and the timer interval changed at the same point.  So for example with the following code:

void startTimer()  //called after boot-up

{

  _timer_create_component(TIMER_TASK_PRIORITY, TIMER_STACK_SIZE);

  oneHz_timer = _timer_start_periodic_every(timer1sEvent, 0, TIMER_ELAPSED_TIME_MODE, 1000);

}

void restartTimer(uint16_t offsetMs)

{

  TIME_STRUCT offsetTime;

  offsetTime.SECONDS = 0;

  offsetTime.MILLISECONDS = offsetMs;

  //cancel current timer

  printf("\nCancelling timer id %d, result %d\n", oneHz_timer, _timer_cancel(oneHz_timer));

  //restart timer at a new offset

  oneHz_timer = _timer_start_periodic_at(timer1sEvent, 0, TIMER_ELAPSED_TIME_MODE, &offsetTime, 2000);

  printf("Timer restarted at %dms, timer id %d...\n", offsetMs, oneHz_timer);

}

//1s timer event.

static void timer1sEvent(_timer_id id, pointer data_ptr, uint32_t seconds, uint32_t milliseconds)

{

  static int count=0;

  printf("tick:id%d,count:%d\n", id, count++);

This is the output:

tick:id2,count:0  <-- at 1s  (one each second)

tick:id2,count:1  <-- at 2s

tick:id2,count:2  <-- at 3s

tick:id2,count:3  <-- at 4s

tick:id2,count:4  <-- at 5s

tick:id2,count:5  <-- at 6s

tick:id2,count:6  <-- at 7s

tick:id2,count:7  <-- at 8s

tick:id2,count:8  <-- at 9s

tick:id2,count:9  <-- at 10s

tick:id2,count:10  <-- at 11s

tick:id2,count:11  <-- at 12s

tick:id2,count:12  <-- at 13s

tick:id2,count:13  <-- at 14s

---(call restartTimer(500))---

Cancelling timer id 2, result 0

Timer restarted at 500ms, timer id 3...

tick:id3,count:14  <-- at 15s  (two every second)

tick:id3,count:15  <-- at 15s

tick:id3,count:16  <-- at 16s

tick:id3,count:17  <-- at 16s

tick:id3,count:18  <-- at 17s

tick:id3,count:19  <-- at 17s

tick:id3,count:20  <-- at 18s

tick:id3,count:21  <-- at 18s

tick:id3,count:22  <-- at 19s

tick:id3,count:23  <-- at 19s

tick:id3,count:24  <-- at 20s

tick:id3,count:25  <-- at 20s

tick:id3,count:26  <-- at 21s

tick:id3,count:27  <-- at 21s

tick:id3,count:28  <-- at 22s

tick:id3,count:29  <-- at 22s

tick:id3,count:30  <-- at 23s  (one every two seconds)

tick:id3,count:31  <-- at 25s

tick:id3,count:32  <-- at 27s

tick:id3,count:33  <-- at 29s

tick:id3,count:34  <-- at 31s

tick:id3,count:35  <-- at 33s

tick:id3,count:36  <-- at 35s

If I call a restart again, it does the same thing, giving double calls (at one second intervals again!), and then eventually returning to single calls every two seconds.  It's really strange.  Stranger still is the time it takes before it returns to expected timer intervals seems to increase each time I do it.  It almost seems that the longer the system time (time since reset), the longer it takes to recover.

Again, this behavior only seems to be happening with _timer_start_periodic_at().  I haven't dug deeper into the MQX code on this, but I suppose I'll have to do that next to figure this out.

0 项奖励
回复

1,071 次查看
norbertoj
Contributor III

The problem is that when you use _timer_start_periodic_every, you generate a new timer id, if you see the function _timer_alloc_id_internal, there is a line that say:

 timer_component_ptr->ID = id + 1;

0 项奖励
回复

1,071 次查看
danielchen
NXP TechSupport
NXP TechSupport

can you try to create the timer component with more stack than the default?

0 项奖励
回复

1,071 次查看
ARQuattr
Contributor IV

Thanks Daniel.  I increase the stack size from 1500 to 5000 and it didn't change the behavior.

0 项奖励
回复