Skip to content
Closed
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
5 changes: 3 additions & 2 deletions arch/tricore/src/common/tricore_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ void tricore_earlyserialinit(void);

/* System Timer *************************************************************/

struct oneshot_lowerhalf_s *
tricore_systimer_initialize(volatile void *tbase, int irq, uint64_t freq);
void tricore_systimer_initialize(volatile void *tbase,
int irq,
uint64_t freq);

/* Debug ********************************************************************/

Expand Down
50 changes: 47 additions & 3 deletions arch/tricore/src/common/tricore_systimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <nuttx/kmalloc.h>

#include <nuttx/timers/oneshot.h>
#include <nuttx/hrtimer.h>
#include <nuttx/timers/arch_alarm.h>

#include "tricore_internal.h"
Expand All @@ -47,6 +48,7 @@ struct tricore_systimer_lowerhalf_s
{
struct oneshot_lowerhalf_s lower;
volatile void *tbase;
int irq;
uint64_t freq;
uint64_t alarm;
oneshot_callback_t callback;
Expand Down Expand Up @@ -332,13 +334,21 @@ tricore_systimer_tick_start(struct oneshot_lowerhalf_s *lower,

static int tricore_systimer_interrupt(int irq, void *context, void *arg)
{
#ifdef CONFIG_HRTIMER
(void)irq;
(void)context;
(void)arg;

hrtimer_upper_process(&g_default_hrtimer_upperhalf);
#else
struct tricore_systimer_lowerhalf_s *priv = arg;

tricore_systimer_set_timecmp(priv, UINT64_MAX);
if (priv->callback != NULL)
{
priv->callback(&priv->lower, priv->arg);
}
#endif

return 0;
}
Expand All @@ -356,13 +366,15 @@ static int tricore_systimer_interrupt(int irq, void *context, void *arg)
*
****************************************************************************/

struct oneshot_lowerhalf_s *
tricore_systimer_initialize(volatile void *tbase, int irq, uint64_t freq)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why remove the return oneshot_lowerhalf_s, if so, this timer can only used for system tick, can't for others, like
cpuload in nxsched_oneshot_extclk()

void tricore_systimer_initialize(volatile void *tbase,
int irq,
uint64_t freq)
{
struct tricore_systimer_lowerhalf_s *priv = &g_systimer_lower;

priv->tbase = tbase;
priv->freq = freq;
priv->irq = irq;
spin_lock_init(&priv->lock);

IfxStm_setCompareControl(tbase,
Expand All @@ -376,7 +388,39 @@ tricore_systimer_initialize(volatile void *tbase, int irq, uint64_t freq)
IfxStm_enableComparatorInterrupt(tbase, IfxStm_Comparator_0);

irq_attach(irq, tricore_systimer_interrupt, priv);

up_alarm_set_lowerhalf((struct oneshot_lowerhalf_s *)priv);
Comment thread
xiaoxiang781216 marked this conversation as resolved.

#ifdef CONFIG_HRTIMER
hrtimer_upper_start(&g_default_hrtimer_upperhalf,
HRTIMER_CLOCK_ALARM);
#endif
up_enable_irq(irq);
}

int up_alarm_start(const struct timespec *ts)
{
struct tricore_systimer_lowerhalf_s *priv = &g_systimer_lower;
uint64_t mtime = ts->tv_sec * priv->freq +
ts->tv_nsec * priv->freq / NSEC_PER_SEC;

IfxStm_updateCompare(priv->tbase, IfxStm_Comparator_0, mtime);
up_enable_irq(priv->irq);
}

int up_alarm_gettime(FAR struct timespec *ts)
{
struct tricore_systimer_lowerhalf_s *priv = &g_systimer_lower;
uint64_t mtime = IfxStm_get(priv->tbase);
uint64_t nsecs = mtime * NSEC_PER_SEC / priv->freq;

ts->tv_sec = nsecs / NSEC_PER_SEC;
ts->tv_nsec = nsecs % NSEC_PER_SEC;
}

int up_alarm_trigger(void)
{
struct tricore_systimer_lowerhalf_s *priv = &g_systimer_lower;

return (struct oneshot_lowerhalf_s *)priv;
up_trigger_irq(priv->irq, 0);
}
8 changes: 1 addition & 7 deletions arch/tricore/src/tc3xx/tc3xx_timerisr.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,5 @@

void up_timer_initialize(void)
{
struct oneshot_lowerhalf_s *lower;

lower = tricore_systimer_initialize(&MODULE_STM0, 192, SCU_FREQUENCY);

DEBUGASSERT(lower != NULL);

up_alarm_set_lowerhalf(lower);
tricore_systimer_initialize(&MODULE_STM0, 192, SCU_FREQUENCY);
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ CONFIG_TESTING_GETPRIME=y
CONFIG_TESTING_OSTEST=y
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_SCHED_EVENTS=y
CONFIG_HRTIMER=y
15 changes: 9 additions & 6 deletions drivers/timers/arch_alarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,22 @@ static void oneshot_callback(FAR struct oneshot_lowerhalf_s *lower,

void up_alarm_set_lowerhalf(FAR struct oneshot_lowerhalf_s *lower)
{
#ifdef CONFIG_SCHED_TICKLESS
#ifdef CONFIG_HRTIMER
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HRtimer and wdog, these two should exist in a coexisting relationship rather than an either-or one.

How about provide a framework:
Keep the underlying driver unchanged, reuse a hardware timer, and add the hrtimer processing flow in arch_alarm/arch_timer/wdog

g_oneshot_lower = lower;
#else
# ifdef CONFIG_SCHED_TICKLESS
clock_t ticks = 0;
#endif

# endif
g_oneshot_lower = lower;

#ifdef CONFIG_SCHED_TICKLESS
# ifdef CONFIG_SCHED_TICKLESS
ONESHOT_TICK_MAX_DELAY(g_oneshot_lower, &ticks);
g_oneshot_maxticks = ticks < UINT32_MAX ? ticks : UINT32_MAX;
#else
# else
ONESHOT_TICK_CURRENT(g_oneshot_lower, &g_current_tick);
ONESHOT_TICK_START(g_oneshot_lower, oneshot_callback, NULL, 1);
#endif
# endif
#endif /* CONFIG_HRTIMER */
}

/****************************************************************************
Expand Down
118 changes: 99 additions & 19 deletions include/nuttx/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -1932,6 +1932,88 @@ int up_timer_gettime(FAR struct timespec *ts);
int up_timer_gettick(FAR clock_t *ticks);
void up_timer_getmask(FAR clock_t *mask);

/****************************************************************************
* Name: up_alarm_gettime
*
* Description:
* Return the current time according to the underlying high-resolution
* alarm timer. This is the time base used by the alarm hardware.
*
* Provided by platform-specific code and called from the RTOS base code.
*
* Input Parameters:
* ts - Location to return the current time. Must not be NULL.
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned on
* any failure.
*
* Assumptions:
* May be called from interrupt level handling or from the normal tasking
* level.
*
****************************************************************************/

#if (defined(CONFIG_HRTIMER) && defined(CONFIG_ALARM_ARCH))
int up_alarm_gettime(FAR struct timespec *ts);
int up_alarm_gettick(FAR clock_t *ticks);
#endif

/****************************************************************************
* Name: up_alarm_trigger
*
* Description:
* Force the expiration of the alarm immediately, causing the alarm
* handler nxsched_alarm_expiration() to be invoked as soon as possible.
*
* Provided by platform-specific code and called from the RTOS base code.
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned on
* any failure.
*
* Assumptions:
* May be called from interrupt level handling or from the normal tasking
* level. Interrupts may need to be disabled internally to assure
* non-reentrancy.
*
****************************************************************************/

#if (defined(CONFIG_HRTIMER) && defined(CONFIG_ALARM_ARCH))
int up_alarm_trigger(void);
#endif

/****************************************************************************
* Name: up_timer_trigger
*
* Description:
* Force the expiration of the interval timer immediately, causing the
* system tick or equivalent timer handler to be invoked as soon as
* possible. This is typically used for testing or debugging purposes.
*
* Provided by platform-specific code and called from the RTOS base code.
*
* Input Parameters:
* None
*
* Returned Value:
* Zero (OK) is returned on success. A negated errno value is returned on
* any failure.
*
* Assumptions:
* May be called from interrupt level handling or from the normal tasking
* level. Interrupts may need to be disabled internally to assure
* non-reentrancy.
*
****************************************************************************/

#if (defined(CONFIG_HRTIMER) && defined(CONFIG_TIMER_ARCH))
int up_timer_trigger(void);
#endif

/****************************************************************************
* Name: up_alarm_cancel
*
Expand Down Expand Up @@ -1966,12 +2048,12 @@ void up_timer_getmask(FAR clock_t *mask);
*
****************************************************************************/

#if defined(CONFIG_SCHED_TICKLESS) && defined(CONFIG_SCHED_TICKLESS_ALARM)
# ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
#if (defined(CONFIG_HRTIMER) && defined(CONFIG_ALARM_ARCH)) || \
(defined(CONFIG_SCHED_TICKLESS) && defined(CONFIG_SCHED_TICKLESS_ALARM))
int up_alarm_cancel(FAR struct timespec *ts);
# else
#ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
int up_alarm_tick_cancel(FAR clock_t *ticks);
# endif
# endif
#endif

/****************************************************************************
Expand Down Expand Up @@ -1999,12 +2081,12 @@ int up_alarm_tick_cancel(FAR clock_t *ticks);
*
****************************************************************************/

#if defined(CONFIG_SCHED_TICKLESS) && defined(CONFIG_SCHED_TICKLESS_ALARM)
# ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
#if (defined(CONFIG_HRTIMER) && defined(CONFIG_ALARM_ARCH)) || \
(defined(CONFIG_SCHED_TICKLESS) && defined(CONFIG_SCHED_TICKLESS_ALARM))
int up_alarm_start(FAR const struct timespec *ts);
# else
#ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
int up_alarm_tick_start(clock_t ticks);
# endif
# endif
#endif

/****************************************************************************
Expand Down Expand Up @@ -2043,12 +2125,12 @@ int up_alarm_tick_start(clock_t ticks);
*
****************************************************************************/

#if defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_ALARM)
# ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
#if (defined(CONFIG_HRTIMER) && defined(CONFIG_TIMER_ARCH)) || \
(defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_ALARM))
int up_timer_cancel(FAR struct timespec *ts);
# else
#ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
int up_timer_tick_cancel(FAR clock_t *ticks);
# endif
#endif
#endif

/****************************************************************************
Expand All @@ -2075,15 +2157,13 @@ int up_timer_tick_cancel(FAR clock_t *ticks);
* non-reentrancy.
*
****************************************************************************/

#if defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_ALARM)
# ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
#if (defined(CONFIG_HRTIMER) && defined(CONFIG_TIMER_ARCH)) || \
(defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_ALARM))
int up_timer_start(FAR const struct timespec *ts);
# else
int up_timer_tick_start(clock_t ticks);
# endif
#ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
int up_timer_tick_start(FAR clock_t *ticks);
#endif
#endif

/****************************************************************************
* Name: up_getsp
*
Expand Down
Loading
Loading