This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 3856ddf929b6f8a26f45fd0e14968480eaf1eb5c Author: raiden00pl <[email protected]> AuthorDate: Tue Oct 20 14:47:58 2026 +0200 !arch/arm/src/common/stm32: use the common tickless driver on STM32L4, L5 and U5 Drop the STM32L4 two-timer tickless driver in favor of the common one. It is a 2016 copy of the STM32 driver from before the single-timer rewrite in 95cbbf552bb ("Change STM32 tickless to use only one timer") and never got that change. STM32L5 and STM32U5 had no driver before, and STM32WL5 tickless did not link; all three build now. usleep() latency with a 100 us tick, 500 calls per run (100 for 15 ms). NUCLEO-L496ZG, master STM32L4 driver vs this change, 3 runs each: request two-timer (TIM2+TIM5) single-timer (TIM2) 100 us 1200-1400 us, 1 of 3 hung 900-1300 us 1 ms 3 of 3 hung 1700-1900 us 15 ms 16100-16300 us 15900 us In a hung run the sleeping task never wakes up: the one-shot timer is stopped with its interrupt disabled. Clock drift over 60 s is the same with both drivers. BREAKING CHANGE: this is a change of the STM32L4 tickless implementation, not of its interface; it is marked as breaking only to make it visible. Configurations with the default timers need no change and keep using TIM2. CONFIG_STM32_TICKLESS_ONESHOT and CONFIG_STM32_TICKLESS_FREERUN are removed; a configuration that set them selects the timer with CONFIG_STM32_TICKLESS_TIMER and CONFIG_STM32_TICKLESS_CHANNEL instead (basic timers TIM6/TIM7 cannot be used). Signed-off-by: raiden00pl <[email protected]> Assisted-by: Claude Code --- .github/CODEOWNERS | 1 - arch/arm/src/common/stm32/Kconfig.system | 9 +- arch/arm/src/common/stm32/Kconfig.tim | 20 -- arch/arm/src/stm32l4/CMakeLists.txt | 4 - arch/arm/src/stm32l4/Make.defs | 4 - arch/arm/src/stm32l4/stm32l4_tickless.c | 341 ------------------------------- 6 files changed, 3 insertions(+), 376 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5c1f4578231..241de2c39c3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4419,7 +4419,6 @@ arch/arm/src/stm32l4/stm32l4_spi.c [email protected] petro.karashchenko@gmail arch/arm/src/stm32l4/stm32l4_spi.h [email protected] [email protected] [email protected] [email protected] arch/arm/src/stm32l4/stm32l4_start.c [email protected] [email protected] [email protected] [email protected] arch/arm/src/stm32l4/stm32l4_start.h [email protected] [email protected] -arch/arm/src/stm32l4/stm32l4_tickless.c [email protected] [email protected] [email protected] [email protected] arch/arm/src/stm32l4/stm32l4_uart.h [email protected] [email protected] [email protected] [email protected] [email protected] arch/arm/src/stm32l4/stm32l4_uid.c [email protected] [email protected] arch/arm/src/stm32l4/stm32l4_uid.h [email protected] [email protected] diff --git a/arch/arm/src/common/stm32/Kconfig.system b/arch/arm/src/common/stm32/Kconfig.system index 67586e410aa..5a4b85f1b29 100644 --- a/arch/arm/src/common/stm32/Kconfig.system +++ b/arch/arm/src/common/stm32/Kconfig.system @@ -40,19 +40,16 @@ config STM32_DFU config STM32_TICKLESS_TIMER int "Tickless hardware timer" - depends on SCHED_TICKLESS - depends on (STM32_COMMON_LEGACY && STM32_TIM) || STM32_COMMON_F7_H7_H5 || ARCH_CHIP_STM32WB + depends on SCHED_TICKLESS && STM32_TIM default 2 - range 1 14 if STM32_COMMON_LEGACY || ARCH_CHIP_STM32F7 - range 1 17 if STM32_COMMON_H7_H5 || ARCH_CHIP_STM32WB + range 1 17 ---help--- If the Tickless OS feature is enabled, then one clock must be assigned to provided the timer needed by the OS. config STM32_TICKLESS_CHANNEL int "Tickless timer channel" - depends on SCHED_TICKLESS - depends on (STM32_COMMON_LEGACY && STM32_TIM) || STM32_COMMON_F7_H7_H5 || ARCH_CHIP_STM32WB + depends on SCHED_TICKLESS && STM32_TIM default 1 range 1 4 ---help--- diff --git a/arch/arm/src/common/stm32/Kconfig.tim b/arch/arm/src/common/stm32/Kconfig.tim index ec9729f01a5..aae4d6ba70a 100644 --- a/arch/arm/src/common/stm32/Kconfig.tim +++ b/arch/arm/src/common/stm32/Kconfig.tim @@ -979,7 +979,6 @@ endchoice config STM32_ONESHOT bool "TIM one-shot wrapper" depends on STM32_TIM - default y if STM32_COMMON_L4_L5_U5 && SCHED_TICKLESS ---help--- Enable a wrapper around the low level timer/counter functions to support one-shot timer. @@ -987,7 +986,6 @@ config STM32_ONESHOT config STM32_FREERUN bool "TIM free-running wrapper" depends on STM32_TIM - default y if STM32_COMMON_L4_L5_U5 && SCHED_TICKLESS ---help--- Enable a wrapper around the low level timer/counter functions to support a free-running timer. @@ -4051,24 +4049,6 @@ config STM32_LPTIM5_CLOCK ---help--- This clock frequency determines the timer's counting rate. -config STM32_TICKLESS_ONESHOT - int "Tickless one-shot timer channel" - depends on STM32_COMMON_L4_L5_U5 && SCHED_TICKLESS && STM32_ONESHOT - default 2 - range 1 8 - ---help--- - If the Tickless OS feature is enabled, then one clock must be - assigned to provide the one-shot timer needed by the OS. - -config STM32_TICKLESS_FREERUN - int "Tickless free-running timer channel" - depends on STM32_COMMON_L4_L5_U5 && SCHED_TICKLESS && STM32_FREERUN - default 5 - range 1 8 - ---help--- - If the Tickless OS feature is enabled, then one clock must be - assigned to provide the free-running timer needed by the OS. - config STM32_LPTIM1_PWM bool "LPTIM1 PWM" depends on STM32_COMMON_L4_L5_U5 && STM32_LPTIM1 diff --git a/arch/arm/src/stm32l4/CMakeLists.txt b/arch/arm/src/stm32l4/CMakeLists.txt index a851827960c..819a8d8f48d 100644 --- a/arch/arm/src/stm32l4/CMakeLists.txt +++ b/arch/arm/src/stm32l4/CMakeLists.txt @@ -44,10 +44,6 @@ if(NOT CONFIG_ARCH_IDLE_CUSTOM) list(APPEND SRCS stm32l4_idle.c) endif() -if(CONFIG_SCHED_TICKLESS) - list(APPEND SRCS stm32l4_tickless.c) -endif() - if(CONFIG_BUILD_PROTECTED) list(APPEND SRCS stm32l4_userspace.c stm32l4_mpuinit.c) endif() diff --git a/arch/arm/src/stm32l4/Make.defs b/arch/arm/src/stm32l4/Make.defs index 39081676073..8dd3a34c2e1 100644 --- a/arch/arm/src/stm32l4/Make.defs +++ b/arch/arm/src/stm32l4/Make.defs @@ -41,10 +41,6 @@ ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y) CHIP_CSRCS += stm32l4_idle.c endif -ifeq ($(CONFIG_SCHED_TICKLESS),y) -CHIP_CSRCS += stm32l4_tickless.c -endif - ifeq ($(CONFIG_BUILD_PROTECTED),y) CHIP_CSRCS += stm32l4_userspace.c stm32l4_mpuinit.c endif diff --git a/arch/arm/src/stm32l4/stm32l4_tickless.c b/arch/arm/src/stm32l4/stm32l4_tickless.c deleted file mode 100644 index a10568f7107..00000000000 --- a/arch/arm/src/stm32l4/stm32l4_tickless.c +++ /dev/null @@ -1,341 +0,0 @@ -/**************************************************************************** - * arch/arm/src/stm32l4/stm32l4_tickless.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. - * - ****************************************************************************/ - -/**************************************************************************** - * Tickless OS Support. - * - * When CONFIG_SCHED_TICKLESS is enabled, all support for timer interrupts - * is suppressed and the platform specific code is expected to provide the - * following custom functions. - * - * void up_timer_initialize(void): Initializes the timer facilities. - * Called early in the initialization sequence (by up_initialize()). - * int up_timer_gettime(struct timespec *ts): Returns the current - * time from the platform specific time source. - * int up_timer_cancel(void): Cancels the interval timer. - * int up_timer_start(const struct timespec *ts): Start (or re-starts) - * the interval timer. - * - * The RTOS will provide the following interfaces for use by the platform- - * specific interval timer implementation: - * - * void nxsched_process_timer(void): Called by the platform-specific - * logic when the interval timer expires. - * - ****************************************************************************/ - -/**************************************************************************** - * STM32L4 Timer Usage - * - * This current implementation uses two timers: A one-shot timer to provide - * the timed events and a free running timer to provide the current time. - * Since timers are a limited resource, that could be an issue on some - * systems. - * - * We could do the job with a single timer if we were to keep the single - * timer in a free-running at all times. The STM32 timer/counters have - * 16-bit/32-bit counters with the capability to generate a compare interrupt - * when the timer matches a compare value but also to continue counting - * without stopping (giving another, different interrupt when the timer - * rolls over from 0xffffffff to zero). So we could potentially just set - * the compare at the number of ticks you want PLUS the current value of - * timer. Then you could have both with a single timer: An interval timer - * and a free-running counter with the same timer! - * - * Patches are welcome! - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <nuttx/config.h> - -#include <stdint.h> -#include <stdbool.h> - -#include <nuttx/arch.h> -#include <assert.h> -#include <nuttx/debug.h> - -#include "stm32_oneshot.h" -#include "stm32_freerun.h" - -#ifdef CONFIG_SCHED_TICKLESS - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#ifndef CONFIG_STM32_ONESHOT -# error CONFIG_STM32_ONESHOT must be selected for the Tickless OS option -#endif - -#ifndef CONFIG_STM32_FREERUN -# error CONFIG_STM32_FREERUN must be selected for the Tickless OS option -#endif - -#ifndef CONFIG_STM32_TICKLESS_FREERUN -# error CONFIG_STM32_TICKLESS_FREERUN must be selected for the Tickless OS option -#endif - -#ifndef CONFIG_STM32_TICKLESS_ONESHOT -# error CONFIG_STM32_TICKLESS_ONESHOT must be selected for the Tickless OS option -#endif - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct stm32_tickless_s -{ - struct stm32_oneshot_s oneshot; - struct stm32_freerun_s freerun; -}; - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static struct stm32_tickless_s g_tickless; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: stm32_oneshot_handler - * - * Description: - * Called when the one shot timer expires - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - * Assumptions: - * Called early in the initialization sequence before any special - * concurrency protections are required. - * - ****************************************************************************/ - -static void stm32_oneshot_handler(void *arg) -{ - tmrinfo("Expired...\n"); - nxsched_process_timer(); -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: up_timer_initialize - * - * Description: - * Initializes all platform-specific timer facilities. This function is - * called early in the initialization sequence by up_initialize(). - * On return, the current up-time should be available from - * up_timer_gettime() and the interval timer is ready for use (but not - * actively timing. - * - * Provided by platform-specific code and called from the architecture- - * specific logic. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - * Assumptions: - * Called early in the initialization sequence before any special - * concurrency protections are required. - * - ****************************************************************************/ - -void up_timer_initialize(void) -{ -#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP - uint64_t max_delay; -#endif - int ret; - - /* Initialize the one-shot timer */ - - ret = stm32_oneshot_initialize(&g_tickless.oneshot, - CONFIG_STM32_TICKLESS_ONESHOT, - CONFIG_USEC_PER_TICK); - if (ret < 0) - { - tmrerr("ERROR: stm32_oneshot_initialize failed\n"); - DEBUGPANIC(); - } - -#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP - /* Get the maximum delay of the one-shot timer in microseconds */ - - ret = stm32_oneshot_max_delay(&g_tickless.oneshot, &max_delay); - if (ret < 0) - { - tmrerr("ERROR: stm32_oneshot_max_delay failed\n"); - DEBUGPANIC(); - } - - /* Convert this to configured clock ticks for use by the OS timer logic */ - - max_delay /= CONFIG_USEC_PER_TICK; - if (max_delay > UINT32_MAX) - { - g_oneshot_maxticks = UINT32_MAX; - } - else - { - g_oneshot_maxticks = max_delay; - } -#endif - - /* Initialize the free-running timer */ - - ret = stm32_freerun_initialize(&g_tickless.freerun, - CONFIG_STM32_TICKLESS_FREERUN, - CONFIG_USEC_PER_TICK); - if (ret < 0) - { - tmrerr("ERROR: stm32_freerun_initialize failed\n"); - DEBUGPANIC(); - } -} - -/**************************************************************************** - * Name: up_timer_gettime - * - * Description: - * Return the elapsed time since power-up (or, more correctly, since - * up_timer_initialize() was called). This function is functionally - * equivalent to: - * - * int clock_gettime(clockid_t clockid, struct timespec *ts); - * - * when clockid is CLOCK_MONOTONIC. - * - * This function provides the basis for reporting the current time and - * also is used to eliminate error build-up from small errors in interval - * time calculations. - * - * Provided by platform-specific code and called from the RTOS base code. - * - * Input Parameters: - * ts - Provides the location in which to return the up-time. - * - * Returned Value: - * Zero (OK) is returned on success; a negated errno value is returned on - * any failure. - * - * Assumptions: - * Called from the normal tasking context. The implementation must - * provide whatever mutual exclusion is necessary for correct operation. - * This can include disabling interrupts in order to assure atomic register - * operations. - * - ****************************************************************************/ - -int up_timer_gettime(struct timespec *ts) -{ - return stm32_freerun_counter(&g_tickless.freerun, ts); -} - -/**************************************************************************** - * Name: up_timer_cancel - * - * Description: - * Cancel the interval timer and return the time remaining on the timer. - * These two steps need to be as nearly atomic as possible. - * nxsched_process_timer() will not be called unless the timer is - * restarted with up_timer_start(). - * - * If, as a race condition, the timer has already expired when this - * function is called, then that pending interrupt must be cleared so - * that up_timer_start() and the remaining time of zero should be - * returned. - * - * NOTE: This function may execute at a high rate with no timer running (as - * when pre-emption is enabled and disabled). - * - * Provided by platform-specific code and called from the RTOS base code. - * - * Input Parameters: - * ts - Location to return the remaining time. Zero should be returned - * if the timer is not active. ts may be zero in which case the - * time remaining is not returned. - * - * Returned Value: - * Zero (OK) is returned on success. A call to up_timer_cancel() when - * the timer is not active should also return success; a negated errno - * value is returned on any failure. - * - * Assumptions: - * May be called from interrupt level handling or from the normal tasking - * level. Interrupts may need to be disabled internally to assure - * non-reentrancy. - * - ****************************************************************************/ - -int up_timer_cancel(struct timespec *ts) -{ - return stm32_oneshot_cancel(&g_tickless.oneshot, ts); -} - -/**************************************************************************** - * Name: up_timer_start - * - * Description: - * Start the interval timer. nxsched_process_timer() will be - * called at the completion of the timeout (unless up_timer_cancel - * is called to stop the timing. - * - * Provided by platform-specific code and called from the RTOS base code. - * - * Input Parameters: - * ts - Provides the time interval until nxsched_process_timer() is - * called. - * - * Returned Value: - * Zero (OK) is returned on success; a negated errno value is returned on - * any failure. - * - * Assumptions: - * May be called from interrupt level handling or from the normal tasking - * level. Interrupts may need to be disabled internally to assure - * non-reentrancy. - * - ****************************************************************************/ - -int up_timer_start(const struct timespec *ts) -{ - return stm32_oneshot_start(&g_tickless.oneshot, - stm32_oneshot_handler, NULL, ts); -} -#endif /* CONFIG_SCHED_TICKLESS */
