drivers/timers/arch_alarm.c and arch_timer.c: Implement up_critmon_gettime and up_critmon_convert and remove the critical section from current_usec to infinite recursion.

This commit is contained in:
Xiang Xiao 2019-01-27 10:15:51 -06:00 committed by Gregory Nutt
parent e57f7cf6ae
commit 15db8a21ae
2 changed files with 94 additions and 11 deletions

View File

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

View File

@ -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);
do
{
timebase = g_timer.timebase;
leave_critical_section(flags);
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
*