Browse Source

[clock_time] Add comprehensive examples and test code

- Created clock_time_example.c with 7 different usage examples
- Added examples for info display, boottime, conversion, delays, timers
- Included performance benchmark example
- Added comprehensive examples README with troubleshooting guide

Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
copilot-swe-agent[bot] 1 month ago
parent
commit
0866b88dc6
2 changed files with 544 additions and 0 deletions
  1. 241 0
      examples/clock_time/README.md
  2. 303 0
      examples/clock_time/clock_time_example.c

+ 241 - 0
examples/clock_time/README.md

@@ -0,0 +1,241 @@
+# Clock Time Examples
+
+This directory contains examples demonstrating the use of the unified `clock_time` subsystem.
+
+## Prerequisites
+
+Enable `RT_USING_CLOCK_TIME` in your configuration:
+```
+CONFIG_RT_USING_CLOCK_TIME=y
+```
+
+## Available Examples
+
+### 1. Clock Time Information (`clock_time_info_example`)
+Displays basic information about the clock_time device:
+- Clock frequency
+- Clock resolution
+- Current counter value
+- Device capabilities
+
+**Usage:**
+```
+msh> clock_time_info_example
+```
+
+### 2. Boottime Tracking (`clock_boottime_example`)
+Shows system uptime in different formats:
+- Nanosecond precision
+- Microsecond precision
+- Second precision
+
+**Usage:**
+```
+msh> clock_boottime_example
+```
+
+### 3. Time Conversion (`clock_conversion_example`)
+Demonstrates conversion between counter ticks and time units (ms, us, ns).
+
+**Usage:**
+```
+msh> clock_conversion_example
+```
+
+### 4. High-Precision Delay (`clock_delay_example`)
+Tests high-precision delay functions and measures actual delays:
+- Microsecond delays (`rt_clock_udelay`)
+- Millisecond delays (`rt_clock_mdelay`)
+
+**Usage:**
+```
+msh> clock_delay_example
+```
+
+### 5. One-Shot Timer (`clock_hrtimer_oneshot_example`)
+Demonstrates using a high-resolution timer for one-shot timeouts.
+
+**Usage:**
+```
+msh> clock_hrtimer_oneshot_example
+```
+
+**Expected Output:**
+```
+=== High-Resolution Timer (One-Shot) Example ===
+Starting timer for 500ms...
+Timer started successfully
+High-resolution timer fired! Parameter: One-shot timer
+Timer example complete
+```
+
+### 6. Periodic Timer (`clock_hrtimer_periodic_example`)
+Demonstrates using a high-resolution timer for periodic callbacks.
+
+**Usage:**
+```
+msh> clock_hrtimer_periodic_example
+```
+
+**Expected Output:**
+```
+=== High-Resolution Timer (Periodic) Example ===
+Starting periodic timer (200ms period)...
+Timer started successfully
+Periodic timer tick #1
+Periodic timer tick #2
+Periodic timer tick #3
+Periodic timer tick #4
+Periodic timer tick #5
+Timer stopped. Total ticks: 5
+```
+
+### 7. Performance Benchmark (`clock_benchmark_example`)
+Measures the overhead of clock_time operations:
+- `get_counter()` call overhead
+- Time conversion overhead
+
+**Usage:**
+```
+msh> clock_benchmark_example
+```
+
+### Run All Examples (`clock_time_examples_all`)
+Runs all examples in sequence.
+
+**Usage:**
+```
+msh> clock_time_examples_all
+```
+
+## Building the Examples
+
+### Method 1: Include in BSP
+
+Add to your BSP's `applications/SConscript`:
+```python
+src += Glob('../../examples/clock_time/*.c')
+```
+
+### Method 2: Manual Compilation
+
+Copy `clock_time_example.c` to your BSP's `applications` directory and rebuild.
+
+### Method 3: menuconfig
+
+Some BSPs may include examples in menuconfig. Look for:
+```
+RT-Thread online packages --->
+    miscellaneous packages --->
+        [*] Enable clock_time examples
+```
+
+## Interpreting Results
+
+### Delay Accuracy
+The delay examples measure actual vs. target delays. Typical results:
+- **Good**: Actual delay within 1-5% of target
+- **Acceptable**: Actual delay within 10% of target
+- **Poor**: Actual delay > 10% off target (may indicate timer issues)
+
+Factors affecting accuracy:
+- Timer resolution
+- Interrupt latency
+- System load
+- Compiler optimizations
+
+### Performance Benchmarks
+Typical overhead values (depending on platform):
+- `get_counter()`: 10-100 ns per call
+- `cnt_to_us()`: 50-500 ns per call
+
+Lower values are better. Very high values may indicate:
+- Slow hardware timer access
+- Cache misses
+- Inefficient implementation
+
+## Troubleshooting
+
+### "RT_USING_CLOCK_TIME is not enabled"
+Enable the clock_time subsystem in Kconfig:
+```
+Device Drivers --->
+    [*] Using unified clock_time subsystem
+```
+
+### "No clock_time device found"
+No clock_time device has been registered. Options:
+1. Enable an adapter (e.g., ARM Generic Timer, SysTick)
+2. Implement a custom adapter for your hardware
+3. The tick-based fallback should be available
+
+### Timer callbacks not firing
+If one-shot or periodic timers don't fire:
+1. Check that your clock_time device supports `RT_CLOCK_TIME_CAP_CLOCKEVENT`
+2. Verify the timer ISR calls `rt_clock_hrtimer_process()`
+3. Check interrupt configuration and priority
+4. Ensure timer interrupts are enabled
+
+### Inaccurate delays
+If delays are consistently off:
+1. Verify timer frequency with `clock_time_info_example`
+2. Check for interrupt latency issues
+3. Ensure timer counter is actually counting
+4. Consider using a higher frequency timer
+
+## Advanced Usage
+
+### Custom Timer Callbacks
+
+```c
+static void my_callback(void *parameter)
+{
+    int *count = (int *)parameter;
+    (*count)++;
+    rt_kprintf("Callback executed %d times\n", *count);
+}
+
+void custom_timer_example(void)
+{
+    struct rt_clock_hrtimer timer;
+    int count = 0;
+    
+    rt_clock_hrtimer_init(&timer, "custom", 
+                         RT_TIMER_FLAG_PERIODIC,
+                         my_callback, 
+                         &count);
+    
+    unsigned long period = (unsigned long)rt_clock_time_ms_to_cnt(100);
+    rt_clock_hrtimer_start(&timer, period);
+    
+    /* Let it run... */
+    rt_thread_mdelay(1000);
+    
+    rt_clock_hrtimer_stop(&timer);
+    rt_clock_hrtimer_detach(&timer);
+}
+```
+
+### Precision Timing
+
+```c
+void measure_function_time(void)
+{
+    unsigned long start = (unsigned long)rt_clock_time_getcnt();
+    
+    /* Function to measure */
+    my_function();
+    
+    unsigned long end = (unsigned long)rt_clock_time_getcnt();
+    unsigned long delta = end - start;
+    
+    rt_kprintf("Function took %u us\n", 
+               (rt_uint32_t)rt_clock_time_cnt_to_us(delta));
+}
+```
+
+## See Also
+
+- [Clock Time Documentation](../../documentation/6.components/device-driver/clock_time.md)
+- [Clock Time README](../../components/drivers/clock_time/README.md)
+- [Adapter Examples](../../components/drivers/clock_time/adapters/)

+ 303 - 0
examples/clock_time/clock_time_example.c

@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2024-12-04     RT-Thread    clock_time usage examples
+ */
+
+/**
+ * @file clock_time_example.c
+ * @brief Examples demonstrating the unified clock_time subsystem
+ * 
+ * This file contains various examples showing how to use the clock_time
+ * subsystem for different time-related tasks.
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#ifdef RT_USING_CLOCK_TIME
+
+/**
+ * @brief Example 1: Basic time information
+ * 
+ * Demonstrates how to get clock frequency, resolution, and current counter.
+ */
+static void clock_time_info_example(void)
+{
+    rt_kprintf("\n=== Clock Time Info Example ===\n");
+    
+    /* Get clock frequency */
+    rt_uint64_t freq = rt_clock_time_getfreq();
+    rt_kprintf("Clock frequency: %u Hz\n", (rt_uint32_t)freq);
+    
+    /* Get clock resolution (in nanoseconds * RT_CLOCK_TIME_RESMUL) */
+    rt_uint64_t res = rt_clock_time_getres();
+    rt_kprintf("Clock resolution: %u ns (scaled)\n", 
+               (rt_uint32_t)(res / RT_CLOCK_TIME_RESMUL));
+    
+    /* Get current counter value */
+    rt_uint64_t cnt = rt_clock_time_getcnt();
+    rt_kprintf("Current counter: %u\n", (rt_uint32_t)cnt);
+    
+    /* Get device info */
+    struct rt_clock_time_device *dev = rt_clock_time_get_default();
+    if (dev)
+    {
+        rt_kprintf("Device name: %s\n", dev->parent.parent.name);
+        rt_kprintf("Capabilities: ");
+        if (dev->caps & RT_CLOCK_TIME_CAP_CLOCKSOURCE)
+            rt_kprintf("CLOCKSOURCE ");
+        if (dev->caps & RT_CLOCK_TIME_CAP_CLOCKEVENT)
+            rt_kprintf("CLOCKEVENT ");
+        rt_kprintf("\n");
+    }
+}
+MSH_CMD_EXPORT(clock_time_info_example, Show clock time information);
+
+/**
+ * @brief Example 2: Boottime tracking
+ * 
+ * Demonstrates how to get system uptime in different formats.
+ */
+static void clock_boottime_example(void)
+{
+    struct timespec ts;
+    struct timeval tv;
+    time_t t;
+    
+    rt_kprintf("\n=== Boottime Example ===\n");
+    
+    /* Get boottime in nanoseconds */
+    rt_clock_time_boottime_ns(&ts);
+    rt_kprintf("Boottime (ns): %d.%09d seconds\n", 
+               (rt_uint32_t)ts.tv_sec, (rt_uint32_t)ts.tv_nsec);
+    
+    /* Get boottime in microseconds */
+    rt_clock_time_boottime_us(&tv);
+    rt_kprintf("Boottime (us): %d.%06d seconds\n", 
+               (rt_uint32_t)tv.tv_sec, (rt_uint32_t)tv.tv_usec);
+    
+    /* Get boottime in seconds */
+    rt_clock_time_boottime_s(&t);
+    rt_kprintf("Boottime (s):  %d seconds\n", (rt_uint32_t)t);
+}
+MSH_CMD_EXPORT(clock_boottime_example, Show system boottime);
+
+/**
+ * @brief Example 3: Time conversion
+ * 
+ * Demonstrates conversion between counter ticks and time units.
+ */
+static void clock_conversion_example(void)
+{
+    rt_kprintf("\n=== Time Conversion Example ===\n");
+    
+    /* Convert 1 second to counter ticks */
+    unsigned long cnt_1s = (unsigned long)rt_clock_time_ms_to_cnt(1000);
+    rt_kprintf("1 second = %u counter ticks\n", cnt_1s);
+    
+    /* Convert back to time units */
+    rt_uint64_t ms = rt_clock_time_cnt_to_ms(cnt_1s);
+    rt_uint64_t us = rt_clock_time_cnt_to_us(cnt_1s);
+    rt_uint64_t ns = rt_clock_time_cnt_to_ns(cnt_1s);
+    
+    rt_kprintf("  = %u ms\n", (rt_uint32_t)ms);
+    rt_kprintf("  = %u us\n", (rt_uint32_t)us);
+    rt_kprintf("  = %u ns\n", (rt_uint32_t)ns);
+}
+MSH_CMD_EXPORT(clock_conversion_example, Show time conversion);
+
+/**
+ * @brief Example 4: High-precision delay
+ * 
+ * Demonstrates using high-precision delay functions.
+ */
+static void clock_delay_example(void)
+{
+    rt_kprintf("\n=== High-Precision Delay Example ===\n");
+    
+    /* Measure delay accuracy */
+    unsigned long start_cnt = (unsigned long)rt_clock_time_getcnt();
+    
+    rt_kprintf("Delaying 100 microseconds...\n");
+    rt_clock_udelay(100);
+    
+    unsigned long end_cnt = (unsigned long)rt_clock_time_getcnt();
+    unsigned long delta_cnt = end_cnt - start_cnt;
+    
+    rt_uint64_t actual_us = rt_clock_time_cnt_to_us(delta_cnt);
+    rt_kprintf("Actual delay: %u us (target: 100 us)\n", (rt_uint32_t)actual_us);
+    
+    /* Millisecond delay */
+    start_cnt = (unsigned long)rt_clock_time_getcnt();
+    rt_kprintf("Delaying 10 milliseconds...\n");
+    rt_clock_mdelay(10);
+    end_cnt = (unsigned long)rt_clock_time_getcnt();
+    delta_cnt = end_cnt - start_cnt;
+    
+    rt_uint64_t actual_ms = rt_clock_time_cnt_to_ms(delta_cnt);
+    rt_kprintf("Actual delay: %u ms (target: 10 ms)\n", (rt_uint32_t)actual_ms);
+}
+MSH_CMD_EXPORT(clock_delay_example, Demonstrate high-precision delays);
+
+/**
+ * @brief Example 5: High-resolution timer (one-shot)
+ * 
+ * Demonstrates using high-resolution timer for one-shot timeout.
+ */
+static void hrtimer_callback(void *parameter)
+{
+    rt_kprintf("High-resolution timer fired! Parameter: %s\n", 
+               (char *)parameter);
+}
+
+static void clock_hrtimer_oneshot_example(void)
+{
+    struct rt_clock_hrtimer timer;
+    
+    rt_kprintf("\n=== High-Resolution Timer (One-Shot) Example ===\n");
+    
+    /* Initialize one-shot timer */
+    rt_clock_hrtimer_init(&timer, "oneshot_timer", 
+                         RT_TIMER_FLAG_ONE_SHOT,
+                         hrtimer_callback, 
+                         (void *)"One-shot timer");
+    
+    /* Start with 500ms delay */
+    unsigned long delay_cnt = (unsigned long)rt_clock_time_ms_to_cnt(500);
+    rt_kprintf("Starting timer for 500ms...\n");
+    
+    rt_err_t result = rt_clock_hrtimer_start(&timer, delay_cnt);
+    if (result == RT_EOK)
+    {
+        rt_kprintf("Timer started successfully\n");
+    }
+    
+    /* Let timer fire, then cleanup */
+    rt_thread_mdelay(600);
+    rt_clock_hrtimer_detach(&timer);
+    
+    rt_kprintf("Timer example complete\n");
+}
+MSH_CMD_EXPORT(clock_hrtimer_oneshot_example, Demonstrate one-shot hrtimer);
+
+/**
+ * @brief Example 6: High-resolution timer (periodic)
+ * 
+ * Demonstrates using high-resolution timer for periodic callbacks.
+ */
+static volatile int periodic_count = 0;
+
+static void periodic_callback(void *parameter)
+{
+    periodic_count++;
+    rt_kprintf("Periodic timer tick #%d\n", periodic_count);
+}
+
+static void clock_hrtimer_periodic_example(void)
+{
+    struct rt_clock_hrtimer timer;
+    
+    rt_kprintf("\n=== High-Resolution Timer (Periodic) Example ===\n");
+    
+    /* Initialize periodic timer */
+    rt_clock_hrtimer_init(&timer, "periodic_timer", 
+                         RT_TIMER_FLAG_PERIODIC,
+                         periodic_callback, 
+                         RT_NULL);
+    
+    /* Start with 200ms period */
+    unsigned long period_cnt = (unsigned long)rt_clock_time_ms_to_cnt(200);
+    rt_kprintf("Starting periodic timer (200ms period)...\n");
+    
+    periodic_count = 0;
+    rt_err_t result = rt_clock_hrtimer_start(&timer, period_cnt);
+    if (result == RT_EOK)
+    {
+        rt_kprintf("Timer started successfully\n");
+    }
+    
+    /* Let it tick 5 times */
+    rt_thread_mdelay(1100);
+    
+    /* Stop and cleanup */
+    rt_clock_hrtimer_stop(&timer);
+    rt_clock_hrtimer_detach(&timer);
+    
+    rt_kprintf("Timer stopped. Total ticks: %d\n", periodic_count);
+}
+MSH_CMD_EXPORT(clock_hrtimer_periodic_example, Demonstrate periodic hrtimer);
+
+/**
+ * @brief Example 7: Benchmark overhead
+ * 
+ * Measures the overhead of various clock_time operations.
+ */
+static void clock_benchmark_example(void)
+{
+    const int iterations = 1000;
+    unsigned long start, end;
+    int i;
+    
+    rt_kprintf("\n=== Clock Time Benchmark ===\n");
+    
+    /* Benchmark get_counter() */
+    start = (unsigned long)rt_clock_time_getcnt();
+    for (i = 0; i < iterations; i++)
+    {
+        volatile unsigned long cnt = (unsigned long)rt_clock_time_getcnt();
+        (void)cnt;
+    }
+    end = (unsigned long)rt_clock_time_getcnt();
+    rt_kprintf("get_counter() x%d: %u ns per call\n", 
+               iterations,
+               (rt_uint32_t)(rt_clock_time_cnt_to_ns(end - start) / iterations));
+    
+    /* Benchmark time conversion */
+    start = (unsigned long)rt_clock_time_getcnt();
+    for (i = 0; i < iterations; i++)
+    {
+        volatile rt_uint64_t us = rt_clock_time_cnt_to_us(1000);
+        (void)us;
+    }
+    end = (unsigned long)rt_clock_time_getcnt();
+    rt_kprintf("cnt_to_us() x%d: %u ns per call\n", 
+               iterations,
+               (rt_uint32_t)(rt_clock_time_cnt_to_ns(end - start) / iterations));
+}
+MSH_CMD_EXPORT(clock_benchmark_example, Benchmark clock_time operations);
+
+/**
+ * @brief Run all examples
+ */
+static void clock_time_examples_all(void)
+{
+    clock_time_info_example();
+    rt_thread_mdelay(100);
+    
+    clock_boottime_example();
+    rt_thread_mdelay(100);
+    
+    clock_conversion_example();
+    rt_thread_mdelay(100);
+    
+    clock_delay_example();
+    rt_thread_mdelay(100);
+    
+    clock_hrtimer_oneshot_example();
+    rt_thread_mdelay(100);
+    
+    clock_hrtimer_periodic_example();
+    rt_thread_mdelay(100);
+    
+    clock_benchmark_example();
+}
+MSH_CMD_EXPORT(clock_time_examples_all, Run all clock_time examples);
+
+#else
+#warning "RT_USING_CLOCK_TIME is not enabled. Examples will not be compiled."
+#endif /* RT_USING_CLOCK_TIME */