This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 3b52763385e2c0bee40e216e807acc03349f82fc
Author: ouyangxiangzhen <[email protected]>
AuthorDate: Fri Nov 7 15:25:45 2025 +0800

    Documentation/componensts: Add doc for timers/oneshot.
    
    This commit added doc for timers/oneshot.
    
    Signed-off-by: ouyangxiangzhen <[email protected]>
---
 Documentation/components/drivers/index.rst         |   1 +
 .../components/drivers/timers/oneshot/index.rst    | 159 +++++++++++++++++++++
 2 files changed, 160 insertions(+)

diff --git a/Documentation/components/drivers/index.rst 
b/Documentation/components/drivers/index.rst
index e5dfd879ac8..2ad2e1ac721 100644
--- a/Documentation/components/drivers/index.rst
+++ b/Documentation/components/drivers/index.rst
@@ -12,6 +12,7 @@ divided in three classes:
   block/index.rst
   special/index.rst
   thermal/index.rst
+  timers/oneshot/index.rst
 
 .. note::
   Device driver support depends on the *in-memory*, *pseudo*
diff --git a/Documentation/components/drivers/timers/oneshot/index.rst 
b/Documentation/components/drivers/timers/oneshot/index.rst
new file mode 100644
index 00000000000..6a29b4ae19b
--- /dev/null
+++ b/Documentation/components/drivers/timers/oneshot/index.rst
@@ -0,0 +1,159 @@
+=====================
+Oneshot Timer Drivers
+=====================
+
+The NuttX timing subsystem consists of four layers:
+
+  * 1 Hardware Timer Drivers: Includes implementations of various hardware
+                              timer drivers.
+  * 2 Timer Driver Abstraction: Such as Oneshot and Timer, which provide
+                                timer hardware abstraction.
+  * 3 OS Timer Interfaces: Timer and Alarm, offering relative and
+                           absolute timer interfaces.
+  * 4 OS Timer Abstraction: The wdog (watchdog) module manages software timers
+                            and provides a unified timer API to upper layers.
+
+Here we focus on the oneshot timer driver abstraction.
+
+Oneshot is the timer driver abstraction that provides:
+
+  * Unified API for different timer hardware.
+  * Functional correct and optimized timing conversion between
+    cycle counts and natural time.
+
+Background
+==========
+
+Computers typically rely on hardware cycle counters that count level changes
+from external clock signals. These signals are generated by a crystal
+oscillator. The signal then goes through a Phase-Locked Loop (PLL) for
+frequency multiplication, and is output as the clock signal to the
+hardware cycle counter.
+
+The counter counting up or counting down—with each level changes, enabling
+hardware-based timing. To generate timing interrupts, timer hardware includes
+a comparator. It triggers a CPU interrupt when the down-counter reaches zero
+or the cycle counter matches a preset value.
+
+Based on the functions of the timers, we can abstract a minimal set of
+capabilities that a timer should provide:
+
+  * 1. Read the current cycle count
+  * 2. Trigger an event at an absolute cycle count
+  * 3. Trigger an event after a relative cycle count
+
+From an OS perspective, The second one and third one are functionally
+equivalent assuming the first one is available. By reprogramming the timer,
+these can also emulate periodical timers. Although these methods are similar
+in expressiveness, timers that use relative delays tend to be less accurate
+and efficient than those supporting absolute timing. This is because reading
+the current time introduces additional CPU overhead, affecting both
+timing-precision and performance.
+
+Oneshot Drivers API
+===================
+
+OneShot currently offers new count-based interfaces, while also providing
+timespec-based interfaces for compatibility with older drivers.
+We strongly recommend using the count-based interface due to its superior
+performance. Besides, count-based APIs are easier to implement, as they only
+need to focus on reading and writing timer-related registers without
+needing to perform error-prone time conversion.
+
+In count-based interface design, oneshot adopts the following principles:
+
+  * Minimalist design: Significantly simplifies the implementation
+                       for drivers.
+  * Count-based interfaces: Uses count cycles as the unit for both reading
+                            time and setting timers.
+  * Supports both absolute and relative timers: Compatible with underlying
+              timer hardware, regardless of whether it uses absolute or
+              relative timing.
+  * No status returns: Since read/write operations on timer hardware should
+                       not fail, any failure should result in an assertion
+                       at the driver level.
+  * No callbacks or parameters: All expiration callback and parameter
+                       management is handled at the upper layer,
+                       preventing thread-unsafe usage.
+
+The count-based interface is as follows:
+
+  * ``clkcnt_t (*current)(FAR struct oneshot_lowerhalf_s *lower);``
+  * ``void     (*start)(FAR struct oneshot_lowerhalf_s *lower, clkcnt_t 
delay);``
+  * ``void     (*start_absolute)(FAR struct oneshot_lowerhalf_s *lower, 
clkcnt_t cnt);``
+  * ``void     (*cancel)(FAR struct oneshot_lowerhalf_s *lower);``
+  * ``clkcnt_t (*max_delay)(FAR struct oneshot_lowerhalf_s *lower);``
+
+The above count-based interfaces provide functions for:
+
+  * getting the current timer count,
+  * starting a relative timer,
+  * starting an absolute timer,
+  * canceling a timer event
+  * and getting the maximum timer delay.
+
+Note that if the driver uses a count-based API, it should call
+``oneshot_count_init`` during initialization to tell the upper-layer
+the timer frequency.
+
+The count-based interfaces are enabled via ``CONFIG_ONESHOT_COUNT``.
+
+The following are the deprecated timespec interfaces:
+
+  * ``int (*max_delay)(FAR struct oneshot_lowerhalf_s *lower, FAR struct 
timespec *ts);``
+  * ``int (*start)(FAR struct oneshot_lowerhalf_s *lower, FAR const struct 
timespec *ts);``
+  * ``int (*cancel)(FAR struct oneshot_lowerhalf_s *lower, FAR struct timespec 
*ts);``
+  * ``int (*current)(FAR struct oneshot_lowerhalf_s *lower, FAR struct 
timespec *ts);``
+
+They provide functions for:
+
+  * getting the maximum timer delay,
+  * starting a relative timer,
+  * canceling a timer event
+  * and getting the current timer count.
+
+ClockCount
+==========
+
+The recommended oneshot APIs are all count-based. So how do we handle time
+conversion? We provide a unified ClockCount(clockcount.h) layer for fast and
+safe time conversions, including:
+
+  * count to timespec
+  * count to tick
+  * timespec to count
+  * tick to count
+
+We notice that there always at least two divisions in timing conversion. So
+clockcount implements two methods to accelerate time conversion:
+
+  1. Invariant Divisor Division Optimization: Used for converting counts
+  to seconds or ticks. It can be enabled via ``CONFIG_ONESHOT_FAST_DIVISION``.
+  This division optimization can transforms a division into:
+
+    * one unsigned high multiplication (UMULH),
+    * one subtraction,
+    * one addition, and
+    * one logical right shift (LShR).
+
+  Please note that Invariant Divisor Division Optimization does not
+  necessarily provide a performance advantage. It is related to the
+  overhead of UMULH and UDIV instructions on different CPU platforms.
+  E.g. On early ARMv8A platforms (Cortex A-53), UMULH took 6 cycles,
+  which meant that enabling optimization was actually less efficient
+  than direct division using the UDIV instructions.
+
+  2. Multiply-Shift Approximate Division: Used to convert delta counts into
+  nanoseconds or ticks.
+
+  Note this was enabled by default. If extramely precise time conversion
+  is required, it should be disable.
+  This method trades off slight precision (a few nanoseconds) for better
+  performance. However, due to potential multiplication overflow, it is
+  only suitable for relative time conversions.
+  The first method is exact, but takes about 6-9 CPU cycles. The
+  approximate approach requires only one unsigned multiplication and one
+  LShR, typically consuming around 4 CPU cycles, making it
+  significantly faster.
+
+Combining 1 and 2, we can achieve a fast and precise time conversion.

Reply via email to