This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Timer always running, interrupt for selected values

Other Parts Discussed in Thread: EK-TM4C123GXL

Hi,

I'm porting the RIOT-RTOS to the tiva launchpad (ek-tm4c123gxl).

RIOT wants to have a timer always running so it can get a current time in ticks, but would also like to use that timer to trigger events at given times.


So I do

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC_UP | TIMER_CFG_B_PERIODIC_UP);
    TimerPrescaleSet(TIMER0_BASE, TIMER_A, TIMER_0_PRESCALER);
    TimerLoadSet(TIMER0_BASE, TIMER_A, 0xffff);

    NVIC_EnableIRQ(TIMER0A_IRQn);

    TimerEnable(TIMER0_BASE, TIMER_A);

to start a counting timer, which doesn't trigger any interrupts yet.

Now if the RTOS wants to trigger an event in 1000 ticks, I would do

uint32_t value = TimerValueGet(TIMER0_BASE, TIMER_A) + 1000;
TimerMatchSet(TIMER0_BASE, TIMER_A, value);
TimerIntEnable(TIMER0_BASE, TIMER_CAPA_MATCH);


However, nothing happens.

I think I misunderstood the way TimerMatchSet()/TIMER_CAPA_MATCH works, I assumed I would set a value at which an interrupt is triggered, but that doesn't seem to be the case.

How can I achieve this behaviour?

When I set TIMER_TIMA_TIMEOUT the interrupt is trigged on overflow as expected.

  • Hi,

    You must make difference between system clock ticks and a timer tick. And to be precise when programming an event after timer tick or clock tick.

    Explanation: in a timer like you have chosen, the system clock is used - i.e. 1 system clock tick is 12.5ns if running at 80MHz. If you set the timer to interrupt at 10 ms, then a timer tick is 10 ms, so your event should be programmed at N x 10ms (N=1000 in your case) so you must count the number of interrupts. Your code seems just to add the N to the system clock  tick, which is not what you expect to be.

    Usually, in RTOSes SysTick timer is used, its use is easier, easier to set or change the system tick duration, e.g for 10 ms load the timer with [SysCtlFreqGet()/10] -1. No need to reload, no need for prescaler, no need to clear the interrupt flags. Using an usual timer may not be the best idea, should be left for users needs.

    Take care the above function has a bug in latest Tiva version.

    Petrei

  • You say TimerValueGet() will return the system clock ticks, not timer ticks, regardless of prescale?

    I thought prescale would cause the timer value to only be incremented every $prescale_value clock ticks, so all other Timer functions would still behave the same, just count at a lower frequency.


    If I use systick(), how do I then sync systick with the timer I use? Would the timer have to run at the same speed as systick?

  • Hi, 

    The things are a little bit more complicated. You should note you have also a prescaler match register, you did not used it at all. 

    Yes, the TimerValueGet() returns system clock ticks, strictly 16 bits, since you splitted the timer.

    Also, for interrupts, you should note this (from the user manual, related to timer match with prescaler):

    Note that the interrupt status bits are not updated by the hardware unless the TnMIE bit in the GPTMTnMR register is set, which is different than the behavior for the time-out interrupt. 

    As for SysTick() - do not understand why do you need synchro with other timers? The purpose is to use a dedicated timer for RTOS ticks (was implemented there for purpose), no prescalers... Also, as I said, avoid blocking resources, may be needed by usual users, some may avoid such packages.

    Petrei

  • I did just read the documentation again, looks like the prescaler is not available as such when counting upwards, but instead extends the range of the timer register by 8 byte.

    When in one-shot or periodic down count modes, this register acts as a true prescaler for the timer
    counter. When acting as a true prescaler, the prescaler counts down to 0 before the value in the
    GPTMTAR and GPTMTAV registers are incremented. In all other individual/split modes, this register
    is a linear extension of the upper range of the timer counter, holding bits 23:16 in the 16-bit modes
    of the 16/32-bit GPTM and bits 47:32 in the 32-bit modes of the 32/64-bit Wide GPTM.


    So when I use SysTick as clock (RIOT doesn't require a SysTick interrupt, it only wants to have a monotonic time to schedule events), how do I make sure that, say 100 SysTick ticks are as long as 100 Timer ticks?

  • Hi,

    SysTick also uses the system clock (80MHz) but internally is a 24 bit timer, so no need for prescalers. Once set for ticking at 10ms, you must be absolutely sure that 100 ticks always means one second.

    The Systick is also explained in the user manual. Another source of inspiration can be the FreeRTOS, see Tiva, the source code is available. 

    Note: unlike other (old) microcontrollers, the Cortex-Mx were specially designed for RTOSes, with a lot of unusual features; a notably one is the interrupts can never be globally disabled, a lot of discussions on these...

  • But how do I set the SysTick to only be ticking every 10ms? The way I read the specification, there is no way to add a prescaler or slow down SysTick, only decrease the period when it wraps.


    So I could have SysTick generate an interrupt every 10ms, but that's not what I want.