diff --git a/drivers/timers/arch_alarm.c b/drivers/timers/arch_alarm.c index 22c9a275bcf..731a05e6c45 100644 --- a/drivers/timers/arch_alarm.c +++ b/drivers/timers/arch_alarm.c @@ -392,6 +392,47 @@ int up_alarm_start(FAR const struct timespec *ts) } #endif +/******************************************************************************** + * Name: up_critmon_* + * + * Description: + * The first interface simply provides the current time value in unknown + * units. NOTE: This function may be called early before the timer has + * been initialized. In that event, the function should just return a + * start time of zero. + * + * Nothing is assumed about the units of this time value. The following + * are assumed, however: (1) The time is an unsigned integer value, (2) + * the time is monotonically increasing, and (3) the elapsed time (also + * in unknown units) can be obtained by subtracting a start time from + * the current time. + * + * The second interface simple converts an elapsed time into well known + * units. + ********************************************************************************/ + +#ifdef CONFIG_SCHED_CRITMONITOR +uint32_t up_critmon_gettime(void) +{ + uint32_t ret = 0; + + if (g_oneshot_lower != NULL) + { + struct timespec ts; + + ONESHOT_CURRENT(g_oneshot_lower, &ts); + ret = timespec_to_usec(&ts); + } + + return ret; +} + +void up_critmon_convert(uint32_t elapsed, FAR struct timespec *ts) +{ + timespec_from_usec(ts, elapsed); +} +#endif + /**************************************************************************** * Name: up_mdelay * diff --git a/drivers/timers/arch_timer.c b/drivers/timers/arch_timer.c index 75fe6864fd2..9d38ae4f6a2 100644 --- a/drivers/timers/arch_timer.c +++ b/drivers/timers/arch_timer.c @@ -91,12 +91,8 @@ static struct arch_timer_s g_timer; * Private Functions ****************************************************************************/ -#ifdef CONFIG_SCHED_TICKLESS -static inline uint64_t timespec_to_usec(const FAR struct timespec *ts) -{ - return (uint64_t)ts->tv_sec * USEC_PER_SEC + ts->tv_nsec / NSEC_PER_USEC; -} - +#if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_SCHED_CRITMONITOR) \ + || defined(CONFIG_SCHED_IRQMONITOR_GETTIME) static inline void timespec_from_usec(FAR struct timespec *ts, uint64_t microseconds) { @@ -104,6 +100,13 @@ static inline void timespec_from_usec(FAR struct timespec *ts, microseconds -= (uint64_t)ts->tv_sec * USEC_PER_SEC; ts->tv_nsec = microseconds * NSEC_PER_USEC; } +#endif + +#ifdef CONFIG_SCHED_TICKLESS +static inline uint64_t timespec_to_usec(const FAR struct timespec *ts) +{ + return (uint64_t)ts->tv_sec * USEC_PER_SEC + ts->tv_nsec / NSEC_PER_USEC; +} static inline bool timeout_diff(uint32_t new, uint32_t old) { @@ -143,12 +146,13 @@ static uint64_t current_usec(void) { struct timer_status_s status; uint64_t timebase; - irqstate_t flags; - flags = enter_critical_section(); - TIMER_GETSTATUS(g_timer.lower, &status); - timebase = g_timer.timebase; - leave_critical_section(flags); + do + { + timebase = g_timer.timebase; + TIMER_GETSTATUS(g_timer.lower, &status); + } + while (timebase != g_timer.timebase); return timebase + (status.timeout - status.timeleft); } @@ -425,6 +429,44 @@ int up_timer_start(FAR const struct timespec *ts) } #endif +/******************************************************************************** + * Name: up_critmon_* + * + * Description: + * The first interface simply provides the current time value in unknown + * units. NOTE: This function may be called early before the timer has + * been initialized. In that event, the function should just return a + * start time of zero. + * + * Nothing is assumed about the units of this time value. The following + * are assumed, however: (1) The time is an unsigned integer value, (2) + * the time is monotonically increasing, and (3) the elapsed time (also + * in unknown units) can be obtained by subtracting a start time from + * the current time. + * + * The second interface simple converts an elapsed time into well known + * units. + ********************************************************************************/ + +#ifdef CONFIG_SCHED_CRITMONITOR +uint32_t up_critmon_gettime(void) +{ + uint32_t ret = 0; + + if (g_timer.lower != NULL) + { + ret = current_usec(); + } + + return ret; +} + +void up_critmon_convert(uint32_t elapsed, FAR struct timespec *ts) +{ + timespec_from_usec(ts, elapsed); +} +#endif + /**************************************************************************** * Name: up_mdelay *