From 5fd518a27c0adcf156a1d2de963cd3ac486e07a7 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Sat, 25 Jul 2026 02:50:26 +0200 Subject: [PATCH] rp23xx: Add tickless OS support using the RP2350 hardware TIMER. The port could only run with a periodic ARM SysTick tick. Add an alarm/ oneshot lower-half backed by an RP2350 system timer block so the scheduler can run tickless, waking the CPU only when a timer actually expires. rp23xx_oneshot.c implements the ONESHOT_COUNT lower-half (mirroring the RISC-V mtimer driver). A timer block is a free-running 64-bit microsecond counter (clocked by the TICKS block, independent of the SysTick), which serves directly as the monotonic time base returned by current(), so timekeeping is exact to 1 us. The one adaptation versus a full 64-bit compare timer is that the RP2350 ALARM registers match only the low 32 bits of the counter: max_delay() is therefore capped below 2^32 counts (~71.5 minutes) so the scheduler never asks for a longer interval, and any deadline that is already due -- or that the counter reaches while the alarm is being armed -- is raised immediately through the INTF force register instead of waiting a full 32-bit wrap for the compare to match again. Enabled with CONFIG_RP23XX_SYSTIMER_TICKLESS (mutually exclusive with RP23XX_SYSTIMER_SYSTICK), which selects ONESHOT, ONESHOT_COUNT and ALARM_ARCH; up_timer_initialize() then hands the oneshot to up_alarm_set_lowerhalf(). ARCH_CHIP_RP23XX now selects ARCH_HAVE_TICKLESS. The block is selectable with CONFIG_RP23XX_SYSTIMER_TICKLESS_TIMER0 (default) or _TIMER1; the chosen block is claimed exclusively by the scheduler and is excluded from the /dev/timer driver (CONFIG_RP23XX_TIMER) in Kconfig, so the tickless clock and a /dev/timer device can coexist on different blocks. Tested on Pimoroni Pico Plus 2 (RP2350B) hardware with CONFIG_SCHED_TICKLESS and CONFIG_SCHED_TICKLESS_ALARM: the image boots to nsh and keeps accurate time -- "uptime" advances at real-time rate (17 s over a measured 17.4 s) and "sleep 4" blocks for 4.25 s of wall time -- confirming the oneshot both drives the scheduler and provides a correct 1 MHz monotonic clock. Assisted-by: Claude Opus 4.8 (1M context) Signed-off-by: Marco Casaroli --- Documentation/platforms/arm/rp23xx/index.rst | 23 ++ arch/arm/Kconfig | 1 + arch/arm/src/rp23xx/CMakeLists.txt | 4 + arch/arm/src/rp23xx/Kconfig | 34 ++ arch/arm/src/rp23xx/Make.defs | 4 + arch/arm/src/rp23xx/rp23xx_oneshot.c | 331 +++++++++++++++++++ arch/arm/src/rp23xx/rp23xx_oneshot.h | 71 ++++ arch/arm/src/rp23xx/rp23xx_timerisr.c | 14 +- 8 files changed, 480 insertions(+), 2 deletions(-) create mode 100644 arch/arm/src/rp23xx/rp23xx_oneshot.c create mode 100644 arch/arm/src/rp23xx/rp23xx_oneshot.h diff --git a/Documentation/platforms/arm/rp23xx/index.rst b/Documentation/platforms/arm/rp23xx/index.rst index b8422a9e688..e34b82af760 100644 --- a/Documentation/platforms/arm/rp23xx/index.rst +++ b/Documentation/platforms/arm/rp23xx/index.rst @@ -44,6 +44,7 @@ PSRAM Working Three modes of heap allocation described below TRNG Working Hardware RNG at /dev/random and /dev/urandom Flash MTD Working Unused flash tail as an MTD device, answers BIOC_XIPBASE Timer Working /dev/timerN on TIMER0/TIMER1, 1 us resolution +Tickless Working Optional, RP2350 TIMER via the alarm/oneshot ============== ============ ===== Installation @@ -195,6 +196,28 @@ TIMER1). With tickless disabled, both `/dev/timer0` and `/dev/timer1` are available. The `examples/timer` application can exercise a device; point `CONFIG_EXAMPLES_TIMER_DEVNAME` at the block you enabled. +Tickless OS +=========== + +By default the OS tick is a periodic ARM SysTick interrupt. The RP2350 can +instead run tickless, driving the scheduler from a hardware alarm so the CPU +is only interrupted when a timer actually expires. + +Enable `RP23XX_SYSTIMER_TICKLESS` together with `SCHED_TICKLESS` and +`SCHED_TICKLESS_ALARM`. Choose the timer block with the "Tickless timer +block" option (`RP23XX_SYSTIMER_TICKLESS_TIMER0`, the default, or +`RP23XX_SYSTIMER_TICKLESS_TIMER1`). The system time is then taken from that +block -- a free-running 64-bit microsecond counter -- and its ALARM0 provides +the next-event interrupt through the alarm/oneshot lower-half +(`rp23xx_oneshot.c`). Because the 64-bit counter is the monotonic time base, +timekeeping is exact to 1 us, and a single alarm can schedule up to ~71 +minutes ahead, so long idle periods need no wake-ups. This is mutually +exclusive with `RP23XX_SYSTIMER_SYSTICK`. + +The block chosen here is claimed exclusively by the scheduler and is removed +from the `/dev/timer` driver's choices (see the Timer section), so the tickless +clock and a `/dev/timer` device can run at the same time on different blocks. + Programming ============ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b107f0ab91d..6b2ea0d0886 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -394,6 +394,7 @@ config ARCH_CHIP_RP23XX select ARM_HAVE_DSP select ARCH_HAVE_FPU select ARCH_HAVE_CUSTOM_TESTSET + select ARCH_HAVE_TICKLESS select ARCH_BOARD_COMMON ---help--- Raspberry Pi RP23XX architectures (ARM dual Cortex-M33 or RISC-V). diff --git a/arch/arm/src/rp23xx/CMakeLists.txt b/arch/arm/src/rp23xx/CMakeLists.txt index 5c52dca2aa0..6036cb04ebf 100644 --- a/arch/arm/src/rp23xx/CMakeLists.txt +++ b/arch/arm/src/rp23xx/CMakeLists.txt @@ -60,6 +60,10 @@ if(CONFIG_RP23XX_TIMER) list(APPEND SRCS rp23xx_timer.c) endif() +if(CONFIG_RP23XX_SYSTIMER_TICKLESS) + list(APPEND SRCS rp23xx_oneshot.c) +endif() + if(CONFIG_RP23XX_I2C) list(APPEND SRCS rp23xx_i2c.c) endif() diff --git a/arch/arm/src/rp23xx/Kconfig b/arch/arm/src/rp23xx/Kconfig index e3f2f499a05..cb71ef9f529 100644 --- a/arch/arm/src/rp23xx/Kconfig +++ b/arch/arm/src/rp23xx/Kconfig @@ -23,6 +23,40 @@ config RP23XX_SYSTIMER_SYSTICK ---help--- Use ARM SysTick. +config RP23XX_SYSTIMER_TICKLESS + bool "Tickless OS using the RP2350 hardware TIMER" + default n + depends on !RP23XX_SYSTIMER_SYSTICK + select ONESHOT + select ONESHOT_COUNT + select ALARM_ARCH + ---help--- + Use an RP2350 system timer block (TIMER0 or TIMER1, chosen below) + as the OS time source and drive the scheduler through the + alarm/oneshot interface. Each block is a free-running 64-bit + microsecond counter, independent of the ARM SysTick. This is the + arch-side support required by CONFIG_SCHED_TICKLESS (with + CONFIG_SCHED_TICKLESS_ALARM) and gives long tickless idle intervals + -- up to ~71 minutes per alarm -- with 1 us resolution. + +choice + prompt "Tickless timer block" + default RP23XX_SYSTIMER_TICKLESS_TIMER0 + depends on RP23XX_SYSTIMER_TICKLESS + ---help--- + Which RP2350 system timer block drives the tickless OS clock. The + block used here is claimed exclusively by the scheduler; the other + block stays available for the /dev/timer driver (CONFIG_RP23XX_TIMER), + so both features can be enabled at once. + +config RP23XX_SYSTIMER_TICKLESS_TIMER0 + bool "TIMER0" + +config RP23XX_SYSTIMER_TICKLESS_TIMER1 + bool "TIMER1" + +endchoice + ##################################################################### # UART Configuration ##################################################################### diff --git a/arch/arm/src/rp23xx/Make.defs b/arch/arm/src/rp23xx/Make.defs index fb41bb5c6a8..8f59e6aac6d 100644 --- a/arch/arm/src/rp23xx/Make.defs +++ b/arch/arm/src/rp23xx/Make.defs @@ -64,6 +64,10 @@ ifeq ($(CONFIG_RP23XX_TIMER),y) CHIP_CSRCS += rp23xx_timer.c endif +ifeq ($(CONFIG_RP23XX_SYSTIMER_TICKLESS),y) +CHIP_CSRCS += rp23xx_oneshot.c +endif + ifeq ($(CONFIG_RP23XX_I2C),y) CHIP_CSRCS += rp23xx_i2c.c endif diff --git a/arch/arm/src/rp23xx/rp23xx_oneshot.c b/arch/arm/src/rp23xx/rp23xx_oneshot.c new file mode 100644 index 00000000000..f052cc0dc48 --- /dev/null +++ b/arch/arm/src/rp23xx/rp23xx_oneshot.c @@ -0,0 +1,331 @@ +/**************************************************************************** + * arch/arm/src/rp23xx/rp23xx_oneshot.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + * + * A oneshot lower-half backed by an RP2350 system timer block (TIMER0 or + * TIMER1, selected by CONFIG_RP23XX_SYSTIMER_TICKLESS_TIMERn), used to drive + * the tickless scheduler via up_alarm_set_lowerhalf(). The block is a + * free-running 64-bit counter incremented once per microsecond (the 1 MHz + * tick is set up by the TICKS block in rp23xx_clock.c), and serves directly + * as the monotonic time base returned by current(). The other block is left + * free for the /dev/timer driver. + * + * The one wrinkle versus a full 64-bit compare timer (e.g. the RISC-V mtimer + * this mirrors) is that the RP2350 ALARM registers match only the low 32 + * bits of the counter. max_delay() is therefore capped below 2^32 counts so + * the scheduler never asks for a longer interval, and any deadline that is + * already due (or that the counter reaches while the alarm is being armed) + * is raised at once through the INTF force register rather than waiting a + * full 32-bit wrap (~71.5 minutes) for the compare to match again. + * + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "chip.h" +#include "arm_internal.h" +#include "rp23xx_oneshot.h" +#include "hardware/rp23xx_timer.h" +#include "hardware/rp23xx_memorymap.h" + +#ifdef CONFIG_RP23XX_SYSTIMER_TICKLESS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* This driver uses ALARM0 of TIMER0; alarm 0 is bit 0 in the ARMED, INTE, + * INTF, INTR and INTS registers. + */ + +#define ONESHOT_ALARM0_BIT (1 << 0) + +/* The counter is clocked at 1 MHz (1 us per count). */ + +#define ONESHOT_FREQ_HZ 1000000 + +/* The ALARM compare is only 32 bits wide, so never schedule further ahead + * than this many counts. + */ + +#define ONESHOT_MAX_COUNTS ((clkcnt_t)UINT32_MAX) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Cast-compatible with struct oneshot_lowerhalf_s (embedded first). */ + +struct rp23xx_oneshot_lowerhalf_s +{ + struct oneshot_lowerhalf_s lower; /* Lower-half instance (must be first) */ + uint32_t base; /* TIMER block base address */ + int irq; /* ALARM0 interrupt number */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static clkcnt_t rp23xx_oneshot_max_delay(FAR struct oneshot_lowerhalf_s *l); +static clkcnt_t rp23xx_oneshot_current(FAR struct oneshot_lowerhalf_s *l); +static void rp23xx_oneshot_start_absolute(FAR struct oneshot_lowerhalf_s *l, + clkcnt_t expected); +static void rp23xx_oneshot_start(FAR struct oneshot_lowerhalf_s *l, + clkcnt_t delta); +static void rp23xx_oneshot_cancel(FAR struct oneshot_lowerhalf_s *l); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct oneshot_operations_s g_rp23xx_oneshot_ops = +{ + .current = rp23xx_oneshot_current, + .start = rp23xx_oneshot_start, + .start_absolute = rp23xx_oneshot_start_absolute, + .cancel = rp23xx_oneshot_cancel, + .max_delay = rp23xx_oneshot_max_delay, +}; + +static struct rp23xx_oneshot_lowerhalf_s g_rp23xx_oneshot = +{ + .lower.ops = &g_rp23xx_oneshot_ops, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rp23xx_oneshot_count + * + * Description: + * Read the free-running 64-bit microsecond counter, guarding against a + * carry from the low word into the high word between the two reads. + * + ****************************************************************************/ + +static uint64_t +rp23xx_oneshot_count(FAR struct rp23xx_oneshot_lowerhalf_s *p) +{ + uint32_t hi = getreg32(p->base + RP23XX_TIMER_TIMERAWH_OFFSET); + uint32_t lo; + uint32_t next; + + for (; ; ) + { + lo = getreg32(p->base + RP23XX_TIMER_TIMERAWL_OFFSET); + next = getreg32(p->base + RP23XX_TIMER_TIMERAWH_OFFSET); + if (hi == next) + { + break; + } + + hi = next; + } + + return ((uint64_t)hi << 32) | lo; +} + +/**************************************************************************** + * Name: rp23xx_oneshot_setcompare + * + * Description: + * Arm ALARM0 for the absolute counter value "target". Must be called with + * interrupts disabled. If the target is already due -- or the counter + * reaches it while the alarm is being armed -- the interrupt is forced + * immediately through INTF instead of waiting a full 32-bit wrap for the + * compare to match. + * + ****************************************************************************/ + +static void +rp23xx_oneshot_setcompare(FAR struct rp23xx_oneshot_lowerhalf_s *priv, + uint64_t target) +{ + /* Clear any stale force left from a previous expiry. */ + + modifyreg32(priv->base + RP23XX_TIMER_INTF_OFFSET, ONESHOT_ALARM0_BIT, 0); + + if ((int64_t)(target - rp23xx_oneshot_count(priv)) <= 0) + { + /* Already due: raise the interrupt now. */ + + modifyreg32(priv->base + RP23XX_TIMER_INTF_OFFSET, 0, + ONESHOT_ALARM0_BIT); + } + else + { + /* Writing ALARM0 arms it against the low 32 bits of the counter. */ + + putreg32((uint32_t)target, priv->base + RP23XX_TIMER_ALARM0_OFFSET); + + /* Close the race: if the counter reached the target while we were + * arming, force so we do not wait a full wrap for the match. + */ + + if ((int64_t)(rp23xx_oneshot_count(priv) - target) >= 0) + { + modifyreg32(priv->base + RP23XX_TIMER_INTF_OFFSET, 0, + ONESHOT_ALARM0_BIT); + } + } +} + +/**************************************************************************** + * Name: rp23xx_oneshot_interrupt + ****************************************************************************/ + +static int rp23xx_oneshot_interrupt(int irq, FAR void *context, + FAR void *arg) +{ + FAR struct rp23xx_oneshot_lowerhalf_s *priv = arg; + + /* Disarm the alarm, drop any force and clear the latched match. */ + + putreg32(ONESHOT_ALARM0_BIT, priv->base + RP23XX_TIMER_ARMED_OFFSET); + modifyreg32(priv->base + RP23XX_TIMER_INTF_OFFSET, ONESHOT_ALARM0_BIT, 0); + putreg32(ONESHOT_ALARM0_BIT, priv->base + RP23XX_TIMER_INTR_OFFSET); + + oneshot_process_callback(&priv->lower); + return OK; +} + +/**************************************************************************** + * Name: rp23xx_oneshot_max_delay + ****************************************************************************/ + +static clkcnt_t rp23xx_oneshot_max_delay(FAR struct oneshot_lowerhalf_s *l) +{ + UNUSED(l); + return ONESHOT_MAX_COUNTS; +} + +/**************************************************************************** + * Name: rp23xx_oneshot_current + ****************************************************************************/ + +static clkcnt_t rp23xx_oneshot_current(FAR struct oneshot_lowerhalf_s *l) +{ + return rp23xx_oneshot_count((FAR struct rp23xx_oneshot_lowerhalf_s *)l); +} + +/**************************************************************************** + * Name: rp23xx_oneshot_start_absolute + ****************************************************************************/ + +static void rp23xx_oneshot_start_absolute(FAR struct oneshot_lowerhalf_s *l, + clkcnt_t expected) +{ + FAR struct rp23xx_oneshot_lowerhalf_s *priv = + (FAR struct rp23xx_oneshot_lowerhalf_s *)l; + irqstate_t flags = up_irq_save(); + + rp23xx_oneshot_setcompare(priv, expected); + up_irq_restore(flags); +} + +/**************************************************************************** + * Name: rp23xx_oneshot_start + ****************************************************************************/ + +static void rp23xx_oneshot_start(FAR struct oneshot_lowerhalf_s *l, + clkcnt_t delta) +{ + FAR struct rp23xx_oneshot_lowerhalf_s *priv = + (FAR struct rp23xx_oneshot_lowerhalf_s *)l; + irqstate_t flags = up_irq_save(); + + rp23xx_oneshot_setcompare(priv, rp23xx_oneshot_count(priv) + delta); + up_irq_restore(flags); +} + +/**************************************************************************** + * Name: rp23xx_oneshot_cancel + ****************************************************************************/ + +static void rp23xx_oneshot_cancel(FAR struct oneshot_lowerhalf_s *l) +{ + FAR struct rp23xx_oneshot_lowerhalf_s *priv = + (FAR struct rp23xx_oneshot_lowerhalf_s *)l; + irqstate_t flags = up_irq_save(); + + putreg32(ONESHOT_ALARM0_BIT, priv->base + RP23XX_TIMER_ARMED_OFFSET); + modifyreg32(priv->base + RP23XX_TIMER_INTF_OFFSET, ONESHOT_ALARM0_BIT, 0); + putreg32(ONESHOT_ALARM0_BIT, priv->base + RP23XX_TIMER_INTR_OFFSET); + up_irq_restore(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rp23xx_oneshot_initialize + * + * Description: + * Initialise the selected system timer block (TIMER0 or TIMER1) as a + * oneshot lower-half. See rp23xx_oneshot.h. + * + ****************************************************************************/ + +FAR struct oneshot_lowerhalf_s *rp23xx_oneshot_initialize(void) +{ + FAR struct rp23xx_oneshot_lowerhalf_s *priv = &g_rp23xx_oneshot; + +#ifdef CONFIG_RP23XX_SYSTIMER_TICKLESS_TIMER1 + priv->base = RP23XX_TIMER1_BASE; + priv->irq = RP23XX_TIMER1_IRQ_0; +#else + priv->base = RP23XX_TIMER0_BASE; + priv->irq = RP23XX_TIMER0_IRQ_0; +#endif + + oneshot_count_init(&priv->lower, ONESHOT_FREQ_HZ); + + /* Start from a known-idle state: alarm disarmed, no force, status clear, + * then enable the ALARM0 interrupt at the peripheral and the NVIC. + */ + + putreg32(ONESHOT_ALARM0_BIT, priv->base + RP23XX_TIMER_ARMED_OFFSET); + modifyreg32(priv->base + RP23XX_TIMER_INTF_OFFSET, ONESHOT_ALARM0_BIT, 0); + putreg32(ONESHOT_ALARM0_BIT, priv->base + RP23XX_TIMER_INTR_OFFSET); + modifyreg32(priv->base + RP23XX_TIMER_INTE_OFFSET, 0, ONESHOT_ALARM0_BIT); + + irq_attach(priv->irq, rp23xx_oneshot_interrupt, priv); + up_enable_irq(priv->irq); + + return &priv->lower; +} + +#endif /* CONFIG_RP23XX_SYSTIMER_TICKLESS */ diff --git a/arch/arm/src/rp23xx/rp23xx_oneshot.h b/arch/arm/src/rp23xx/rp23xx_oneshot.h new file mode 100644 index 00000000000..eec8184a79c --- /dev/null +++ b/arch/arm/src/rp23xx/rp23xx_oneshot.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/arm/src/rp23xx/rp23xx_oneshot.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RP23XX_RP23XX_ONESHOT_H +#define __ARCH_ARM_SRC_RP23XX_RP23XX_ONESHOT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: rp23xx_oneshot_initialize + * + * Description: + * Initialise the RP2350 system timer TIMER0 as a oneshot lower-half and + * return it, ready to be handed to up_alarm_set_lowerhalf() to drive the + * tickless scheduler. TIMER0 is a free-running 64-bit microsecond counter + * whose ALARM0 provides the compare event. + * + * Returned Value: + * The oneshot lower-half instance on success; NULL never happens (the + * instance is statically allocated). + * + ****************************************************************************/ + +FAR struct oneshot_lowerhalf_s *rp23xx_oneshot_initialize(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_RP23XX_RP23XX_ONESHOT_H */ diff --git a/arch/arm/src/rp23xx/rp23xx_timerisr.c b/arch/arm/src/rp23xx/rp23xx_timerisr.c index f0ef2171cae..f49778e5252 100644 --- a/arch/arm/src/rp23xx/rp23xx_timerisr.c +++ b/arch/arm/src/rp23xx/rp23xx_timerisr.c @@ -40,6 +40,11 @@ #include "chip.h" #include "systick.h" +#ifdef CONFIG_RP23XX_SYSTIMER_TICKLESS +# include +# include "rp23xx_oneshot.h" +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -76,7 +81,8 @@ * of the systems. * ****************************************************************************/ -#ifndef CONFIG_RP23XX_SYSTIMER_SYSTICK +#if !defined(CONFIG_RP23XX_SYSTIMER_SYSTICK) && \ + !defined(CONFIG_RP23XX_SYSTIMER_TICKLESS) static int rp23xx_timerisr(int irq, uint32_t *regs, void *arg) { /* Process timer interrupt */ @@ -110,7 +116,11 @@ void up_timer_initialize(void) regval |= (NVIC_SYSH_PRIORITY_DEFAULT << NVIC_SYSH_PRIORITY_PR15_SHIFT); putreg32(regval, NVIC_SYSH12_15_PRIORITY); -#ifdef CONFIG_RP23XX_SYSTIMER_SYSTICK +#if defined(CONFIG_RP23XX_SYSTIMER_TICKLESS) + /* Drive the tickless scheduler from the selected RP2350 hardware TIMER. */ + + up_alarm_set_lowerhalf(rp23xx_oneshot_initialize()); +#elif defined(CONFIG_RP23XX_SYSTIMER_SYSTICK) up_timer_set_lowerhalf(systick_initialize(true, SYSTICK_CLOCK, -1)); #else