diff --git a/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst b/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst index c99764350e17d..703f73f9a8b2e 100644 --- a/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst +++ b/Documentation/platforms/arm/rtl8720f/boards/rtl8720f_evb/index.rst @@ -47,6 +47,8 @@ Supported in this NuttX port: alarm support, driven directly on the SDK fwlib register layer * On-chip watchdog exposed as a ``/dev/watchdog0`` character device, driven directly on the SDK fwlib register layer +* General-purpose timers exposed as ``/dev/timer0`` and ``/dev/timer1`` + character devices, driven directly on the SDK fwlib register layer Buttons and LEDs ================ @@ -190,6 +192,20 @@ which opens the device, sets a timeout, and pings it:: nsh> wdog # run the watchdog example +timer +----- + +Minimal NSH with the on-chip general-purpose timer driver and the ``timer`` +example enabled (no Wi-Fi). Two 32-bit basic timers clocked at 32.768 kHz are +registered from the board bring-up +(``boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_timer.c``) as ``/dev/timer0`` +(TIM1) and ``/dev/timer1`` (TIM2); they have no board wiring (they are +internal). TIM0 is reserved by the boot ROM as the system timer and is not +exposed. Exercise a device with the example, which sets an interval and counts +the update interrupts:: + + nsh> timer -d /dev/timer0 # run the timer example on TIM1 + nsh --- diff --git a/Documentation/platforms/arm/rtl8721dx/boards/pke8721daf/index.rst b/Documentation/platforms/arm/rtl8721dx/boards/pke8721daf/index.rst index 0e66109df8a1a..0565b1d172563 100644 --- a/Documentation/platforms/arm/rtl8721dx/boards/pke8721daf/index.rst +++ b/Documentation/platforms/arm/rtl8721dx/boards/pke8721daf/index.rst @@ -49,6 +49,8 @@ Supported in this NuttX port: alarm support, driven directly on the SDK fwlib register layer * On-chip watchdog exposed as a ``/dev/watchdog0`` character device, driven directly on the SDK fwlib register layer +* General-purpose timers exposed as ``/dev/timer0`` and ``/dev/timer1`` + character devices, driven directly on the SDK fwlib register layer Buttons and LEDs ================ @@ -199,6 +201,20 @@ which opens the device, sets a timeout, and pings it:: nsh> wdog # run the watchdog example +timer +----- + +Minimal NSH with the on-chip general-purpose timer driver and the ``timer`` +example enabled (no Wi-Fi). Two 32-bit basic timers clocked at 32.768 kHz are +registered from the board bring-up +(``boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_timer.c``) as ``/dev/timer0`` +(TIM1) and ``/dev/timer1`` (TIM2); they have no board wiring (they are +internal). TIM0 is reserved by the boot ROM as the system timer and is not +exposed. Exercise a device with the example, which sets an interval and counts +the update interrupts:: + + nsh> timer -d /dev/timer0 # run the timer example on TIM1 + Wi-Fi ===== diff --git a/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst b/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst index d56b85fa6a6d2..cfbc28429b2d2 100644 --- a/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst +++ b/Documentation/platforms/arm/rtl8721f/boards/rtl8721f_evb/index.rst @@ -48,6 +48,8 @@ Supported in this NuttX port: alarm support, driven directly on the SDK fwlib register layer * On-chip watchdog exposed as a ``/dev/watchdog0`` character device, driven directly on the SDK fwlib register layer +* General-purpose timers exposed as ``/dev/timer0`` and ``/dev/timer1`` + character devices, driven directly on the SDK fwlib register layer Buttons and LEDs ================ @@ -193,6 +195,20 @@ which opens the device, sets a timeout, and pings it:: nsh> wdog # run the watchdog example +timer +----- + +Minimal NSH with the on-chip general-purpose timer driver and the ``timer`` +example enabled (no Wi-Fi). Two 32-bit basic timers clocked at 32.768 kHz are +registered from the board bring-up +(``boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_timer.c``) as ``/dev/timer0`` +(TIM1) and ``/dev/timer1`` (TIM2); they have no board wiring (they are +internal). TIM0 is reserved by the boot ROM as the system timer and is not +exposed. Exercise a device with the example, which sets an interval and counts +the update interrupts:: + + nsh> timer -d /dev/timer0 # run the timer example on TIM1 + nsh --- diff --git a/arch/arm/src/common/ameba/Kconfig b/arch/arm/src/common/ameba/Kconfig index ea74d1435d06e..d34a65e2b6d13 100644 --- a/arch/arm/src/common/ameba/Kconfig +++ b/arch/arm/src/common/ameba/Kconfig @@ -149,4 +149,21 @@ config AMEBA_WDG enabled, so stop() arms the WDG early interrupt and refreshes the counter from its handler to inhibit the reset. +config AMEBA_TIMER + bool "Timer" + default n + select TIMER + ---help--- + Expose the Ameba general-purpose timers as NuttX timer devices at + /dev/timerN (start/stop/settimeout/getstatus, plus a periodic + expiration callback). The timeout is programmed directly in + microseconds. + + The driver (arch/arm/src/common/ameba/ameba_timer.c) is a + parameterised lower half sitting on the SDK fwlib RTIM register + layer; the board picks which of the twelve on-chip timers to expose + via the per-chip instance table. On the pke8721daf /dev/timer0 is + TIM1 and /dev/timer1 is TIM2, both 32.768 kHz basic timers. TIM0 + is reserved by the ROM as the system timer and is not exposed. + endmenu # Ameba Peripheral Support diff --git a/arch/arm/src/common/ameba/ameba_timer.c b/arch/arm/src/common/ameba/ameba_timer.c new file mode 100644 index 0000000000000..a90c2f121ea60 --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_timer.c @@ -0,0 +1,546 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_timer.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 + ****************************************************************************/ + +/* NuttX timer lower half for the Realtek Ameba general-purpose timers. The + * chip carries twelve identical 32-bit up-counting timers (TIM0..TIM11); + * this driver is a parameterised lower half that binds any of them, by + * an instance index into the per-chip AMEBA_TIMER_CONFIG_TABLE. The board + * calls ameba_timer_initialize() once per device, so several timers can be + * exposed at once -- on the pke8721daf /dev/timer0 is TIM1 (32.768 kHz, long + * low-power intervals) and /dev/timer1 is TIM2 (also 32.768 kHz). TIM0 is + * reserved by the ROM as the system timer (SYSTIMER, 31 us/tick) and is + * never exposed as a general-purpose timer here. + * + * Each timer counts up from 0 to its auto-reload value ARR, raises the + * update interrupt on overflow and reloads to 0 automatically, so a running + * timer is inherently periodic. A timeout in microseconds maps to ARR with + * the single SDK formula ARR = us * clkfreq / 1e6 - 1 (verified against the + * vendor timer_api.c gtimer_reload for the 32.768 kHz basic timers); the + * arithmetic is done in 64 bits so a large microsecond timeout scaled by the + * clock does not overflow. + * + * The timer is driven through the SDK fwlib RTIM API. The time-base setup + * (RTIM_TimeBaseStructInit/RTIM_TimeBaseInit/RTIM_Cmd/RTIM_INTConfig/ + * RTIM_GetCount) resolves to the on-chip ROM symbol table (_LONG_CALL_ + * entries), while the interrupt-clear and hot period-change helpers + * (RTIM_INTClear/RTIM_ChangePeriodImmediate) come from the fwlib RAM source + * ameba_tim.c and linked in. The NuttX interrupt is attached with the + * standard irq_attach()/up_enable_irq() (RTIM_TimeBaseInit is passed a NULL + * user callback so the vendor HAL installs nothing of its own), matching the + * other Ameba drivers on this core. + * + * The chip-specific wiring (per-instance register base, input clock, RCC + * clock masks and IRQ number) lives entirely in the per-chip + * ameba_timer_chip.h instance table; the shared driver reads only that table + * and is never edited per chip. As in the PWM driver the one fwlib init + * struct layout used here is mirrored locally rather than pulling in the + * vendor . + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ameba_timer.h" +#include "ameba_timer_chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Second/third argument to fwlib "state" style APIs. */ + +#define AMEBA_DISABLE 0x0 +#define AMEBA_ENABLE 0x1 + +/* fwlib time-base field values (from ameba_pwmtimer.h). */ + +#define AMEBA_TIM_IT_UPDATE 0x00000001 /* TIM_IT_Update */ +#define AMEBA_TIM_UPDATESRC_OVER 0x00000004 /* TIM_UpdateSource_Overflow */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* One row of the per-chip AMEBA_TIMER_CONFIG_TABLE. */ + +struct ameba_timer_config_s +{ + uintptr_t base; /* Non-secure timer register base */ + uint32_t periph; /* RCC periph function mask (arg 1) */ + uint32_t clk; /* RCC periph clock mask (arg 2) */ + uint32_t clkfreq; /* Timer input clock (Hz) */ + int irq; /* NuttX IRQ number */ + uint8_t idx; /* Timer index (TIM_Idx) */ +}; + +/* Layout-compatible mirror of the fwlib RTIM_TimeBaseInitTypeDef (same field + * order and types); passed by address to RTIM_TimeBaseStructInit()/ + * RTIM_TimeBaseInit(). + */ + +struct ameba_tim_timebase_s +{ + uint32_t prescaler; /* TIM_Prescaler */ + uint32_t period; /* TIM_Period */ + uint32_t updateevent; /* TIM_UpdateEvent */ + uint32_t updatesource; /* TIM_UpdateSource */ + uint32_t arrprotection; /* TIM_ARRProtection */ + uint8_t idx; /* TIM_Idx */ + uint32_t securetimer; /* TIM_SecureTimer */ +}; + +struct ameba_timer_lowerhalf_s +{ + const struct timer_ops_s *ops; /* Lower half operations (must be first) */ + struct ameba_timer_config_s cfg; + tccb_t callback; /* Upper-half expiration callback */ + void *arg; /* Argument for the callback */ + uint32_t timeout; /* Programmed timeout (microseconds) */ + uint32_t arr; /* Auto-reload value for that timeout */ + bool started; /* Time base is running */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* SDK fwlib RTIM/clock API (ROM for the time base, RAM ameba_tim.c for the + * interrupt-clear and period-change helpers). The RTIM_TypeDef pointer is + * passed as the raw register base cast to void *. + */ + +extern void RCC_PeriphClockCmd(uint32_t periph, uint32_t clock, + uint8_t newstate); +extern void RTIM_TimeBaseStructInit(struct ameba_tim_timebase_s *init); +extern void RTIM_TimeBaseInit(void *timx, + struct ameba_tim_timebase_s *init, + int irqnum, void *usercb, uint32_t cbdata); +extern void RTIM_Cmd(void *timx, uint32_t newstate); +extern void RTIM_INTConfig(void *timx, uint32_t tim_it, uint32_t newstate); +extern void RTIM_INTClear(void *timx); +extern void RTIM_ChangePeriodImmediate(void *timx, uint32_t autoreload); +extern uint32_t RTIM_GetCount(void *timx); + +/* Timer lower-half operations. */ + +static int ameba_timer_start(struct timer_lowerhalf_s *lower); +static int ameba_timer_stop(struct timer_lowerhalf_s *lower); +static int ameba_timer_getstatus(struct timer_lowerhalf_s *lower, + struct timer_status_s *status); +static int ameba_timer_settimeout(struct timer_lowerhalf_s *lower, + uint32_t timeout); +static void ameba_timer_setcallback(struct timer_lowerhalf_s *lower, + tccb_t callback, void *arg); +static int ameba_timer_maxtimeout(struct timer_lowerhalf_s *lower, + uint32_t *maxtimeout); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct timer_ops_s g_ameba_timer_ops = +{ + .start = ameba_timer_start, + .stop = ameba_timer_stop, + .getstatus = ameba_timer_getstatus, + .settimeout = ameba_timer_settimeout, + .setcallback = ameba_timer_setcallback, + .maxtimeout = ameba_timer_maxtimeout, +}; + +/* Per-chip instance table: { base, periph, clk, clkfreq, irq, idx }. */ + +static const struct ameba_timer_config_s + g_ameba_timer_config[AMEBA_TIMER_NINSTANCES] = AMEBA_TIMER_CONFIG_TABLE; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_timer_us2arr + * + * Description: + * Convert a timeout in microseconds to the timer's auto-reload value using + * the SDK formula ARR = us * clkfreq / 1e6 - 1, in 64-bit arithmetic so a + * large microsecond timeout scaled by the clock does not overflow. + * + ****************************************************************************/ + +static uint32_t ameba_timer_us2arr(uint32_t clkfreq, uint32_t us) +{ + uint64_t ticks = ((uint64_t)us * clkfreq) / 1000000ull; + + if (ticks == 0) + { + ticks = 1; + } + + return (uint32_t)(ticks - 1); +} + +/**************************************************************************** + * Name: ameba_timer_interrupt + * + * Description: + * Update-event ISR. Clears the flag, invokes the upper-half callback and + * honours its verdict: a false return stops the timer, a true return keeps + * it periodic and may hot-change the period to the callback's next + * interval (deferred by the ARR protection to the reload just started). + * + ****************************************************************************/ + +/* Dummy handler passed to RTIM_TimeBaseInit so the ROM performs its full + * timer configuration (some register setup is skipped when UserCB is NULL). + * NuttX installs its own vector table, so this is never actually invoked. + */ + +static uint32_t ameba_timer_dummy_cb(void *data) +{ + UNUSED(data); + return 0; +} + +static int ameba_timer_interrupt(int irq, void *context, void *arg) +{ + struct ameba_timer_lowerhalf_s *priv = arg; + + /* Clear the pending update flag via the ROM helper (it polls the timer + * clock domain to guarantee the write took effect). + */ + + RTIM_INTClear((void *)priv->cfg.base); + + if (priv->callback != NULL) + { + uint32_t next = priv->timeout; + + if (priv->callback(&next, priv->arg)) + { + if (next != priv->timeout && next > 0) + { + /* The callback asked for a different next interval. */ + + priv->timeout = next; + priv->arr = ameba_timer_us2arr(priv->cfg.clkfreq, next); + RTIM_ChangePeriodImmediate((void *)priv->cfg.base, priv->arr); + } + } + else + { + /* The callback asked to stop after this expiration. */ + + RTIM_INTConfig((void *)priv->cfg.base, AMEBA_TIM_IT_UPDATE, + AMEBA_DISABLE); + RTIM_Cmd((void *)priv->cfg.base, AMEBA_DISABLE); + priv->started = false; + } + } + + /* Clear once more (vendor double-clear guard). */ + + RTIM_INTClear((void *)priv->cfg.base); + + return OK; +} + +/**************************************************************************** + * Name: ameba_timer_start + ****************************************************************************/ + +static int ameba_timer_start(struct timer_lowerhalf_s *lower) +{ + struct ameba_timer_lowerhalf_s *priv = + (struct ameba_timer_lowerhalf_s *)lower; + struct ameba_tim_timebase_s tb; + + if (priv->started) + { + return -EPERM; + } + + if (priv->arr == 0 && priv->timeout == 0) + { + /* No timeout has been programmed yet. */ + + return -EINVAL; + } + + memset(&tb, 0, sizeof(tb)); + RTIM_TimeBaseStructInit(&tb); + + /* Match the vendor gtimer_init exactly: TIM_Period is NOT supplied here. + * TimeBaseInit with ARR preload enabled would leave the auto-reload shadow + * at its reset value (0) until the first overflow, so arming the interrupt + * immediately floods the CPU. The period is instead programmed by the + * RTIM_ChangePeriodImmediate() below, which clears ARPE, writes ARR and + * issues a UG so the shadow is loaded before the timer runs. + */ + + tb.idx = priv->cfg.idx; + tb.updateevent = AMEBA_ENABLE; + tb.updatesource = AMEBA_TIM_UPDATESRC_OVER; + tb.arrprotection = AMEBA_ENABLE; + + /* NULL user callback: the NuttX ISR is attached separately, so the vendor + * HAL installs no handler of its own. + */ + + RTIM_TimeBaseInit((void *)priv->cfg.base, &tb, priv->cfg.irq, + (void *)ameba_timer_dummy_cb, 0); + + /* Program the period and force an immediate shadow reload (vendor + * gtimer_reload). The overflow reload is periodic on this IP whatever the + * ARR-preload bit is, so no further CR fix-up is needed here. + */ + + RTIM_ChangePeriodImmediate((void *)priv->cfg.base, priv->arr); + + /* Only fire the update interrupt when an upper-half callback wants it; a + * bare timer just free-runs and reloads for getstatus() polling (vendor + * gtimer_start: INTConfig then Cmd). + */ + + RTIM_INTConfig((void *)priv->cfg.base, AMEBA_TIM_IT_UPDATE, + priv->callback != NULL ? AMEBA_ENABLE : AMEBA_DISABLE); + + RTIM_Cmd((void *)priv->cfg.base, AMEBA_ENABLE); + + priv->started = true; + return OK; +} + +/**************************************************************************** + * Name: ameba_timer_stop + ****************************************************************************/ + +static int ameba_timer_stop(struct timer_lowerhalf_s *lower) +{ + struct ameba_timer_lowerhalf_s *priv = + (struct ameba_timer_lowerhalf_s *)lower; + + if (!priv->started) + { + return -EPERM; + } + + RTIM_INTConfig((void *)priv->cfg.base, AMEBA_TIM_IT_UPDATE, AMEBA_DISABLE); + RTIM_Cmd((void *)priv->cfg.base, AMEBA_DISABLE); + priv->started = false; + return OK; +} + +/**************************************************************************** + * Name: ameba_timer_getstatus + ****************************************************************************/ + +static int ameba_timer_getstatus(struct timer_lowerhalf_s *lower, + struct timer_status_s *status) +{ + struct ameba_timer_lowerhalf_s *priv = + (struct ameba_timer_lowerhalf_s *)lower; + uint32_t count; + uint32_t remaining; + + status->flags = 0; + if (priv->started) + { + status->flags |= TCFLAGS_ACTIVE; + } + + if (priv->callback != NULL) + { + status->flags |= TCFLAGS_HANDLER; + } + + status->timeout = priv->timeout; + + /* Time left = (ARR + 1 - current up-count) converted back to microseconds + * in 64-bit arithmetic; a stopped timer has the full timeout left. + */ + + if (priv->started) + { + count = RTIM_GetCount((void *)priv->cfg.base); + remaining = (count > priv->arr) ? 0 : (priv->arr + 1 - count); + status->timeleft = + (uint32_t)(((uint64_t)remaining * 1000000ull) / priv->cfg.clkfreq); + } + else + { + status->timeleft = priv->timeout; + } + + return OK; +} + +/**************************************************************************** + * Name: ameba_timer_settimeout + ****************************************************************************/ + +static int ameba_timer_settimeout(struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + struct ameba_timer_lowerhalf_s *priv = + (struct ameba_timer_lowerhalf_s *)lower; + + if (timeout == 0) + { + return -EINVAL; + } + + priv->timeout = timeout; + priv->arr = ameba_timer_us2arr(priv->cfg.clkfreq, timeout); + + /* Hot-update a running time base; the auto-reload protection defers the + * change to the next update event so the count does not glitch. + */ + + if (priv->started) + { + RTIM_ChangePeriodImmediate((void *)priv->cfg.base, priv->arr); + } + + return OK; +} + +/**************************************************************************** + * Name: ameba_timer_setcallback + ****************************************************************************/ + +static void ameba_timer_setcallback(struct timer_lowerhalf_s *lower, + tccb_t callback, void *arg) +{ + struct ameba_timer_lowerhalf_s *priv = + (struct ameba_timer_lowerhalf_s *)lower; + irqstate_t flags; + + flags = enter_critical_section(); + + priv->callback = callback; + priv->arg = arg; + + /* Track the interrupt enable to the callback while the timer runs, so a + * callback set or cleared after start() takes effect immediately. + */ + + if (priv->started) + { + RTIM_INTConfig((void *)priv->cfg.base, AMEBA_TIM_IT_UPDATE, + callback != NULL ? AMEBA_ENABLE : AMEBA_DISABLE); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: ameba_timer_maxtimeout + ****************************************************************************/ + +static int ameba_timer_maxtimeout(struct timer_lowerhalf_s *lower, + uint32_t *maxtimeout) +{ + struct ameba_timer_lowerhalf_s *priv = + (struct ameba_timer_lowerhalf_s *)lower; + uint64_t maxus; + + /* Largest microsecond value whose ARR still fits the 32-bit counter: + * us = (ARR_max + 1) * 1e6 / clkfreq, capped to the uint32_t API range. + */ + + maxus = ((uint64_t)0xffffffffull * 1000000ull) / priv->cfg.clkfreq; + if (maxus > 0xffffffffull) + { + maxus = 0xffffffffull; + } + + *maxtimeout = (uint32_t)maxus; + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ameba_timer_initialize + * + * Description: + * See ameba_timer.h. + * + ****************************************************************************/ + +int ameba_timer_initialize(const char *devpath, int instance) +{ + struct ameba_timer_lowerhalf_s *priv; + void *handle; + + if (instance < 0 || instance >= AMEBA_TIMER_NINSTANCES) + { + return -EINVAL; + } + + priv = kmm_zalloc(sizeof(struct ameba_timer_lowerhalf_s)); + if (priv == NULL) + { + return -ENOMEM; + } + + priv->ops = &g_ameba_timer_ops; + priv->cfg = g_ameba_timer_config[instance]; + + /* Gate the timer's peripheral clock (function and clock masks are equal on + * this chip) and wire the NuttX interrupt. The time base itself is left + * stopped until start(); settimeout() supplies the period first. + */ + + RCC_PeriphClockCmd(priv->cfg.periph, priv->cfg.clk, AMEBA_ENABLE); + + irq_attach(priv->cfg.irq, ameba_timer_interrupt, priv); + up_enable_irq(priv->cfg.irq); + + handle = timer_register(devpath, (struct timer_lowerhalf_s *)priv); + if (handle == NULL) + { + up_disable_irq(priv->cfg.irq); + irq_detach(priv->cfg.irq); + _err("ERROR: timer_register(%s) failed\n", devpath); + kmm_free(priv); + return -EEXIST; + } + + return OK; +} diff --git a/arch/arm/src/common/ameba/ameba_timer.h b/arch/arm/src/common/ameba/ameba_timer.h new file mode 100644 index 0000000000000..bec1e5294830a --- /dev/null +++ b/arch/arm/src/common/ameba/ameba_timer.h @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/arm/src/common/ameba/ameba_timer.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_COMMON_AMEBA_AMEBA_TIMER_H +#define __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: ameba_timer_initialize + * + * Description: + * Bind one Ameba general-purpose timer instance to the NuttX timer + * character driver and register it at the given path (typically + * "/dev/timerN"). The instance index selects a row of the per-chip + * AMEBA_TIMER_CONFIG_TABLE (0 == TIM1, 1 == TIM2, both @ 32.768 kHz on the + * pke8721daf); its base, clock, RCC masks and IRQ come from that table, so + * a board only names the device and the instance it wants. + * + * Input Parameters: + * devpath - The device path to register, e.g. "/dev/timer0". + * instance - Index into the per-chip timer instance table + * (0 .. AMEBA_TIMER_NINSTANCES - 1). + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int ameba_timer_initialize(const char *devpath, int instance); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_ARM_SRC_COMMON_AMEBA_AMEBA_TIMER_H */ diff --git a/arch/arm/src/rtl8720f/CMakeLists.txt b/arch/arm/src/rtl8720f/CMakeLists.txt index a251710730365..ecd2e5dba0f2d 100644 --- a/arch/arm/src/rtl8720f/CMakeLists.txt +++ b/arch/arm/src/rtl8720f/CMakeLists.txt @@ -78,6 +78,10 @@ if(CONFIG_AMEBA_WDG) list(APPEND SRCS ${AMEBA_COMMON}/ameba_wdg.c) endif() +if(CONFIG_AMEBA_TIMER) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_timer.c) +endif() + target_include_directories(arch PRIVATE ${AMEBA_COMMON}) target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/rtl8720f/Make.defs b/arch/arm/src/rtl8720f/Make.defs index 42ac8697a1eb7..0416d99990379 100644 --- a/arch/arm/src/rtl8720f/Make.defs +++ b/arch/arm/src/rtl8720f/Make.defs @@ -88,6 +88,10 @@ ifeq ($(CONFIG_AMEBA_WDG),y) CHIP_CSRCS += ameba_wdg.c endif +ifeq ($(CONFIG_AMEBA_TIMER),y) +CHIP_CSRCS += ameba_timer.c +endif + ############################################################################ # Realtek RTL8720F SDK integration # diff --git a/arch/arm/src/rtl8720f/ameba_board.mk b/arch/arm/src/rtl8720f/ameba_board.mk index 77ec3645d817b..f1b7b9b8660c0 100644 --- a/arch/arm/src/rtl8720f/ameba_board.mk +++ b/arch/arm/src/rtl8720f/ameba_board.mk @@ -144,12 +144,13 @@ ifeq ($(CONFIG_AMEBA_SPI),y) AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_spi.c endif -# PWM timer register layer. The time-base entry points (RTIM_TimeBaseInit/ -# StructInit/Cmd) are in ROM, but the compare/period helpers the PWM driver -# (arch/.../common/ameba/ameba_pwm.c) calls -- RTIM_CCStructInit/CCxInit/ -# CCRxSet/CCxCmd/ChangePeriod/PrescalerConfig -- are compiled from this RAM +# PWM/timer register layer. The time-base entry points (RTIM_TimeBaseInit/ +# StructInit/Cmd/INTConfig/GetCount) are in ROM, but the compare/period and +# interrupt-clear helpers the PWM driver (ameba_pwm.c: RTIM_CCStructInit/ +# CCxInit/CCRxSet/CCxCmd/ChangePeriod/PrescalerConfig) and the timer driver +# (ameba_timer.c: RTIM_INTClear/ChangePeriod) call are compiled from this RAM # source and linked in (--gc-sections drops the unused input-capture paths). -ifeq ($(CONFIG_AMEBA_PWM),y) +ifneq (,$(filter y,$(CONFIG_AMEBA_PWM) $(CONFIG_AMEBA_TIMER))) AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_tim.c endif diff --git a/arch/arm/src/rtl8720f/ameba_timer_chip.h b/arch/arm/src/rtl8720f/ameba_timer_chip.h new file mode 100644 index 0000000000000..3b27cb0253828 --- /dev/null +++ b/arch/arm/src/rtl8720f/ameba_timer_chip.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * arch/arm/src/rtl8720f/ameba_timer_chip.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_RTL8720F_AMEBA_TIMER_CHIP_H +#define __ARCH_ARM_SRC_RTL8720F_AMEBA_TIMER_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Per-chip general-purpose timer wiring for RTL8720F. The shared driver + * (arch/arm/src/common/ameba/ameba_timer.c) includes this header to learn + * which timer instances it may expose and, for each one, its register base, + * input clock, RCC clock masks and interrupt line. A port to another Ameba + * chip supplies a same-named header on the chip include path; the shared + * driver is never edited -- it reads only the macros below and the instance + * table, computing the period from clkfreq with one formula. + * + * The Ameba SoC carries a bank of timers that all share the one RTIM + * register layout and fwlib API, so the register access, the + * microsecond<->tick conversion and the whole lower-half live in the shared + * driver. What differs per instance -- and per chip -- is only data: the + * base address, the clock that feeds it, its RCC gate masks and its NuttX + * IRQ number. These sit in AMEBA_TIMER_CONFIG_TABLE so a new chip (or + * a different instance choice) edits this header alone. + * + * This port exposes two of the 32-bit "basic" (LTIM) timers so a single + * lower-half serves them uniformly (verified against the SoC hal_platform.h + * / sysreg_lsys.h / vector table, not guessed): + * + * instance timer base clock RCC gate NuttX IRQ + * -------- ------ ---------- --------- -------------- ---------- + * 0 TIM1 0x40808200 32.768 kHz APBPeriph_LTIM1 IRQ_TIMER1 + * 1 TIM2 0x40808400 32.768 kHz APBPeriph_LTIM2 IRQ_TIMER2 + * + * TIM1 and TIM2 are two of the four "basic" (LTIM) timers clocked from the + * 32.768 kHz LS clock: ~30.5 us per tick, up to ~36 h in one shot. A full + * 32-bit auto-reload lets them cover the whole microsecond API range, which + * is why the driver exposes this bank rather than the "high" (HTIM) timers, + * whose 16-bit auto-reload suits sub-millisecond fine timing only. The + * non-secure base alias (0x40xxxxxx) is used, matching the core this port + * runs on. + * + * TIM0 is deliberately NOT exposed: the boot ROM claims it as the always-on + * system timer (see the vendor ameba_delay.h), and DelayUs/DelayMs and the + * SYSTIMER_* helpers all rely on it. Reprogramming TIM0 would break every + * SDK delay, so the + * driver starts the basic bank at TIM1. + * + * The RCC gate masks are the fwlib APBPeriph_LTIM1 / APBPeriph_LTIM2 values + * (function and clock masks are identical on this chip). They are written + * out here rather than pulled from to keep the vendor + * headers out of the NuttX include world (same rule as the PWM chip header). + */ + +/* RCC "function" and "clock" masks, bit30 group selector then bit index. */ + +#define AMEBA_TIMER_LTIM1_MASK (((uint32_t)1 << 30) | ((uint32_t)1 << 13)) +#define AMEBA_TIMER_LTIM2_MASK (((uint32_t)1 << 30) | ((uint32_t)1 << 14)) + +/* Number of timer instances this chip exposes and the data table that + * describes each one. The shared driver defines struct ameba_timer_config_s + * and instantiates this table; each row is + * { base, periph, clk, clkfreq, irq, idx }. + */ + +#define AMEBA_TIMER_NINSTANCES 2 + +#define AMEBA_TIMER_CONFIG_TABLE \ +{ \ + { \ + 0x40808200ul, AMEBA_TIMER_LTIM1_MASK, AMEBA_TIMER_LTIM1_MASK, \ + 32768ul, RTL8720F_IRQ_TIMER1, 1 \ + }, \ + { \ + 0x40808400ul, AMEBA_TIMER_LTIM2_MASK, AMEBA_TIMER_LTIM2_MASK, \ + 32768ul, RTL8720F_IRQ_TIMER2, 2 \ + }, \ +} + +#endif /* __ARCH_ARM_SRC_RTL8720F_AMEBA_TIMER_CHIP_H */ diff --git a/arch/arm/src/rtl8721dx/CMakeLists.txt b/arch/arm/src/rtl8721dx/CMakeLists.txt index 5e2dda71e146f..b9345e0d78f48 100644 --- a/arch/arm/src/rtl8721dx/CMakeLists.txt +++ b/arch/arm/src/rtl8721dx/CMakeLists.txt @@ -72,6 +72,10 @@ if(CONFIG_AMEBA_WDG) list(APPEND SRCS ${AMEBA_COMMON}/ameba_wdg.c) endif() +if(CONFIG_AMEBA_TIMER) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_timer.c) +endif() + target_include_directories(arch PRIVATE ${AMEBA_COMMON}) target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/rtl8721dx/Make.defs b/arch/arm/src/rtl8721dx/Make.defs index 0503fce09fb90..303d1fc2b8259 100644 --- a/arch/arm/src/rtl8721dx/Make.defs +++ b/arch/arm/src/rtl8721dx/Make.defs @@ -82,6 +82,10 @@ ifeq ($(CONFIG_AMEBA_WDG),y) CHIP_CSRCS += ameba_wdg.c endif +ifeq ($(CONFIG_AMEBA_TIMER),y) +CHIP_CSRCS += ameba_timer.c +endif + ############################################################################ # Realtek RTL8721Dx SDK integration # diff --git a/arch/arm/src/rtl8721dx/ameba_board.mk b/arch/arm/src/rtl8721dx/ameba_board.mk index 204699ed8d754..e2710e0eea4a4 100644 --- a/arch/arm/src/rtl8721dx/ameba_board.mk +++ b/arch/arm/src/rtl8721dx/ameba_board.mk @@ -155,12 +155,13 @@ ifeq ($(CONFIG_AMEBA_SPI),y) AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_spi.c endif -# PWM timer register layer. The time-base entry points (RTIM_TimeBaseInit/ -# StructInit/Cmd) are in ROM, but the compare/period helpers the PWM driver -# (arch/.../common/ameba/ameba_pwm.c) calls -- RTIM_CCStructInit/CCxInit/ -# CCRxSet/CCxCmd/ChangePeriod/PrescalerConfig -- are compiled from this RAM +# PWM/timer register layer. The time-base entry points (RTIM_TimeBaseInit/ +# StructInit/Cmd/INTConfig/GetCount) are in ROM, but the compare/period and +# interrupt-clear helpers the PWM driver (ameba_pwm.c: RTIM_CCStructInit/ +# CCxInit/CCRxSet/CCxCmd/ChangePeriod/PrescalerConfig) and the timer driver +# (ameba_timer.c: RTIM_INTClear/ChangePeriod) call are compiled from this RAM # source and linked in (--gc-sections drops the unused input-capture paths). -ifeq ($(CONFIG_AMEBA_PWM),y) +ifneq (,$(filter y,$(CONFIG_AMEBA_PWM) $(CONFIG_AMEBA_TIMER))) AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_tim.c endif diff --git a/arch/arm/src/rtl8721dx/ameba_timer_chip.h b/arch/arm/src/rtl8721dx/ameba_timer_chip.h new file mode 100644 index 0000000000000..90e65e096c5ff --- /dev/null +++ b/arch/arm/src/rtl8721dx/ameba_timer_chip.h @@ -0,0 +1,111 @@ +/**************************************************************************** + * arch/arm/src/rtl8721dx/ameba_timer_chip.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_RTL8721DX_AMEBA_TIMER_CHIP_H +#define __ARCH_ARM_SRC_RTL8721DX_AMEBA_TIMER_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Per-chip general-purpose timer wiring for RTL8721DX (amebadplus). The + * shared driver (arch/arm/src/common/ameba/ameba_timer.c) includes this + * header to learn which timer instances it may expose and, for each one, its + * register base, input clock, RCC clock masks and interrupt line. A port to + * another Ameba chip supplies a same-named header on the chip include path; + * the shared driver is never edited -- it reads only the macros below and + * the instance table, computing the period from clkfreq with one formula. + * + * The Ameba SoC carries twelve timers (TIM0..TIM11) that all share the one + * RTIM register layout and fwlib API, so the register access, the + * microsecond<->tick conversion and the whole lower-half live in the shared + * driver. What differs per instance -- and per chip -- is only data: the + * base address, the clock that feeds it, its RCC gate masks and its NuttX + * IRQ number. These sit in AMEBA_TIMER_CONFIG_TABLE so a new chip (or + * a different instance choice) edits this header alone. + * + * This port exposes two of the twelve, both from the 32-bit "basic" (LTIM) + * bank so a single lower-half serves them uniformly (verified against the + * SoC hal_platform.h / sysreg_lsys.h / vector table and the vendor + * timer_api.c, not guessed): + * + * instance timer base clock RCC gate NuttX IRQ + * -------- ------ ---------- --------- -------------- ---------- + * 0 TIM1 0x41017200 32.768 kHz APBPeriph_LTIM1 IRQ_TIMER1 + * 1 TIM2 0x41017400 32.768 kHz APBPeriph_LTIM2 IRQ_TIMER2 + * + * TIM1 and TIM2 are two of the eight 32-bit "basic" (LTIM) timers clocked + * from the 32.768 kHz LS clock: ~30.5 us per tick, up to ~36 h in one shot. + * A full 32-bit auto-reload lets them cover the whole microsecond API range, + * which is why the driver exposes this bank rather than the four 40 MHz + * "high" (HTIM) timers TIM8..TIM11: those have only a 16-bit auto-reload + * (max ~1.638 ms at 40 MHz) and no usable prescaler on TIM10/TIM11, so they + * suit sub-millisecond fine timing only and are intentionally not exposed. + * TIM8/TIM9 additionally drive the PWM/input-capture block. + * + * TIM0 is deliberately NOT exposed: the boot ROM claims it as the always-on + * system timer (see the vendor ameba_delay.h -- "TIM0 is used as systimer, + * so TIM0 can not be used for other purpose ... init when boot in rom + * code"), and DelayUs/DelayMs/SYSTIMER_* all rely on it. Reprogramming TIM0 + * would break every SDK delay, so the driver starts the basic bank at TIM1. + * + * The RCC gate masks are the fwlib APBPeriph_LTIM1 / APBPeriph_LTIM2 values + * (function and clock masks are identical on this chip). They are written + * out here rather than pulled from to keep the vendor + * headers out of the NuttX include world (same rule as the PWM chip header). + */ + +/* RCC "function" and "clock" masks, bit30 group selector then bit index. */ + +#define AMEBA_TIMER_LTIM1_MASK (((uint32_t)1 << 30) | ((uint32_t)1 << 13)) +#define AMEBA_TIMER_LTIM2_MASK (((uint32_t)1 << 30) | ((uint32_t)1 << 14)) + +/* Number of timer instances this chip exposes and the data table that + * describes each one. The shared driver defines struct ameba_timer_config_s + * and instantiates this table; each row is + * { base, periph, clk, clkfreq, irq, idx }. + */ + +#define AMEBA_TIMER_NINSTANCES 2 + +#define AMEBA_TIMER_CONFIG_TABLE \ +{ \ + { \ + 0x41017200ul, AMEBA_TIMER_LTIM1_MASK, AMEBA_TIMER_LTIM1_MASK, \ + 32768ul, RTL8721DX_IRQ_TIMER1, 1 \ + }, \ + { \ + 0x41017400ul, AMEBA_TIMER_LTIM2_MASK, AMEBA_TIMER_LTIM2_MASK, \ + 32768ul, RTL8721DX_IRQ_TIMER2, 2 \ + }, \ +} + +#endif /* __ARCH_ARM_SRC_RTL8721DX_AMEBA_TIMER_CHIP_H */ diff --git a/arch/arm/src/rtl8721f/CMakeLists.txt b/arch/arm/src/rtl8721f/CMakeLists.txt index b873cd91c6291..48131cf2d149c 100644 --- a/arch/arm/src/rtl8721f/CMakeLists.txt +++ b/arch/arm/src/rtl8721f/CMakeLists.txt @@ -78,6 +78,10 @@ if(CONFIG_AMEBA_WDG) list(APPEND SRCS ${AMEBA_COMMON}/ameba_wdg.c) endif() +if(CONFIG_AMEBA_TIMER) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_timer.c) +endif() + target_include_directories(arch PRIVATE ${AMEBA_COMMON}) target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm/src/rtl8721f/Make.defs b/arch/arm/src/rtl8721f/Make.defs index 55461ca346541..0c2fce0fd8423 100644 --- a/arch/arm/src/rtl8721f/Make.defs +++ b/arch/arm/src/rtl8721f/Make.defs @@ -88,6 +88,10 @@ ifeq ($(CONFIG_AMEBA_WDG),y) CHIP_CSRCS += ameba_wdg.c endif +ifeq ($(CONFIG_AMEBA_TIMER),y) +CHIP_CSRCS += ameba_timer.c +endif + ############################################################################ # Realtek RTL8721F SDK integration # diff --git a/arch/arm/src/rtl8721f/ameba_board.mk b/arch/arm/src/rtl8721f/ameba_board.mk index a8f47443747d1..3b4148e71d77c 100644 --- a/arch/arm/src/rtl8721f/ameba_board.mk +++ b/arch/arm/src/rtl8721f/ameba_board.mk @@ -167,12 +167,13 @@ ifeq ($(CONFIG_AMEBA_SPI),y) AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_spi.c endif -# PWM timer register layer. The time-base entry points (RTIM_TimeBaseInit/ -# StructInit/Cmd) are in ROM, but the compare/period helpers the PWM driver -# (arch/.../common/ameba/ameba_pwm.c) calls -- RTIM_CCStructInit/CCxInit/ -# CCRxSet/CCxCmd/ChangePeriod/PrescalerConfig -- are compiled from this RAM +# PWM/timer register layer. The time-base entry points (RTIM_TimeBaseInit/ +# StructInit/Cmd/INTConfig/GetCount) are in ROM, but the compare/period and +# interrupt-clear helpers the PWM driver (ameba_pwm.c: RTIM_CCStructInit/ +# CCxInit/CCRxSet/CCxCmd/ChangePeriod/PrescalerConfig) and the timer driver +# (ameba_timer.c: RTIM_INTClear/ChangePeriod) call are compiled from this RAM # source and linked in (--gc-sections drops the unused input-capture paths). -ifeq ($(CONFIG_AMEBA_PWM),y) +ifneq (,$(filter y,$(CONFIG_AMEBA_PWM) $(CONFIG_AMEBA_TIMER))) AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_tim.c endif diff --git a/arch/arm/src/rtl8721f/ameba_timer_chip.h b/arch/arm/src/rtl8721f/ameba_timer_chip.h new file mode 100644 index 0000000000000..364548f800a7c --- /dev/null +++ b/arch/arm/src/rtl8721f/ameba_timer_chip.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * arch/arm/src/rtl8721f/ameba_timer_chip.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_RTL8721F_AMEBA_TIMER_CHIP_H +#define __ARCH_ARM_SRC_RTL8721F_AMEBA_TIMER_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Per-chip general-purpose timer wiring for RTL8721F (amebagreen2). The + * shared driver (arch/arm/src/common/ameba/ameba_timer.c) includes this + * header to learn which timer instances it may expose and, for each one, its + * register base, input clock, RCC clock masks and interrupt line. A port to + * another Ameba chip supplies a same-named header on the chip include path; + * the shared driver is never edited -- it reads only the macros below and + * the instance table, computing the period from clkfreq with one formula. + * + * The Ameba SoC carries a bank of timers that all share the one RTIM + * register layout and fwlib API, so the register access, the + * microsecond<->tick conversion and the whole lower-half live in the shared + * driver. What differs per instance -- and per chip -- is only data: the + * base address, the clock that feeds it, its RCC gate masks and its NuttX + * IRQ number. These sit in AMEBA_TIMER_CONFIG_TABLE so a new chip (or + * a different instance choice) edits this header alone. + * + * This port exposes two of the 32-bit "basic" (LTIM) timers so a single + * lower-half serves them uniformly (verified against the SoC hal_platform.h + * / sysreg_lsys.h / vector table, not guessed): + * + * instance timer base clock RCC gate NuttX IRQ + * -------- ------ ---------- --------- -------------- ---------- + * 0 TIM1 0x40819200 32.768 kHz APBPeriph_LTIM1 IRQ_TIMER1 + * 1 TIM2 0x40819400 32.768 kHz APBPeriph_LTIM2 IRQ_TIMER2 + * + * TIM1 and TIM2 are two of the six "basic" (LTIM) timers clocked from the + * 32.768 kHz LS clock: ~30.5 us per tick, up to ~36 h in one shot. A full + * 32-bit auto-reload lets them cover the whole microsecond API range, which + * is why the driver exposes this bank rather than the "high" (HTIM) timers, + * whose 16-bit auto-reload suits sub-millisecond fine timing only. The + * non-secure base alias (0x40xxxxxx) is used, matching the core this port + * runs on. + * + * TIM0 is deliberately NOT exposed: the boot ROM claims it as the always-on + * system timer (see the vendor ameba_delay.h), and DelayUs/DelayMs and the + * SYSTIMER_* helpers all rely on it. Reprogramming TIM0 would break every + * SDK delay, so the + * driver starts the basic bank at TIM1. + * + * The RCC gate masks are the fwlib APBPeriph_LTIM1 / APBPeriph_LTIM2 values + * (function and clock masks are identical on this chip). They are written + * out here rather than pulled from to keep the vendor + * headers out of the NuttX include world (same rule as the PWM chip header). + */ + +/* RCC "function" and "clock" masks, bit30 group selector then bit index. */ + +#define AMEBA_TIMER_LTIM1_MASK (((uint32_t)1 << 30) | ((uint32_t)1 << 13)) +#define AMEBA_TIMER_LTIM2_MASK (((uint32_t)1 << 30) | ((uint32_t)1 << 14)) + +/* Number of timer instances this chip exposes and the data table that + * describes each one. The shared driver defines struct ameba_timer_config_s + * and instantiates this table; each row is + * { base, periph, clk, clkfreq, irq, idx }. + */ + +#define AMEBA_TIMER_NINSTANCES 2 + +#define AMEBA_TIMER_CONFIG_TABLE \ +{ \ + { \ + 0x40819200ul, AMEBA_TIMER_LTIM1_MASK, AMEBA_TIMER_LTIM1_MASK, \ + 32768ul, RTL8721F_IRQ_TIMER1, 1 \ + }, \ + { \ + 0x40819400ul, AMEBA_TIMER_LTIM2_MASK, AMEBA_TIMER_LTIM2_MASK, \ + 32768ul, RTL8721F_IRQ_TIMER2, 2 \ + }, \ +} + +#endif /* __ARCH_ARM_SRC_RTL8721F_AMEBA_TIMER_CHIP_H */ diff --git a/boards/arm/rtl8720f/rtl8720f_evb/configs/timer/defconfig b/boards/arm/rtl8720f/rtl8720f_evb/configs/timer/defconfig new file mode 100644 index 0000000000000..e3fb1a819f843 --- /dev/null +++ b/boards/arm/rtl8720f/rtl8720f_evb/configs/timer/defconfig @@ -0,0 +1,46 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_AMEBA_TIMER=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="rtl8720f_evb" +CONFIG_ARCH_BOARD_RTL8720F_EVB=y +CONFIG_ARCH_CHIP="rtl8720f" +CONFIG_ARCH_CHIP_RTL8720F=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV8M_SYSTICK=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_TASK_STACKSIZE=4096 +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_TIMER=y +CONFIG_FS_PROCFS=y +CONFIG_FS_TMPFS=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LIBC_MEMFD_ERROR=y +CONFIG_MM_DEFAULT_ALIGNMENT=32 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=262144 +CONFIG_RAM_START=0x30008000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_LPWORK=y +CONFIG_STACK_COLORATION=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=2500 +CONFIG_TIMER_ARCH=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/CMakeLists.txt b/boards/arm/rtl8720f/rtl8720f_evb/src/CMakeLists.txt index 5160bf6170a96..73ac9f1864876 100644 --- a/boards/arm/rtl8720f/rtl8720f_evb/src/CMakeLists.txt +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/CMakeLists.txt @@ -54,6 +54,10 @@ if(CONFIG_AMEBA_WDG) list(APPEND SRCS rtl8720f_wdg.c) endif() +if(CONFIG_AMEBA_TIMER) + list(APPEND SRCS rtl8720f_timer.c) +endif() + target_sources(board PRIVATE ${SRCS}) if(CONFIG_AMEBA_GPIO @@ -63,7 +67,8 @@ if(CONFIG_AMEBA_GPIO OR CONFIG_AMEBA_PWM OR CONFIG_AMEBA_ADC OR CONFIG_AMEBA_RTC - OR CONFIG_AMEBA_WDG) + OR CONFIG_AMEBA_WDG + OR CONFIG_AMEBA_TIMER) # The board pin tables pull in the shared drivers' public headers from # arch/arm/src/common/ameba/, not on the default board include path. target_include_directories(board diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/Makefile b/boards/arm/rtl8720f/rtl8720f_evb/src/Makefile index ca5e5a9e93173..c2a7f73090b2c 100644 --- a/boards/arm/rtl8720f/rtl8720f_evb/src/Makefile +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/Makefile @@ -56,10 +56,14 @@ ifeq ($(CONFIG_AMEBA_WDG),y) CSRCS += rtl8720f_wdg.c endif +ifeq ($(CONFIG_AMEBA_TIMER),y) +CSRCS += rtl8720f_timer.c +endif + # The board pin tables pull in the shared drivers' public headers from # arch/arm/src/common/ameba/, which is not on the default board include path. -ifneq ($(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART)$(CONFIG_AMEBA_I2C)$(CONFIG_AMEBA_SPI)$(CONFIG_AMEBA_PWM)$(CONFIG_AMEBA_ADC)$(CONFIG_AMEBA_RTC)$(CONFIG_AMEBA_WDG),) +ifneq ($(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART)$(CONFIG_AMEBA_I2C)$(CONFIG_AMEBA_SPI)$(CONFIG_AMEBA_PWM)$(CONFIG_AMEBA_ADC)$(CONFIG_AMEBA_RTC)$(CONFIG_AMEBA_WDG)$(CONFIG_AMEBA_TIMER),) CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba endif diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_bringup.c b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_bringup.c index 59a9cb0d4110a..a5ec42deec617 100644 --- a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_bringup.c +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_bringup.c @@ -200,6 +200,16 @@ int rtl8720f_bringup(void) } #endif +#ifdef CONFIG_AMEBA_TIMER + /* Register the board's timers at /dev/timer0 and /dev/timer1. */ + + ret = rtl8720f_timer_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: rtl8720f_timer_initialize failed: %d\n", ret); + } +#endif + /* Install the inter-core HW IPC-semaphore RTOS hooks LAST -- after all the * flash / WHC bring-up above, and just before this (board_late_initialize) * path returns and nx_start() hands off to the init task. diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h index d8cc70e811a82..ba8c12c880148 100644 --- a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_rtl8720f_evb.h @@ -117,6 +117,19 @@ int rtl8720f_rtc_initialize(void); int rtl8720f_wdg_initialize(void); #endif +#ifdef CONFIG_AMEBA_TIMER +/**************************************************************************** + * Name: rtl8720f_timer_initialize + * + * Description: + * Register the board's timers at /dev/timer0 (TIM1) and /dev/timer1 + * (TIM2) (boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_timer.c). + * + ****************************************************************************/ + +int rtl8720f_timer_initialize(void); +#endif + #ifdef CONFIG_RTL8720F_WIFI /**************************************************************************** * Name: rtl8720f_wifi_initialize diff --git a/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_timer.c b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_timer.c new file mode 100644 index 0000000000000..5404d7ecd413a --- /dev/null +++ b/boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_timer.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/arm/rtl8720f/rtl8720f_evb/src/rtl8720f_timer.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 + ****************************************************************************/ + +#include + +#include +#include + +#include "ameba_timer.h" +#include "rtl8720f_rtl8720f_evb.h" + +#ifdef CONFIG_AMEBA_TIMER + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8720f_timer_initialize + * + * Description: + * Register the board's general-purpose timers. Both timers are internal + * (no board wiring), so this just binds the two exposed instances to their + * device nodes: /dev/timer0 is TIM1 and /dev/timer1 is TIM2, both 32-bit + * basic timers at 32.768 kHz. TIM0 is reserved by the ROM as the system + * timer and is not exposed. A failure on either is logged but does not + * abort the other. + * + ****************************************************************************/ + +int rtl8720f_timer_initialize(void) +{ + int ret; + + ret = ameba_timer_initialize("/dev/timer0", 0); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_timer_initialize(/dev/timer0) failed: %d\n", ret); + } + + ret = ameba_timer_initialize("/dev/timer1", 1); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_timer_initialize(/dev/timer1) failed: %d\n", ret); + } + + return ret; +} + +#endif /* CONFIG_AMEBA_TIMER */ diff --git a/boards/arm/rtl8721dx/pke8721daf/configs/timer/defconfig b/boards/arm/rtl8721dx/pke8721daf/configs/timer/defconfig new file mode 100644 index 0000000000000..22a609302de5a --- /dev/null +++ b/boards/arm/rtl8721dx/pke8721daf/configs/timer/defconfig @@ -0,0 +1,47 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_AMEBA_TIMER=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="pke8721daf" +CONFIG_ARCH_BOARD_PKE8721DAF=y +CONFIG_ARCH_CHIP="rtl8721dx" +CONFIG_ARCH_CHIP_RTL8721DX=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV8M_SYSTICK=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_TASK_STACKSIZE=4096 +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_TIMER=y +CONFIG_FS_PROCFS=y +CONFIG_FS_TMPFS=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LIBC_MEMFD_ERROR=y +CONFIG_MM_DEFAULT_ALIGNMENT=32 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=294912 +CONFIG_RAM_START=0x20020000 +CONFIG_RR_INTERVAL=200 +CONFIG_RTL8721DX_FLASH_FS=y +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_LPWORK=y +CONFIG_STACK_COLORATION=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=2500 +CONFIG_TIMER_ARCH=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm/rtl8721dx/pke8721daf/src/CMakeLists.txt b/boards/arm/rtl8721dx/pke8721daf/src/CMakeLists.txt index b0e12365ffe44..6e4a7c921b5f0 100644 --- a/boards/arm/rtl8721dx/pke8721daf/src/CMakeLists.txt +++ b/boards/arm/rtl8721dx/pke8721daf/src/CMakeLists.txt @@ -54,6 +54,10 @@ if(CONFIG_AMEBA_WDG) list(APPEND SRCS rtl8721dx_wdg.c) endif() +if(CONFIG_AMEBA_TIMER) + list(APPEND SRCS rtl8721dx_timer.c) +endif() + target_sources(board PRIVATE ${SRCS}) if(CONFIG_AMEBA_GPIO @@ -63,7 +67,8 @@ if(CONFIG_AMEBA_GPIO OR CONFIG_AMEBA_PWM OR CONFIG_AMEBA_ADC OR CONFIG_AMEBA_RTC - OR CONFIG_AMEBA_WDG) + OR CONFIG_AMEBA_WDG + OR CONFIG_AMEBA_TIMER) # The board pin/UART tables pull in the shared driver's public headers from # arch/arm/src/common/ameba/, not on the default board include path. target_include_directories(board diff --git a/boards/arm/rtl8721dx/pke8721daf/src/Makefile b/boards/arm/rtl8721dx/pke8721daf/src/Makefile index 2fd83e815f387..f5ab325199380 100644 --- a/boards/arm/rtl8721dx/pke8721daf/src/Makefile +++ b/boards/arm/rtl8721dx/pke8721daf/src/Makefile @@ -96,4 +96,13 @@ CSRCS += rtl8721dx_wdg.c CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba endif +ifeq ($(CONFIG_AMEBA_TIMER),y) +CSRCS += rtl8721dx_timer.c + +# The board timer bring-up pulls in the shared driver's public header from +# arch/arm/src/common/ameba/, which is not on the default board include path. + +CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_bringup.c b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_bringup.c index d32f19c2062b3..5a456a7ea691a 100644 --- a/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_bringup.c +++ b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_bringup.c @@ -188,6 +188,16 @@ int rtl8721dx_bringup(void) } #endif +#ifdef CONFIG_AMEBA_TIMER + /* Register the board's timers at /dev/timer0 and /dev/timer1. */ + + ret = rtl8721dx_timer_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: rtl8721dx_timer_initialize failed: %d\n", ret); + } +#endif + /* Install the inter-core HW IPC-semaphore RTOS hooks LAST -- after all the * flash / WHC bring-up above, and just before this (board_late_initialize) * path returns and nx_start() hands off to the init task. diff --git a/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_pke8721daf.h b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_pke8721daf.h index 94a3934b73d55..6e5b908941041 100644 --- a/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_pke8721daf.h +++ b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_pke8721daf.h @@ -173,6 +173,19 @@ int rtl8721dx_rtc_initialize(void); int rtl8721dx_wdg_initialize(void); #endif +#ifdef CONFIG_AMEBA_TIMER +/**************************************************************************** + * Name: rtl8721dx_timer_initialize + * + * Description: + * Register the board's timers at /dev/timer0 (TIM1) and /dev/timer1 + * (TIM2) (boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_timer.c). + * + ****************************************************************************/ + +int rtl8721dx_timer_initialize(void); +#endif + #ifdef CONFIG_RTL8721DX_FLASH_FS /**************************************************************************** * Name: ameba_flash_fs_initialize diff --git a/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_timer.c b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_timer.c new file mode 100644 index 0000000000000..36cf349d25c13 --- /dev/null +++ b/boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_timer.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/arm/rtl8721dx/pke8721daf/src/rtl8721dx_timer.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 + ****************************************************************************/ + +#include + +#include +#include + +#include "ameba_timer.h" +#include "rtl8721dx_pke8721daf.h" + +#ifdef CONFIG_AMEBA_TIMER + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8721dx_timer_initialize + * + * Description: + * Register the board's general-purpose timers. Both timers are internal + * (no board wiring), so this just binds the two exposed instances to their + * device nodes: /dev/timer0 is TIM1 and /dev/timer1 is TIM2, both 32-bit + * basic timers at 32.768 kHz. TIM0 is reserved by the ROM as the system + * timer and is not exposed. A failure on either is logged but does not + * abort the other. + * + ****************************************************************************/ + +int rtl8721dx_timer_initialize(void) +{ + int ret; + + ret = ameba_timer_initialize("/dev/timer0", 0); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_timer_initialize(/dev/timer0) failed: %d\n", ret); + } + + ret = ameba_timer_initialize("/dev/timer1", 1); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_timer_initialize(/dev/timer1) failed: %d\n", ret); + } + + return ret; +} + +#endif /* CONFIG_AMEBA_TIMER */ diff --git a/boards/arm/rtl8721f/rtl8721f_evb/configs/timer/defconfig b/boards/arm/rtl8721f/rtl8721f_evb/configs/timer/defconfig new file mode 100644 index 0000000000000..c56abd7590b75 --- /dev/null +++ b/boards/arm/rtl8721f/rtl8721f_evb/configs/timer/defconfig @@ -0,0 +1,46 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_AMEBA_TIMER=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="rtl8721f_evb" +CONFIG_ARCH_BOARD_RTL8721F_EVB=y +CONFIG_ARCH_CHIP="rtl8721f" +CONFIG_ARCH_CHIP_RTL8721F=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARMV8M_SYSTICK=y +CONFIG_BOARD_LOOPSPERMSEC=43103 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_TASK_STACKSIZE=4096 +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_TIMER=y +CONFIG_FS_PROCFS=y +CONFIG_FS_TMPFS=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LIBC_MEMFD_ERROR=y +CONFIG_MM_DEFAULT_ALIGNMENT=32 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=401408 +CONFIG_RAM_START=0x20006000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SCHED_LPWORK=y +CONFIG_STACK_COLORATION=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=2500 +CONFIG_TIMER_ARCH=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt b/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt index 3f11353500811..8a3de07c5fae2 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/CMakeLists.txt @@ -54,6 +54,10 @@ if(CONFIG_AMEBA_WDG) list(APPEND SRCS rtl8721f_wdg.c) endif() +if(CONFIG_AMEBA_TIMER) + list(APPEND SRCS rtl8721f_timer.c) +endif() + target_sources(board PRIVATE ${SRCS}) if(CONFIG_AMEBA_GPIO @@ -63,7 +67,8 @@ if(CONFIG_AMEBA_GPIO OR CONFIG_AMEBA_PWM OR CONFIG_AMEBA_ADC OR CONFIG_AMEBA_RTC - OR CONFIG_AMEBA_WDG) + OR CONFIG_AMEBA_WDG + OR CONFIG_AMEBA_TIMER) # The board pin tables pull in the shared drivers' public headers from # arch/arm/src/common/ameba/, not on the default board include path. target_include_directories(board diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile b/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile index f07897e486bea..d9c0a6277649a 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/Makefile @@ -56,10 +56,14 @@ ifeq ($(CONFIG_AMEBA_WDG),y) CSRCS += rtl8721f_wdg.c endif +ifeq ($(CONFIG_AMEBA_TIMER),y) +CSRCS += rtl8721f_timer.c +endif + # The board pin tables pull in the shared drivers' public headers from # arch/arm/src/common/ameba/, which is not on the default board include path. -ifneq ($(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART)$(CONFIG_AMEBA_I2C)$(CONFIG_AMEBA_SPI)$(CONFIG_AMEBA_PWM)$(CONFIG_AMEBA_ADC)$(CONFIG_AMEBA_RTC)$(CONFIG_AMEBA_WDG),) +ifneq ($(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART)$(CONFIG_AMEBA_I2C)$(CONFIG_AMEBA_SPI)$(CONFIG_AMEBA_PWM)$(CONFIG_AMEBA_ADC)$(CONFIG_AMEBA_RTC)$(CONFIG_AMEBA_WDG)$(CONFIG_AMEBA_TIMER),) CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba endif diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c index a8506819977eb..955f11caed406 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_bringup.c @@ -214,6 +214,16 @@ int rtl8721f_bringup(void) } #endif +#ifdef CONFIG_AMEBA_TIMER + /* Register the board's timers at /dev/timer0 and /dev/timer1. */ + + ret = rtl8721f_timer_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: rtl8721f_timer_initialize failed: %d\n", ret); + } +#endif + IPC_patch_function(rtos_critical_enter, rtos_critical_exit, AMEBA_RTOS_CRITICAL_SEMA); IPC_SEMDelayStub(rtos_time_delay_ms); diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h index 01ce0923c4cfa..9d38c8b7b8d54 100644 --- a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_rtl8721f_evb.h @@ -186,6 +186,19 @@ int rtl8721f_rtc_initialize(void); int rtl8721f_wdg_initialize(void); #endif +#ifdef CONFIG_AMEBA_TIMER +/**************************************************************************** + * Name: rtl8721f_timer_initialize + * + * Description: + * Register the board's timers at /dev/timer0 (TIM1) and /dev/timer1 + * (TIM2) (boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_timer.c). + * + ****************************************************************************/ + +int rtl8721f_timer_initialize(void); +#endif + #ifdef CONFIG_RTL8721F_FLASH_FS /**************************************************************************** * Name: ameba_flash_fs_initialize diff --git a/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_timer.c b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_timer.c new file mode 100644 index 0000000000000..1aa671490307b --- /dev/null +++ b/boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_timer.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/arm/rtl8721f/rtl8721f_evb/src/rtl8721f_timer.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 + ****************************************************************************/ + +#include + +#include +#include + +#include "ameba_timer.h" +#include "rtl8721f_rtl8721f_evb.h" + +#ifdef CONFIG_AMEBA_TIMER + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8721f_timer_initialize + * + * Description: + * Register the board's general-purpose timers. Both timers are internal + * (no board wiring), so this just binds the two exposed instances to their + * device nodes: /dev/timer0 is TIM1 and /dev/timer1 is TIM2, both 32-bit + * basic timers at 32.768 kHz. TIM0 is reserved by the ROM as the system + * timer and is not exposed. A failure on either is logged but does not + * abort the other. + * + ****************************************************************************/ + +int rtl8721f_timer_initialize(void) +{ + int ret; + + ret = ameba_timer_initialize("/dev/timer0", 0); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_timer_initialize(/dev/timer0) failed: %d\n", ret); + } + + ret = ameba_timer_initialize("/dev/timer1", 1); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_timer_initialize(/dev/timer1) failed: %d\n", ret); + } + + return ret; +} + +#endif /* CONFIG_AMEBA_TIMER */