STM32 TIM: Add method to get timer width. Freerun timer: Use timer width to get the correct clock rollover point.

This commit is contained in:
Gregory Nutt 2017-05-08 12:33:15 -06:00
parent c64983dbeb
commit aa11d637a8
4 changed files with 54 additions and 12 deletions

View File

@ -137,6 +137,7 @@ int stm32_freerun_initialize(struct stm32_freerun_s *freerun, int chan,
*/
freerun->chan = chan;
freerun->width = STM32_TIM_GETWIDTH(freerun->tch);
freerun->running = false;
#ifdef CONFIG_CLOCK_TIMEKEEPING
@ -153,7 +154,7 @@ int stm32_freerun_initialize(struct stm32_freerun_s *freerun, int chan,
/* Set timer period */
STM32_TIM_SETPERIOD(freerun->tch, UINT32_MAX);
STM32_TIM_SETPERIOD(freerun->tch, (uint32_t)((1ull << freerun->width) - 1));
/* Start the counter */
@ -248,7 +249,8 @@ int stm32_freerun_counter(struct stm32_freerun_s *freerun,
* usecs = (ticks * USEC_PER_SEC) / frequency;
*/
usec = ((((uint64_t)overflow << 32) + (uint64_t)counter) * USEC_PER_SEC) /
usec = ((((uint64_t)overflow << freerun->width) +
(uint64_t)counter) * USEC_PER_SEC) /
freerun->frequency;
/* And return the value of the timer */

View File

@ -63,6 +63,7 @@
struct stm32_freerun_s
{
uint8_t chan; /* The timer/counter in use */
uint8_t width; /* Width of timer (16- or 32-bits) */
bool running; /* True: the timer is running */
FAR struct stm32_tim_dev_s *tch; /* Handle returned by stm32_tim_init() */
uint32_t frequency;

View File

@ -334,22 +334,23 @@ static void stm32_tim_gpioconfig(uint32_t cfg, stm32_tim_channel_t mode);
/* Timer methods */
static int stm32_tim_setmode(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode);
static int stm32_tim_setclock(FAR struct stm32_tim_dev_s *dev, uint32_t freq);
static int stm32_tim_setmode(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode);
static int stm32_tim_setclock(FAR struct stm32_tim_dev_s *dev, uint32_t freq);
static void stm32_tim_setperiod(FAR struct stm32_tim_dev_s *dev,
uint32_t period);
static uint32_t stm32_tim_getcounter(FAR struct stm32_tim_dev_s *dev);
static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel,
stm32_tim_channel_t mode);
static int stm32_tim_setcompare(FAR struct stm32_tim_dev_s *dev, uint8_t channel,
uint32_t compare);
static int stm32_tim_getcapture(FAR struct stm32_tim_dev_s *dev, uint8_t channel);
static int stm32_tim_setisr(FAR struct stm32_tim_dev_s *dev, xcpt_t handler,
void *arg, int source);
static int stm32_tim_getwidth(FAR struct stm32_tim_dev_s *dev);
static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel,
stm32_tim_channel_t mode);
static int stm32_tim_setcompare(FAR struct stm32_tim_dev_s *dev, uint8_t channel,
uint32_t compare);
static int stm32_tim_getcapture(FAR struct stm32_tim_dev_s *dev, uint8_t channel);
static int stm32_tim_setisr(FAR struct stm32_tim_dev_s *dev, xcpt_t handler,
void *arg, int source);
static void stm32_tim_enableint(FAR struct stm32_tim_dev_s *dev, int source);
static void stm32_tim_disableint(FAR struct stm32_tim_dev_s *dev, int source);
static void stm32_tim_ackint(FAR struct stm32_tim_dev_s *dev, int source);
static int stm32_tim_checkint(FAR struct stm32_tim_dev_s *dev, int source);
static int stm32_tim_checkint(FAR struct stm32_tim_dev_s *dev, int source);
/************************************************************************************
* Private Data
@ -361,6 +362,7 @@ static const struct stm32_tim_ops_s stm32_tim_ops =
.setclock = stm32_tim_setclock,
.setperiod = stm32_tim_setperiod,
.getcounter = stm32_tim_getcounter,
.getwidth = stm32_tim_getwidth,
.setchannel = stm32_tim_setchannel,
.setcompare = stm32_tim_setcompare,
.getcapture = stm32_tim_getcapture,
@ -904,6 +906,41 @@ static uint32_t stm32_tim_getcounter(FAR struct stm32_tim_dev_s *dev)
return stm32_getreg32(dev, STM32_BTIM_CNT_OFFSET);
}
/************************************************************************************
* Name: stm32_tim_getwidth
************************************************************************************/
static int stm32_tim_getwidth(FAR struct stm32_tim_dev_s *dev)
{
/* Only TIM2 and TIM5 timers may be 32-bits in width
*
* Reference Table 2 of en.DM00042534.pdf
*/
switch (((struct stm32_tim_priv_s *)dev)->base)
{
/* TIM2 is 32-bits on all except F10x, L0x, and L1x lines */
#if defined(CONFIG_STM32_TIM2) && !defined(STM32_STM32F10XX) && \
!defined(STM32_STM32L15XX)
case STM32_TIM2_BASE:
return 32;
#endif
/* TIM5 is 32-bits on all except F10x lines */
#if defined(CONFIG_STM32_TIM5) && !defined(STM32_STM32F10XX)
case STM32_TIM5_BASE:
return 32;
#endif
/* All others are 16-bit times */
default:
return 16;
}
}
/************************************************************************************
* Name: stm32_tim_setchannel
************************************************************************************/

View File

@ -61,6 +61,7 @@
#define STM32_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq))
#define STM32_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period))
#define STM32_TIM_GETCOUNTER(d) ((d)->ops->getcounter(d))
#define STM32_TIM_GETWIDTH(d) ((d)->ops->getwidth(d))
#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode))
#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp))
#define STM32_TIM_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch))
@ -166,6 +167,7 @@ struct stm32_tim_ops_s
/* General and Advanced Timers Adds */
int (*getwidth)(FAR struct stm32_tim_dev_s *dev);
int (*setchannel)(FAR struct stm32_tim_dev_s *dev, uint8_t channel,
stm32_tim_channel_t mode);
int (*setcompare)(FAR struct stm32_tim_dev_s *dev, uint8_t channel,