diff --git a/examples/clock_time/README.md b/examples/clock_time/README.md new file mode 100644 index 0000000000..c03c7418ba --- /dev/null +++ b/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/) diff --git a/examples/clock_time/clock_time_example.c b/examples/clock_time/clock_time_example.c new file mode 100644 index 0000000000..fc521171cd --- /dev/null +++ b/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 +#include + +#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 */