2

I'm using ASF4 API hal_timer for a ARM Cortex M4. I'm using the timer driver to timing a data sequence. Why does no reset function exist? I'm using the timer on a TIMER_TASK_ONE_SHOT mode and want to reset it when ever I need to.

I thought a simple

timer_start(&TIMER_0);
timer_stop(&TIMER_0);

would do the trick but does not seem to work.

Is it necessary to re-initialize the timer for each timing event?

I'm probably missing something obvious. Am I approaching this problem incorrectly reason being why the method timer_reset() doesn't exist?

Lundin
  • 195,001
  • 40
  • 254
  • 396
Müller
  • 313
  • 5
  • 18
  • Which part is this, more precisely? How/where do you setup the clock? Is this based on SYSTICK? – Lundin Oct 25 '19 at 07:31
  • You need to define the semantics you require of "timer_reset" - is that _"re-start period and continue running"_ for example? "reset" could mean a number of things. – Clifford Oct 25 '19 at 08:57
  • @Lundin I want to reset the counter of the timer in another external interrupt handler that I'm using. I have a timer_task struct called TIMER_0_CLOCK_BREAK variable where the interval is set at TIMER_0_CLOCK_BREAK.interval = 5000. Once 5 seconds run out I want to reset the timer to start again but I want to trigger this on an external interrupt moment. The ticks come from the real time clock hardware timer managed by the hal_timer.c driver in ASF4 API, the chip is an ARM cortex-m4 running at 32.77 kHz counter set at 32 for now so the above-mentioned interval gives you 5000 ticks = 5 seconds. – Müller Oct 25 '19 at 13:13
  • Ok well, first things first, have you verified that the system clock is correctly configured? These things are always painful. What system clock are you running at, did you set wait states etc. For the SAM parts you need to set wait states if running faster than 20MHz for 5V supply, iirc. And then you need to configure up the GCLK. I don't know how much of this ASF does or how buggy it is, I threw that crapware out at day 1. Better to learn how the hardware actually works, or you'll be held hostage by ASF. – Lundin Oct 25 '19 at 13:35
  • Here's the link for the reference manual [ASF4 API Reference Manual - Microchip Technology](http://ww1.microchip.com/downloads/en/DeviceDoc/50002633A.pdf) – Müller Oct 28 '19 at 08:32

2 Answers2

0

I have no experience of this API, but looking at the documentation it is apparent that a single timer can have multiple tasks on different periods, so resetting TIMER_0 makes little semantic sense; rather you need to reset the individual timer task attached to the timer - of which there may be more than one.

From the documentation (which is poor and contains errors), and the source code which is more reliable:

timer_task_instance.time_label = TIMER_0.time ;

where the timer_task_instance is the struct timer_task instance you want to reset. This sets the start time to the current time.

Probably best to wrap that in a function:

// Restart current interval, return interval.
uint32_t timer_restart( struct timer_descriptor* desc, struct timer_task* tsk )
{
    tsk->time_label = desc->time
    return tsk->interval ;
}

Then:

timer_restart( &TIMER_0, &timer_task_instance ) ;
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • It may not matter, but in the case of multiple tasks associated with a timer, there is a list of tasks, maintained in order of when each task will expire. Changing `time_label` will break the ordering. – Phil Dec 13 '19 at 05:44
  • @Phil : Oh, indeed it is a nasty hack to a nasty API. My advice would be to use an RTOS for scheduling. – Clifford Dec 13 '19 at 10:03
0

Assuming you're using the (edited) example from the ASF4 Reference Manual:

/* TIMER_0 example */
static struct timer_task TIMER_0_task;

static void TIMER_0_task_cb(const struct timer_task *const timer_task)
{
    // task you want to delay using non-existent reset function.
}

void TIMER_0_example(void)
{
 TIMER_0_task.interval = 100;
 TIMER_0_task.cb = TIMER_0_task_cb;
 TIMER_0_task.mode = TIMER_TASK_ONE_SHOT;
 timer_add_task(&TIMER_0, &TIMER_0_task);
 timer_start(&TIMER_0);
}

Instead of resetting, which isn't supported by the API, you could use:

timer_remove_task(&TIMER_0, &TIMER_0_task);
timer_add_task(&TIMER_0, &TIMER_0_task);

which will effectively restart the delay associated with TIMER_0_task.

Under the hood, timer tasks are maintained as an ordered list, in order of when each task will expire, and using the functions provided by the API maintains the list order.

Phil
  • 2,080
  • 2
  • 12
  • 13