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


The following commit(s) were added to refs/heads/master by this push:
     new 3edf6de552d drivers/timers/arch_alarm: Revert removal of 
ndelay_accurate
3edf6de552d is described below

commit 3edf6de552d863e7a0c83305c84ce750948c2dfb
Author: Matteo Golin <[email protected]>
AuthorDate: Mon Oct 20 20:36:05 2025 -0400

    drivers/timers/arch_alarm: Revert removal of ndelay_accurate
    
    This reverts the removal of ndelay_accurate from #14450, since as
    mentioned in #17011, this fails to consider the `sim` architecture
    where CONFIG_BOARD_LOOPSPERMSEC was set to 0 because of reliance on the
    accurate implementations of the up_delay functions. All the commit did
    was remove a more accurate implementation in favour of a less accurate
    one.
    
    Signed-off-by: Matteo Golin <[email protected]>
---
 drivers/timers/arch_alarm.c | 120 ++++++++++++++++++++++++++++++++++++++++++++
 sched/clock/CMakeLists.txt  |   2 +-
 sched/clock/Make.defs       |   4 +-
 3 files changed, 124 insertions(+), 2 deletions(-)

diff --git a/drivers/timers/arch_alarm.c b/drivers/timers/arch_alarm.c
index 7a825b06446..de1019ab871 100644
--- a/drivers/timers/arch_alarm.c
+++ b/drivers/timers/arch_alarm.c
@@ -30,6 +30,14 @@
 #include <nuttx/clock.h>
 #include <nuttx/timers/arch_alarm.h>
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define CONFIG_BOARD_LOOPSPER100USEC ((CONFIG_BOARD_LOOPSPERMSEC+5)/10)
+#define CONFIG_BOARD_LOOPSPER10USEC  ((CONFIG_BOARD_LOOPSPERMSEC+50)/100)
+#define CONFIG_BOARD_LOOPSPERUSEC    ((CONFIG_BOARD_LOOPSPERMSEC+500)/1000)
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -44,6 +52,69 @@ static clock_t g_current_tick;
  * Private Functions
  ****************************************************************************/
 
+static void udelay_coarse(useconds_t microseconds)
+{
+  volatile int i;
+
+  /* We'll do this a little at a time because we expect that the
+   * CONFIG_BOARD_LOOPSPERUSEC is very inaccurate during to truncation in
+   * the divisions of its calculation.  We'll use the largest values that
+   * we can in order to prevent significant error buildup in the loops.
+   */
+
+  while (microseconds > 1000)
+    {
+      for (i = 0; i < CONFIG_BOARD_LOOPSPERMSEC; i++)
+        {
+        }
+
+      microseconds -= 1000;
+    }
+
+  while (microseconds > 100)
+    {
+      for (i = 0; i < CONFIG_BOARD_LOOPSPER100USEC; i++)
+        {
+        }
+
+      microseconds -= 100;
+    }
+
+  while (microseconds > 10)
+    {
+      for (i = 0; i < CONFIG_BOARD_LOOPSPER10USEC; i++)
+        {
+        }
+
+      microseconds -= 10;
+    }
+
+  while (microseconds > 0)
+    {
+      for (i = 0; i < CONFIG_BOARD_LOOPSPERUSEC; i++)
+        {
+        }
+
+      microseconds--;
+    }
+}
+
+static void ndelay_accurate(unsigned long nanoseconds)
+{
+  struct timespec now;
+  struct timespec end;
+  struct timespec delta;
+
+  ONESHOT_CURRENT(g_oneshot_lower, &now);
+  clock_nsec2time(&delta, nanoseconds);
+  clock_timespec_add(&now, &delta, &end);
+
+  while (clock_timespec_compare(&now, &end) < 0)
+    {
+      ONESHOT_CURRENT(g_oneshot_lower, &now);
+    }
+}
+
 static void oneshot_callback(FAR struct oneshot_lowerhalf_s *lower,
                              FAR void *arg)
 {
@@ -74,6 +145,55 @@ static void oneshot_callback(FAR struct oneshot_lowerhalf_s 
*lower,
  * Public Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: up_mdelay
+ *
+ * Description:
+ *   Delay inline for the requested number of milliseconds.
+ *   WARNING: NOT multi-tasking friendly
+ *
+ ****************************************************************************/
+
+void weak_function up_mdelay(unsigned int milliseconds)
+{
+  up_udelay(USEC_PER_MSEC * milliseconds);
+}
+
+/****************************************************************************
+ * Name: up_udelay
+ *
+ * Description:
+ *   Delay inline for the requested number of microseconds.
+ *   WARNING: NOT multi-tasking friendly
+ *
+ ****************************************************************************/
+
+void weak_function up_udelay(useconds_t microseconds)
+{
+  up_ndelay(NSEC_PER_USEC * microseconds);
+}
+
+/****************************************************************************
+ * Name: up_ndelay
+ *
+ * Description:
+ *   Delay inline for the requested number of nanoseconds.
+ *   WARNING: NOT multi-tasking friendly
+ *
+ ****************************************************************************/
+
+void weak_function up_ndelay(unsigned long nanoseconds)
+{
+  if (g_oneshot_lower != NULL)
+    {
+      ndelay_accurate(nanoseconds);
+    }
+  else /* Oneshot timer hasn't been initialized yet */
+    {
+      udelay_coarse((nanoseconds + NSEC_PER_USEC - 1) / NSEC_PER_USEC);
+    }
+}
+
 void up_alarm_set_lowerhalf(FAR struct oneshot_lowerhalf_s *lower)
 {
 #ifdef CONFIG_SCHED_TICKLESS
diff --git a/sched/clock/CMakeLists.txt b/sched/clock/CMakeLists.txt
index 9599bb972fd..62c4346bf0d 100644
--- a/sched/clock/CMakeLists.txt
+++ b/sched/clock/CMakeLists.txt
@@ -35,7 +35,7 @@ set(SRCS
 # include the base delay definition (busy-loop) as a minimum-viable product. We
 # don't want the weak references to conflict.
 
-if(NOT CONFIG_TIMER_ARCH)
+if(NOT CONFIG_TIMER_ARCH AND NOT CONFIG_ALARM_ARCH)
   list(APPEND SRCS delay.c)
 endif()
 
diff --git a/sched/clock/Make.defs b/sched/clock/Make.defs
index 00b723b8af0..e61da4dbd9e 100644
--- a/sched/clock/Make.defs
+++ b/sched/clock/Make.defs
@@ -29,7 +29,9 @@ CSRCS += clock_perf.c clock_realtime2absticks.c
 # don't want the weak references to conflict.
 
 ifneq ($(CONFIG_TIMER_ARCH),y)
-  CSRCS += delay.c
+  ifneq ($(CONFIG_ALARM_ARCH),y)
+    CSRCS += delay.c
+  endif
 endif
 
 ifeq ($(CONFIG_CLOCK_TIMEKEEPING),y)

Reply via email to