drivers/timers/arch_alarm: Revert removal of ndelay_accurate
Some checks failed
Docker-Linux / push (push) Has been cancelled

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 <matteo.golin@gmail.com>
This commit is contained in:
Matteo Golin
2025-10-20 20:36:05 -04:00
committed by Xiang Xiao
parent cf30528231
commit 3edf6de552
3 changed files with 124 additions and 2 deletions

View File

@@ -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

View File

@@ -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()

View File

@@ -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)