JL JieLi AC696N Series Chip Development – Timer Detailed Explanation: Differences and Selection Between sys_timer and usr_timer

 Introduction

Timers seem simple, but using them in the wrong place either increases power consumption or causes timing inaccuracies—and debugging can be quite troublesome. The JL JieLi AC696N SDK provides two sets of timers: sys_timer and usr_timer. When first getting started, it's easy to get confused—when to use which? Why does my timer become inaccurate after entering sleep? Can I perform work in the callback? I encountered all these issues while debugging low-power solutions on the AC696N development board. Here's a summary of the differences and selection logic, so you can directly reference it when writing code.

文章内容

Chip Product Introduction

文章内容

I. System Timer (sys_timer) – "Software Timer"

Features: Managed by the systimer thread, synchronous interface. The callback executes in the same thread where the timer was added.

Low Power: System can sleep; the timer will wake the system when it expires, without losing ticks.

Use Case: Suitable for general tasks that need periodic execution and can tolerate slight delays.

Interfaces: sys_timer_add, sys_timer_del, sys_timeout_add (one-shot)

文章内容

II. User Timer (usr_timer) – "Hardware Timer"

Features: Driven by hardware timer, asynchronous interface, callback executes in interrupt context.

Priority Impact:

  • 🔹 priority=1: System cannot enter low power, timing is precise
  • 🔹 priority=0: System can sleep, but timing period may lengthen due to sleep
  • 🔹 Use Case: Suitable for timing tasks requiring precision and fast response, or one-shot timeouts.
  • 🔹 Interfaces: usr_timer_add, usr_timer_del, usr_timeout_add

文章内容

III. Timer Applications

1) Timing Function

Example using led7_timer.c on AC696:


static void timer2_isr()
{
    //local_irq_disable();    // Enable when extremely accurate timing is needed
    TIMER_CON |= BIT(14);      // Clear interrupt flag
    // User custom code
    //......
    //local_irq_enable();      // Enable when extremely accurate timing is needed
}

int led7_timer_init()
{
    u32 prd_cnt;
    u8 index;

    printf("------------%s :%d", __func__, __LINE__);

    for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) {
        prd_cnt = TIMER_UNIT_MS * (APP_TIMER_CLK / 1000) / timer_div[index];
        if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) {
            break;
        }
    }
    __this->index   = index;
    __this->prd     = prd_cnt;

    TIMER_CNT = 0;
    TIMER_PRD = prd_cnt; //1ms
    request_irq(TIMER_VETOR, 6, timer2_isr, 0); //Highest priority 7, enable when extremely accurate timing needed
    TIMER_CON = (index << 4) | BIT(0) | BIT(3);

    printf("PRD : 0x%x / %d", TIMER_PRD, clk_get("timer"));

    return 0;
}


2) Capture Function

• Reference Code

// Based on AC696 program. Some I/O pins may not support this function—test first, then design PCB!!!!!!
#define TIMER5                      7 // see irflt.h
#define CATCH_TIMER                 TIMER5
#define CATCH_IRQ_TIME_IDX          IRQ_TIME5_IDX
#define CATCH_TIME_REG              JL_TIMER5
#define CATCH_GPIO                  IO_PORTB_06

int num = 0;

void timer_ms()
{
    static int flag = 0;
    if(flag){
        gpio_set_pull_down(IO_PORTA_02,0);
        gpio_set_pull_up(IO_PORTA_02,0);
        gpio_set_direction(IO_PORTA_02,1);
        flag = 0;
    }
    else{
        gpio_set_pull_down(IO_PORTA_02,0);
        gpio_set_pull_up(IO_PORTA_02,0);
        gpio_set_direction(IO_PORTA_02,0);
        gpio_set_output_value(IO_PORTA_02,0);
        putchar('0');
        flag = 1;        
    }
}

__interrupt
void timer_catch_isr(void)
{
    CATCH_TIME_REG->CON |= BIT(14);
    u16 bCap1 = CATCH_TIME_REG->PRD;    // Time from last interrupt to this one, can be used for timing
    CATCH_TIME_REG->CNT = 0;
    num++;                               // Count
}

void timer_100ms()
{
    printf("num == %d\n",num);
    num = 0;
}

void timer_catch_init()
{
    printf("timer_catch_init\n");
    // I/O configuration
    gpio_irflt_in(CATCH_GPIO);
    gpio_set_direction(CATCH_GPIO, 1);
    gpio_set_die(CATCH_GPIO, 1);
    gpio_set_pull_up(CATCH_GPIO, 1);
    gpio_set_pull_down(CATCH_GPIO, 0);
    // Clock configuration
    SFR(JL_IOMAP->CON0, 5, 3, CATCH_TIMER);                           // TIMER5:7 in irflt.h
    CATCH_TIME_REG->CON = 0;
    CATCH_TIME_REG->CON |= (0b10 << 2);                       // Select crystal oscillator clock source: 24MHz
    CATCH_TIME_REG->CON |= (0b0001 << 4);                   // Clock source divide by 4
    // Set period, initial value, timer mode
    CATCH_TIME_REG->PRD = OSC_Hz / (4 * 1000);
    CATCH_TIME_REG->CNT = CATCH_TIME_REG->PRD;
    CATCH_TIME_REG->CON |= BIT(14);
    CATCH_TIME_REG->CON |= (0b11 << 0);
    request_irq(CATCH_IRQ_TIME_IDX, 5, timer_catch_isr, 0);
    sys_timer_add(NULL, timer_100ms, 100);                   // Periodically read interrupt count
    sys_timer_add(NULL, timer_ms, 1);                        // Generate waveform for interrupt capture (not precise, not exactly 1ms)
}


Selection Guide

  • 🔹 Need low power and low real-time requirements → Use sys_timer
  • 🔹 Need precise timing or fast response, power consumption not the primary concern → Use usr_timer (priority=1)
  • 🔹 Need one-shot timeout functionality → Use sys_timeout_add or usr_timeout_add


Summary

In simple terms, prioritize sys_timer in regular code—it doesn't affect sleep, is power-friendly, and covers most scenarios. If you need millisecond-level precision or the callback needs to handle urgent tasks, use usr_timer, but remember that when priority=1, the system cannot sleep, increasing power consumption—don't keep it running long-term in production. Both support one-shot timeouts; use whichever you prefer. I recommend trying both timers on the AC696N development board, printing the callback thread and sleep behavior via serial to intuitively understand the difference—then you won't hesitate when selecting timers.

评论

此博客中的热门博文

Jieli Bluetooth Smart Speaker Development: Common Issues with AC696N SoCs

KT148A Voice Chip: A Powerful Tool to Enhance the User Experience of Smart Soymilk Makers