copilot-swe-agent[bot] 0f3a297f4d [clock_time] Add README and example adapters 2 luni în urmă
..
README.md 0f3a297f4d [clock_time] Add README and example adapters 2 luni în urmă
clock_time_arm_gtimer.c 0f3a297f4d [clock_time] Add README and example adapters 2 luni în urmă
clock_time_systick.c 0f3a297f4d [clock_time] Add README and example adapters 2 luni în urmă

README.md

Clock Time Adapters

This directory contains reference adapter implementations for various hardware timers. These adapters demonstrate how to integrate hardware timers with the unified clock_time subsystem.

Available Adapters

1. ARM Generic Timer (clock_time_arm_gtimer.c)

Target Platforms:

  • ARMv7-A (ARM Cortex-A with Generic Timer)
  • ARMv8-A/ARMv8-R (AArch64 and AArch32)

Features:

  • Clocksource: Uses CNTPCT (physical counter)
  • Clockevent: Uses CNTP_TVAL/CVAL for programmable interrupts
  • Full capabilities: Both CLOCKSOURCE and CLOCKEVENT

Usage:

// In your BSP board.c or timer initialization
rt_clock_time_arm_gtimer_init();

// In your timer ISR
void ARM_GTIMER_IRQHandler(void)
{
    rt_interrupt_enter();
    rt_clock_time_arm_gtimer_isr();
    rt_interrupt_leave();
}

Registers Used:

  • CNTFRQ_EL0: Counter frequency
  • CNTPCT_EL0: Physical counter value
  • CNTP_TVAL_EL0: Timer value (countdown)
  • CNTP_CTL_EL0: Timer control

2. SysTick/DWT (clock_time_systick.c)

Target Platforms:

  • ARM Cortex-M0/M0+/M3/M4/M7/M33/M55

Features:

  • Clocksource: Uses DWT CYCCNT (cycle counter) if available
  • Falls back to tick counter if DWT is not available
  • Clockevent: Not supported (SysTick is used for system tick)

Usage:

// DWT is automatically enabled during initialization
// No ISR needed - this is clocksource only

// Optional: Set CPU frequency if SystemCoreClock is not accurate
rt_clock_time_systick_set_freq(168000000); // 168 MHz

Notes:

  • DWT may not be available on all Cortex-M cores or may be disabled by debugger
  • Provides microsecond-level precision on typical MCUs (>= 1 MHz clock)
  • For clockevent capability, pair with a hardware timer (TIM, LPTIM, etc.)

Creating Your Own Adapter

To create an adapter for your hardware timer:

Step 1: Implement the ops structure

static rt_uint64_t my_timer_get_freq(void)
{
    return TIMER_FREQUENCY_HZ;
}

static rt_uint64_t my_timer_get_counter(void)
{
    return MY_TIMER->COUNT;  /* Read hardware counter */
}

static rt_err_t my_timer_set_timeout(rt_uint64_t delta)
{
    if (delta == 0)
    {
        /* Cancel timeout */
        MY_TIMER->CTRL &= ~TIMER_ENABLE;
        return RT_EOK;
    }
    
    /* Set compare value for interrupt */
    MY_TIMER->COMPARE = MY_TIMER->COUNT + delta;
    MY_TIMER->CTRL |= TIMER_ENABLE | TIMER_INT_ENABLE;
    
    return RT_EOK;
}

static const struct rt_clock_time_ops my_timer_ops =
{
    .get_freq = my_timer_get_freq,
    .get_counter = my_timer_get_counter,
    .set_timeout = my_timer_set_timeout,
};

Step 2: Register the device

int my_timer_init(void)
{
    static struct rt_clock_time_device my_device;
    
    /* Initialize hardware */
    // ... hardware setup code ...
    
    my_device.ops = &my_timer_ops;
    
    /* Register with appropriate capabilities */
    return rt_clock_time_device_register(&my_device, "my_timer",
        RT_CLOCK_TIME_CAP_CLOCKSOURCE | RT_CLOCK_TIME_CAP_CLOCKEVENT);
}
INIT_DEVICE_EXPORT(my_timer_init);

Step 3: Implement ISR (if using clockevent)

void MY_TIMER_IRQHandler(void)
{
    rt_interrupt_enter();
    
    /* Clear hardware interrupt flag */
    MY_TIMER->STATUS = TIMER_INT_FLAG;
    
    /* Process high-resolution timer timeouts */
    rt_clock_hrtimer_process();
    
    rt_interrupt_leave();
}

Capability Selection Guidelines

Clocksource Only

Use when:

  • Timer can only provide a counter, no interrupt capability
  • Timer is already used for system tick
  • Examples: SysTick (used for OS tick), Read-only counters

Clockevent Only

Use when:

  • Timer can generate interrupts but has no readable counter
  • Rare case, most timers have both

Both Clocksource and Clockevent

Use when:

  • Timer has a readable counter AND can generate interrupts
  • This is the most common and preferred configuration
  • Examples: ARM Generic Timer, most hardware timers

Performance Considerations

Counter Frequency

  • Low frequency (1-100 kHz): Good for power-sensitive applications, limited precision
  • Medium frequency (1-10 MHz): Good balance for most MCU applications
  • High frequency (>10 MHz): Best precision, higher CPU overhead

Counter Width

  • 16-bit: May overflow quickly, need careful handling
  • 32-bit: Good for most applications, overflows after ~4 seconds at 1 GHz
  • 64-bit: Effectively never overflows, preferred for ARMv8

Interrupt Latency

  • Keep ISR short - only call rt_clock_hrtimer_process()
  • Disable timer interrupt while processing to avoid re-entry
  • Consider interrupt priority relative to other system interrupts

Debugging Tips

  1. Verify frequency: Print actual frequency during initialization

    rt_kprintf("Timer freq: %d Hz\n", (rt_uint32_t)rt_clock_time_getfreq());
    
  2. Test counter increment: Verify counter is actually counting

    rt_uint64_t cnt1 = rt_clock_time_getcnt();
    rt_thread_mdelay(1);
    rt_uint64_t cnt2 = rt_clock_time_getcnt();
    rt_kprintf("Counter delta: %d (expected ~%d)\n", 
              (rt_uint32_t)(cnt2 - cnt1), 
              (rt_uint32_t)(rt_clock_time_getfreq() / 1000));
    
  3. Check interrupt firing: Add debug output in ISR

    static int isr_count = 0;
    void timer_isr(void) {
       isr_count++;
       if (isr_count % 1000 == 0) {
           rt_kprintf("Timer ISR count: %d\n", isr_count);
       }
    }
    

Examples in BSPs

Look for these files in various BSPs for real-world examples:

  • bsp/qemu-virt64-aarch64/drivers/drv_timer.c - ARM Generic Timer
  • bsp/stm32/libraries/HAL_Drivers/drv_hwtimer.c - STM32 hardware timers
  • bsp/rockchip/*/driver/hwtimer/ - Rockchip timer drivers

Contributing

When contributing a new adapter:

  1. Add comprehensive comments explaining hardware specifics
  2. Include initialization and ISR examples
  3. Document any platform-specific requirements
  4. Test on actual hardware if possible
  5. Update this README with your adapter details