Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions drivers/timers/arch_alarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
****************************************************************************/
Expand All @@ -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)
{
Expand Down Expand Up @@ -82,6 +153,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
Expand Down
2 changes: 1 addition & 1 deletion sched/clock/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,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()

Expand Down
4 changes: 3 additions & 1 deletion sched/clock/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading