STM32L4: Port fix for multiple oneshot timers from STM32. Also fixes a few issues with original STM32 implementation.

This commit is contained in:
Gregory Nutt 2017-01-18 10:45:22 -06:00
parent 0069761d6f
commit b05f928143
6 changed files with 259 additions and 39 deletions

View File

@ -2666,6 +2666,7 @@ config STM32_ONESHOT_MAXTIMERS
int "Maximum number of oneshot timers" int "Maximum number of oneshot timers"
default 1 default 1
range 1 8 range 1 8
depends on STM32_ONESHOT
---help--- ---help---
Determines the maximum number of oneshot timers that can be Determines the maximum number of oneshot timers that can be
supported. This setting pre-allocates some minimal support for each supported. This setting pre-allocates some minimal support for each

View File

@ -105,7 +105,7 @@ static const xcpt_t g_callbacks[CONFIG_STM32_ONESHOT_MAXTIMERS] =
stm32_oneshot5_handler, stm32_oneshot5_handler,
#endif #endif
#if CONFIG_STM32_ONESHOT_MAXTIMERS > 5 #if CONFIG_STM32_ONESHOT_MAXTIMERS > 5
stm32_oneshot5_handler, stm32_oneshot6_handler,
#endif #endif
#if CONFIG_STM32_ONESHOT_MAXTIMERS > 6 #if CONFIG_STM32_ONESHOT_MAXTIMERS > 6
stm32_oneshot7_handler, stm32_oneshot7_handler,
@ -223,7 +223,7 @@ static int stm32_oneshot5_handler(int irq, void *context)
#endif #endif
#if CONFIG_STM32_ONESHOT_MAXTIMERS > 5 #if CONFIG_STM32_ONESHOT_MAXTIMERS > 5
static int stm32_oneshot5_handler(int irq, void *context) static int stm32_oneshot6_handler(int irq, void *context)
{ {
DEBUGASSERT(g_oneshot[6] != NULL); DEBUGASSERT(g_oneshot[6] != NULL);
return stm32_oneshot_handler(g_oneshot[5]); return stm32_oneshot_handler(g_oneshot[5]);

View File

@ -89,7 +89,7 @@ struct stm32_oneshot_s
{ {
uint8_t chan; /* The timer/counter in use */ uint8_t chan; /* The timer/counter in use */
#if CONFIG_STM32_ONESHOT_MAXTIMERS > 1 #if CONFIG_STM32_ONESHOT_MAXTIMERS > 1
uint8_t cbndx; /* Timer callback handler index*/ uint8_t cbndx; /* Timer callback handler index */
#endif #endif
volatile bool running; /* True: the timer is running */ volatile bool running; /* True: the timer is running */
FAR struct stm32_tim_dev_s *tch; /* Pointer returned by FAR struct stm32_tim_dev_s *tch; /* Pointer returned by

View File

@ -659,6 +659,24 @@ config STM32L4_FREERUN
bool bool
default y default y
config STM32L4_TICKLESS_ONESHOT
int "Tickless one-shot timer channel"
default 2
range 1 8
depends on STM32L4_ONESHOT
---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 STM32L4_TICKLESS_FREERUN
int "Tickless free-running timer channel"
default 5
range 1 8
depends on STM32L4_FREERUN
---help---
If the Tickless OS feature is enabled, then one clock must be
assigned to provide the free-running timer needed by the OS.
endif # SCHED_TICKLESS endif # SCHED_TICKLESS
if !SCHED_TICKLESS if !SCHED_TICKLESS
@ -679,23 +697,16 @@ config STM32L4_FREERUN
endif # !SCHED_TICKLESS endif # !SCHED_TICKLESS
config STM32L4_TICKLESS_ONESHOT config STM32L4_ONESHOT_MAXTIMERS
int "Tickless one-shot timer channel" int "Maximum number of oneshot timers"
default 2 default 1
range 1 8 range 1 8
depends on STM32L4_ONESHOT depends on STM32L4_ONESHOT
---help--- ---help---
If the Tickless OS feature is enabled, then one clock must be Determines the maximum number of oneshot timers that can be
assigned to provide the one-shot timer needed by the OS. supported. This setting pre-allocates some minimal support for each
of the timers and places an upper limit on the number of oneshot
config STM32L4_TICKLESS_FREERUN timers that you can use.
int "Tickless free-running timer channel"
default 5
range 1 8
depends on STM32L4_FREERUN
---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 STM32L4_TIM1_PWM config STM32L4_TIM1_PWM
bool "TIM1 PWM" bool "TIM1 PWM"

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/stm32l4/stm32l4_oneshot.c * arch/arm/src/stm32l4/stm32l4_oneshot.c
* *
* Copyright (C) 2016 Gregory Nutt. All rights reserved. * Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* dev@ziggurat29.com * dev@ziggurat29.com
* *
@ -43,6 +43,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <sched.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
@ -55,10 +56,66 @@
#ifdef CONFIG_STM32L4_ONESHOT #ifdef CONFIG_STM32L4_ONESHOT
/**************************************************************************** /****************************************************************************
* Private Date * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static struct stm32l4_oneshot_s *g_oneshot; static int stm32l4_oneshot_handler(struct stm32l4_oneshot_s *oneshot);
static int stm32l4_oneshot1_handler(int irq, void *context);
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 1
static int stm32l4_oneshot2_handler(int irq, void *context);
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 2
static int stm32l4_oneshot3_handler(int irq, void *context);
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 3
static int stm32l4_oneshot4_handler(int irq, void *context);
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 4
static int stm32l4_oneshot5_handler(int irq, void *context);
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 5
static int stm32l4_oneshot6_handler(int irq, void *context);
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 6
static int stm32l4_oneshot7_handler(int irq, void *context);
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 7
static int stm32l4_oneshot8_handler(int irq, void *context);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
static struct stm32l4_oneshot_s *g_oneshot[CONFIG_STM32L4_ONESHOT_MAXTIMERS];
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 1
static const xcpt_t g_callbacks[CONFIG_STM32L4_ONESHOT_MAXTIMERS] =
{
stm32l4_oneshot1_handler,
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 1
stm32l4_oneshot2_handler,
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 2
stm32l4_oneshot3_handler,
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 3
stm32l4_oneshot4_handler,
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 4
stm32l4_oneshot5_handler,
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 5
stm32l4_oneshot6_handler,
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 6
stm32l4_oneshot7_handler,
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 7
stm32l4_oneshot8_handler,
#endif
};
#endif
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@ -68,24 +125,20 @@ static struct stm32l4_oneshot_s *g_oneshot;
* Name: stm32l4_oneshot_handler * Name: stm32l4_oneshot_handler
* *
* Description: * Description:
* Timer interrupt callback. When the oneshot timer interrupt expires, * Common timer interrupt callback. When any oneshot timer interrupt
* this function will be called. It will forward the call to the next * expires, this function will be called. It will forward the call to
* level up. * the next level up.
* *
* Input Parameters: * Input Parameters:
* tch - The handle that represents the timer state * oneshot - The state associated with the expired timer
* 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.
* *
* Returned Value: * Returned Value:
* None * Always returns OK
* *
****************************************************************************/ ****************************************************************************/
static int stm32l4_oneshot_handler(int irq, FAR void *context) static int stm32l4_oneshot_handler(struct stm32l4_oneshot_s *oneshot)
{ {
FAR struct stm32l4_oneshot_s *oneshot = g_oneshot;
oneshot_handler_t oneshot_handler; oneshot_handler_t oneshot_handler;
FAR void *oneshot_arg; FAR void *oneshot_arg;
@ -116,6 +169,137 @@ static int stm32l4_oneshot_handler(int irq, FAR void *context)
return OK; return OK;
} }
/****************************************************************************
* Name: stm32l4_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 stm32l4_oneshot1_handler(int irq, void *context)
{
DEBUGASSERT(g_oneshot[0] != NULL);
return stm32l4_oneshot_handler(g_oneshot[0]);
}
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 1
static int stm32l4_oneshot2_handler(int irq, void *context)
{
DEBUGASSERT(g_oneshot[1] != NULL);
return stm32l4_oneshot_handler(g_oneshot[1]);
}
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 2
static int stm32l4_oneshot3_handler(int irq, void *context)
{
DEBUGASSERT(g_oneshot[2] != NULL);
return stm32l4_oneshot_handler(g_oneshot[2]);
}
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 3
static int stm32l4_oneshot4_handler(int irq, void *context)
{
DEBUGASSERT(g_oneshot[3] != NULL);
return stm32l4_oneshot_handler(g_oneshot[3]);
}
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 4
static int stm32l4_oneshot5_handler(int irq, void *context)
{
DEBUGASSERT(g_oneshot[4] != NULL);
return stm32l4_oneshot_handler(g_oneshot[4]);
}
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 5
static int stm32l4_oneshot6_handler(int irq, void *context)
{
DEBUGASSERT(g_oneshot[6] != NULL);
return stm32l4_oneshot_handler(g_oneshot[5]);
}
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 6
static int stm32l4_oneshot7_handler(int irq, void *context)
{
DEBUGASSERT(g_oneshot[7] != NULL);
return stm32l4_oneshot_handler(g_oneshot[6]);
}
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 7
static int stm32l4_oneshot8_handler(int irq, void *context)
{
DEBUGASSERT(g_oneshot[0] != NULL);
return stm32l4_oneshot_handler(g_oneshot[7]);
}
#endif
/****************************************************************************
* Name: stm32l4_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_STM32L4_ONESHOT_MAXTIMERS.
*
****************************************************************************/
static inline int stm32l4_allocate_handler(struct stm32l4_oneshot_s *oneshot)
{
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 1
int ret = -ENOMEM;
int i;
/* Search for an unused handler */
sched_lock();
for (i = 0; i < CONFIG_STM32L4_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 * Public Functions
****************************************************************************/ ****************************************************************************/
@ -139,8 +323,8 @@ static int stm32l4_oneshot_handler(int irq, FAR void *context)
* *
****************************************************************************/ ****************************************************************************/
int stm32l4_oneshot_initialize(FAR struct stm32l4_oneshot_s *oneshot, int chan, int stm32l4_oneshot_initialize(FAR struct stm32l4_oneshot_s *oneshot,
uint16_t resolution) int chan, uint16_t resolution)
{ {
uint32_t frequency; uint32_t frequency;
@ -161,17 +345,16 @@ int stm32l4_oneshot_initialize(FAR struct stm32l4_oneshot_s *oneshot, int chan,
STM32L4_TIM_SETCLOCK(oneshot->tch, frequency); STM32L4_TIM_SETCLOCK(oneshot->tch, frequency);
/* Initialize the remaining fields in the state structure and return /* Initialize the remaining fields in the state structure. */
* success.
*/
oneshot->chan = chan; oneshot->chan = chan;
oneshot->running = false; oneshot->running = false;
oneshot->handler = NULL; oneshot->handler = NULL;
oneshot->arg = NULL; oneshot->arg = NULL;
g_oneshot = oneshot; /* Assign a callback handler to the oneshot */
return OK;
return stm32l4_allocate_handler(oneshot);
} }
/**************************************************************************** /****************************************************************************
@ -261,7 +444,11 @@ int stm32l4_oneshot_start(FAR struct stm32l4_oneshot_s *oneshot,
/* Set up to receive the callback when the interrupt occurs */ /* Set up to receive the callback when the interrupt occurs */
STM32L4_TIM_SETISR(oneshot->tch, stm32l4_oneshot_handler, 0); #if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 1
STM32L4_TIM_SETISR(oneshot->tch, g_callbacks[oneshot->cbndx], 0);
#else
STM32L4_TIM_SETISR(oneshot->tch, stm32l4_oneshot1_handler, 0);
#endif
/* Set timer period */ /* Set timer period */

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/stm32l4/stm32l4_oneshot.h * arch/arm/src/stm32l4/stm32l4_oneshot.h
* *
* Copyright (C) 2016 Gregory Nutt. All rights reserved. * Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* dev@ziggurat29.com * dev@ziggurat29.com
* *
@ -46,10 +46,28 @@
#include <stdint.h> #include <stdint.h>
#include <time.h> #include <time.h>
#include <nuttx/irq.h>
#include "stm32l4_tim.h" #include "stm32l4_tim.h"
#ifdef CONFIG_STM32L4_ONESHOT #ifdef CONFIG_STM32L4_ONESHOT
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if !defined(CONFIG_STM32L4_ONESHOT_MAXTIMERS) || \
CONFIG_STM32L4_ONESHOT_MAXTIMERS < 1
# undef CONFIG_STM32L4_ONESHOT_MAXTIMERS
# define CONFIG_STM32L4_ONESHOT_MAXTIMERS 1
#endif
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 8
# warning Additional logic required to handle more than 8 timers
# undef CONFIG_STM32L4_ONESHOT_MAXTIMERS
# define CONFIG_STM32L4_ONESHOT_MAXTIMERS 8
#endif
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
@ -71,6 +89,9 @@ typedef void (*oneshot_handler_t)(void *arg);
struct stm32l4_oneshot_s struct stm32l4_oneshot_s
{ {
uint8_t chan; /* The timer/counter in use */ uint8_t chan; /* The timer/counter in use */
#if CONFIG_STM32L4_ONESHOT_MAXTIMERS > 1
uint8_t cbndx; /* Timer callback handler index */
#endif
volatile bool running; /* True: the timer is running */ volatile bool running; /* True: the timer is running */
FAR struct stm32l4_tim_dev_s *tch; /* Pointer returned by FAR struct stm32l4_tim_dev_s *tch; /* Pointer returned by
* stm32l4_tim_init() */ * stm32l4_tim_init() */