Skip to content

General-Purpose Timer (TIMER)


1. Introduction

  • The TIMER is a 32‑bit decrementing counter with a configurable prescaler and multiple counting modes. When the counter reaches 0, a timer event is triggered. It is typically used to repeatedly trigger events at specific intervals, serving as a periodic interrupt generator or event counter.
  • CI13XX supports four dedicated timers: TIMER0~TIMER3. Timer cascading is supported. PWM4 and PWM5 can also be used as AON timers.

2. Features

  • Three counting modes configurable via timer_init/timer_set_mode: one‑shot, auto‑reload, and free‑running.
  • One‑shot: counts a single period once.
  • Auto‑reload: reinitializes the counter at the end of each period.
  • Free‑running: rolls over from 0xFFFFFFFF to 0x00000000 continuously.
  • Clock prescaler supports ÷½/4/16 via timer_init.
  • 32‑bit decrementing counter with live value readable via timer_get_count.
  • Cascade mode configurable via timer_cascade_set.
  • Interrupt on count completion; see timer_clear_irq for clearing behavior.

3. API List

Function Name Description
timer_init Initialize TIMER device
timer_start Start TIMER device
timer_stop Stop TIMER device
timer_set_mode Set TIMER counting mode
timer_event_start Start event counting
timer_set_count Set TIMER period
timer_get_count Get current counter value
timer_cascade_set Configure cascade mode
timer_clear_irq Clear TIMER interrupt

4. TIMER Details

TIMER Name IRQ Name ISR Notes
TIMER0 TIMER0_IRQn TIMER0_IRQHandler
TIMER1 TIMER1_IRQn TIMER1_IRQHandler
TIMER2 TIMER2_IRQn TIMER2_IRQHandler
TIMER3 TIMER3_IRQn TIMER3_IRQHandler
AON_TIMER0 AON_TIM_INT0_IRQn AON_TIM_INT0_IRQHandler HAL_PWM4_BASE can be used as AON_TIMER0
AON_TIMER1 AON_TIM_INT1_IRQn AON_TIM_INT0_IRQHandler HAL_PWM5_BASE can be used as AON_TIMER1


5. Examples

The TIMER interrupt service routines are wake‑type and can be defined anywhere:

#include "ci130x_timer.h"
#include "ci_log.h"

// TIMER0 interrupt service routine definition
void TIMER0_IRQHandler(void)
{
    mprintf("timer0 irq\n");
    timer_clear_irq(TIMER0);
}

// TIMER1 ISR similar to TIMER0
// TIMER2 ISR similar to TIMER0
// TIMER3 ISR similar to TIMER0
// AON_TIMER0 ISR similar to TIMER0
// AON_TIMER1 ISR similar to TIMER0

Note

When the interrupt width is configured as timer_iqr_width_f, if the interrupt is enabled, you must call timer_clear_irq to clear it. For other interrupt widths, hardware auto‑clears the interrupt.

The following configures and starts TIMER0. Passing 1 means a timer interrupt every 1 second:

#include "ci130x_time.h"
#include "ci130x_timer.h"
#include "ci130x_core_eclic.h"

void timer_s(uint32_t s)
{
    /* TIMER0 controller clock configuration */
    scu_set_device_gate(HAL_TIMER0_BASE,ENABLE);
    /* Enable TIMER0 interrupt */
    eclic_irq_enable(TIMER0_IRQn);
    /* TIMER0 initialization */
    timer_init_t init;
    init.mode = timer_count_mode_auto;      // Auto‑reload mode
    init.div = timer_clk_div_0;             // No prescaling
    init.width = timer_iqr_width_f;         // Requires timer_clear_irq to clear
    init.count = get_apb_clk() * s;         // Count for s seconds
    timer_init(TIMER0,init);
    /* Start TIMER0 */
    timer_start(TIMER0);
}

The following configures and starts TIMER0. Passing 1 means an interrupt every 1 ms:

#include "ci130x_time.h"
#include "ci130x_timer.h"
#include "ci130x_core_eclic.h"

void timer_ms(uint32_t ms)
{
    /* TIMER0 controller clock configuration */
    scu_set_device_gate(HAL_TIMER0_BASE,ENABLE);
    /* Enable TIMER0 interrupt */
    eclic_irq_enable(TIMER0_IRQn);
    /* TIMER0 initialization */
    timer_init_t init;
    init.mode = timer_count_mode_auto;          // Auto‑reload mode
    init.div = timer_clk_div_0;                 // No prescaling
    init.width = timer_iqr_width_f;             // Requires timer_clear_irq to clear
    init.count = (get_apb_clk() / 1000) * ms;   // Count for ms milliseconds
    timer_init(TIMER0,init);
    /* Start TIMER0 */
    timer_start(TIMER0);
}

The following configures and starts TIMER0. Passing 1 means an interrupt every 1 µs:

#include "ci130x_time.h"
#include "ci130x_timer.h"
#include "ci130x_core_eclic.h"

void timer_us(uint32_t us)
{
    /* TIMER0 controller clock configuration */
    scu_set_device_gate(HAL_TIMER0_BASE,ENABLE);
    /* Enable TIMER0 interrupt */
    eclic_irq_enable(TIMER0_IRQn);
    /* TIMER0 initialization */
    timer_init_t init;
    init.mode = timer_count_mode_auto;            // Auto‑reload mode
    init.div = timer_clk_div_0;                   // No prescaling
    init.width = timer_iqr_width_f;               // Requires timer_clear_irq to clear
    init.count = (get_apb_clk() / 1000000) * us;  // Count for us microseconds
    timer_init(TIMER0,init);
    /* Start TIMER0 */
    timer_start(TIMER0);
}

Warning

CI13XX integrates 32‑bit counters with range 0x00000000 to 0xFFFFFFFF. For longer timing, use prescaling or cascade mode.


6. FAQs

  • TIMER timing range (base clock CLK_S = 120000000 Hz)

Prescaler: DIV (valid values: 1, 2, 4, 16)

Counting clock: CLK = CLK_S / DIV (Hz)

Minimum period: MIN = 1 s / CLK (seconds)

Maximum period: MAX = 0xFFFFFFFF × MIN (seconds)

With the above, the maximum period is around 9 minutes. For longer periods, use timer cascade mode as described below:

TODO:

Base Timer Cascade Timer
TIMER0 TIMER1\2\3
TIMER1 TIMER2\3
TIMER2 TIMER3
AON_TIMER0 AON_TIMER1

Example: Set TIMER0 as the base timer with prescaler = 16 (to maximize period). Configure TIMER½/3 in cascade with max counts (0xFFFFFFFF). Then each timer’s period is approximately:

Timer Period
TIMER0 ~13 minutes
TIMER1 0xFFFFFFFF × ~13 minutes
TIMER2 0xFFFFFFFF × 0xFFFFFFFF × ~13 minutes
TIMER3 0xFFFFFFFF × 0xFFFFFFFF × 0xFFFFFFFF × ~13 minutes
AON_TIMER0 ~13 minutes
AON_TIMER1 0xFFFFFFFF × ~13 minutes

7. API Reference