diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index b6c04586498..8e9c2d4e494 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -2624,6 +2624,24 @@ config STM32_FREERUN bool default y +config STM32_TICKLESS_ONESHOT + int "Tickless one-shot timer channel" + default 2 + range 1 14 + depends on STM32_ONESHOT + ---help--- + If the Tickless OS feature is enabled, the one clock must be + assigned to provided the one-shot timer needed by the OS. + +config STM32_TICKLESS_FREERUN + int "Tickless free-running timer channel" + default 5 + range 1 14 + depends on STM32_FREERUN + ---help--- + If the Tickless OS feature is enabled, the one clock must be + assigned to provided the free-running timer needed by the OS. + endif # SCHED_TICKLESS if !SCHED_TICKLESS @@ -2644,23 +2662,15 @@ config STM32_FREERUN endif # !SCHED_TICKLESS -config STM32_TICKLESS_ONESHOT - int "Tickless one-shot timer channel" - default 2 - range 1 14 - depends on STM32_ONESHOT +config STM32_ONESHOT_MAXTIMERS + int "Maximum number of oneshot timers" + default 1 + range 1 8 ---help--- - If the Tickless OS feature is enabled, the one clock must be - assigned to provided the one-shot timer needed by the OS. - -config STM32_TICKLESS_FREERUN - int "Tickless free-running timer channel" - default 5 - range 1 14 - depends on STM32_FREERUN - ---help--- - If the Tickless OS feature is enabled, the one clock must be - assigned to provided the free-running timer needed by the OS. + Determines the maximum number of oneshot timers that can be + supported. This setting pre-allocates some minimal support for each + of the timers and places an upper limit on the number of oneshot + timers that you can use. config STM32_TIM1_PWM bool "TIM1 PWM" diff --git a/arch/arm/src/stm32/stm32_oneshot.c b/arch/arm/src/stm32/stm32_oneshot.c index a47307e7212..20607f3b019 100644 --- a/arch/arm/src/stm32/stm32_oneshot.c +++ b/arch/arm/src/stm32/stm32_oneshot.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -54,10 +55,66 @@ #ifdef CONFIG_STM32_ONESHOT /**************************************************************************** - * Private Date + * Private Function Prototypes ****************************************************************************/ -static struct stm32_oneshot_s *g_oneshot; +static int stm32_oneshot_handler(struct stm32_oneshot_s *oneshot); +static int stm32_oneshot1_handler(int irq, void *context); +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 1 +static int stm32_oneshot2_handler(int irq, void *context); +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 2 +static int stm32_oneshot3_handler(int irq, void *context); +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 3 +static int stm32_oneshot4_handler(int irq, void *context); +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 4 +static int stm32_oneshot5_handler(int irq, void *context); +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 5 +static int stm32_oneshot6_handler(int irq, void *context); +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 6 +static int stm32_oneshot7_handler(int irq, void *context); +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 7 +static int stm32_oneshot8_handler(int irq, void *context); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct stm32_oneshot_s *g_oneshot[CONFIG_STM32_ONESHOT_MAXTIMERS]; + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 1 +static const xcpt_t g_callbacks[CONFIG_STM32_ONESHOT_MAXTIMERS] = +{ + stm32_oneshot1_handler, +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 1 + stm32_oneshot2_handler, +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 2 + stm32_oneshot3_handler, +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 3 + stm32_oneshot4_handler, +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 4 + stm32_oneshot5_handler, +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 5 + stm32_oneshot5_handler, +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 6 + stm32_oneshot7_handler, +#endif +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 7 + stm32_oneshot8_handler, +#endif +}; +#endif /**************************************************************************** * Private Functions @@ -67,24 +124,20 @@ static struct stm32_oneshot_s *g_oneshot; * Name: stm32_oneshot_handler * * Description: - * Timer interrupt callback. When the oneshot timer interrupt expires, - * this function will be called. It will forward the call to the next - * level up. + * Common timer interrupt callback. When any oneshot timer interrupt + * expires, this function will be called. It will forward the call to + * the next level up. * * Input Parameters: - * tch - The handle that represents the timer state - * arg - An opaque argument provided when the interrupt was registered - * sr - The value of the timer interrupt status register at the time - * that the interrupt occurred. + * oneshot - The state associated with the expired timer * * Returned Value: - * None + * Always returns OK * ****************************************************************************/ -static int stm32_oneshot_handler(int irq, void *context) +static int stm32_oneshot_handler(struct stm32_oneshot_s *oneshot) { - struct stm32_oneshot_s *oneshot = g_oneshot; oneshot_handler_t oneshot_handler; void *oneshot_arg; @@ -115,6 +168,137 @@ static int stm32_oneshot_handler(int irq, void *context) return OK; } +/**************************************************************************** + * Name: stm32_oneshot[N]_handler + * + * Description: + * Timer interrupt callbacks. When a oneshot timer interrupt expires, + * one of these functions will be called. These functions will forward + * the call to the nextlevel up. + * + * Input Parameters: + * Standard interrupt handler arguments. + * + * Returned Value: + * Always returns OK + * + ****************************************************************************/ + +static int stm32_oneshot1_handler(int irq, void *context) +{ + DEBUGASSERT(g_oneshot[0] != NULL); + return stm32_oneshot_handler(g_oneshot[0]); +} + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 1 +static int stm32_oneshot2_handler(int irq, void *context) +{ + DEBUGASSERT(g_oneshot[1] != NULL); + return stm32_oneshot_handler(g_oneshot[1]); +} +#endif + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 2 +static int stm32_oneshot3_handler(int irq, void *context) +{ + DEBUGASSERT(g_oneshot[2] != NULL); + return stm32_oneshot_handler(g_oneshot[2]); +} +#endif + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 3 +static int stm32_oneshot4_handler(int irq, void *context) +{ + DEBUGASSERT(g_oneshot[3] != NULL); + return stm32_oneshot_handler(g_oneshot[3]); +} +#endif + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 4 +static int stm32_oneshot5_handler(int irq, void *context) +{ + DEBUGASSERT(g_oneshot[4] != NULL); + return stm32_oneshot_handler(g_oneshot[4]); +} +#endif + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 5 +static int stm32_oneshot5_handler(int irq, void *context) +{ + DEBUGASSERT(g_oneshot[6] != NULL); + return stm32_oneshot_handler(g_oneshot[5]); +} +#endif + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 6 +static int stm32_oneshot7_handler(int irq, void *context) +{ + DEBUGASSERT(g_oneshot[7] != NULL); + return stm32_oneshot_handler(g_oneshot[6]); +} +#endif + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 7 +static int stm32_oneshot8_handler(int irq, void *context) +{ + DEBUGASSERT(g_oneshot[0] != NULL); + return stm32_oneshot_handler(g_oneshot[7]); +} +#endif + +/**************************************************************************** + * Name: stm32_allocate_handler + * + * Description: + * Allocate a timer callback handler for the oneshot instance. + * + * Input Parameters: + * oneshot - The state instance the new oneshot timer + * + * Returned Value: + * Returns zero (OK) on success. This can only fail if the number of + * timers exceeds CONFIG_STM32_ONESHOT_MAXTIMERS. + * + ****************************************************************************/ + +static inline int stm32_allocate_handler(struct stm32_oneshot_s *oneshot) +{ +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 1 + int ret = -ENOMEM; + int i; + + /* Search for an unused handler */ + + sched_lock(); + for (i = 0; i < CONFIG_STM32_ONESHOT_MAXTIMERS; i++) + { + /* Is this handler available? */ + + if (g_oneshot[i] == NULL) + { + /* Yes... assign it to this oneshot */ + + g_oneshot[i] = oneshot; + oneshot->cbndx = i; + ret = OK; + break; + } + } + + sched_unlock(); + return ret; + +#else + if (g_oneshot[0] == NULL) + { + g_oneshot[0] = oneshot; + return OK; + } + + return -ENOMEM; +#endif +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -139,7 +323,7 @@ static int stm32_oneshot_handler(int irq, void *context) ****************************************************************************/ int stm32_oneshot_initialize(struct stm32_oneshot_s *oneshot, int chan, - uint16_t resolution) + uint16_t resolution) { uint32_t frequency; @@ -160,17 +344,16 @@ int stm32_oneshot_initialize(struct stm32_oneshot_s *oneshot, int chan, STM32_TIM_SETCLOCK(oneshot->tch, frequency); - /* Initialize the remaining fields in the state structure and return - * success. - */ + /* Initialize the remaining fields in the state structure. */ oneshot->chan = chan; oneshot->running = false; oneshot->handler = NULL; oneshot->arg = NULL; - g_oneshot = oneshot; - return OK; + /* Assign a callback handler to the oneshot */ + + return stm32_allocate_handler(oneshot); } /**************************************************************************** @@ -259,7 +442,11 @@ int stm32_oneshot_start(struct stm32_oneshot_s *oneshot, /* Set up to receive the callback when the interrupt occurs */ - STM32_TIM_SETISR(oneshot->tch, stm32_oneshot_handler, 0); +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 1 + STM32_TIM_SETISR(oneshot->tch, g_callbacks[oneshot->cbndx], 0); +#else + STM32_TIM_SETISR(oneshot->tch, stm32_oneshot1_handler, 0); +#endif /* Set timer period */ diff --git a/arch/arm/src/stm32/stm32_oneshot.h b/arch/arm/src/stm32/stm32_oneshot.h index bff21319393..2762006edff 100644 --- a/arch/arm/src/stm32/stm32_oneshot.h +++ b/arch/arm/src/stm32/stm32_oneshot.h @@ -45,10 +45,28 @@ #include #include +#include + #include "stm32_tim.h" #ifdef CONFIG_STM32_ONESHOT +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if !defined(CONFIG_STM32_ONESHOT_MAXTIMERS) || \ + CONFIG_STM32_ONESHOT_MAXTIMERS < 1 +# undef CONFIG_STM32_ONESHOT_MAXTIMERS +# define CONFIG_STM32_ONESHOT_MAXTIMERS 1 +#endif + +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 8 +# warning Additional logic required to handle more than 8 timers +# undef CONFIG_STM32_ONESHOT_MAXTIMERS +# define CONFIG_STM32_ONESHOT_MAXTIMERS 8 +#endif + /**************************************************************************** * Public Types ****************************************************************************/ @@ -70,6 +88,9 @@ typedef void (*oneshot_handler_t)(void *arg); struct stm32_oneshot_s { uint8_t chan; /* The timer/counter in use */ +#if CONFIG_STM32_ONESHOT_MAXTIMERS > 1 + uint8_t cbndx; /* Timer callback handler index*/ +#endif volatile bool running; /* True: the timer is running */ FAR struct stm32_tim_dev_s *tch; /* Pointer returned by * stm32_tim_init() */