Add fuction to set timer frequency.
This commit is contained in:
parent
3f6157001a
commit
e73e03a33f
@ -270,6 +270,8 @@ static void stm32l4_tim_dumpregs(FAR struct stm32l4_tim_dev_s *dev);
|
|||||||
|
|
||||||
static int stm32l4_tim_setmode(FAR struct stm32l4_tim_dev_s *dev,
|
static int stm32l4_tim_setmode(FAR struct stm32l4_tim_dev_s *dev,
|
||||||
enum stm32l4_tim_mode_e mode);
|
enum stm32l4_tim_mode_e mode);
|
||||||
|
static int stm32l4_tim_setfreq(FAR struct stm32l4_tim_dev_s *dev,
|
||||||
|
uint32_t freq);
|
||||||
static int stm32l4_tim_setclock(FAR struct stm32l4_tim_dev_s *dev,
|
static int stm32l4_tim_setclock(FAR struct stm32l4_tim_dev_s *dev,
|
||||||
uint32_t freq);
|
uint32_t freq);
|
||||||
static uint32_t stm32l4_tim_getclock(FAR struct stm32l4_tim_dev_s *dev);
|
static uint32_t stm32l4_tim_getclock(FAR struct stm32l4_tim_dev_s *dev);
|
||||||
@ -298,7 +300,10 @@ static int stm32l4_tim_checkint(FAR struct stm32l4_tim_dev_s *dev, int source);
|
|||||||
|
|
||||||
static const struct stm32l4_tim_ops_s stm32l4_tim_ops =
|
static const struct stm32l4_tim_ops_s stm32l4_tim_ops =
|
||||||
{
|
{
|
||||||
|
.enable = stm32l4_tim_enable,
|
||||||
|
.disable = stm32l4_tim_disable,
|
||||||
.setmode = stm32l4_tim_setmode,
|
.setmode = stm32l4_tim_setmode,
|
||||||
|
.setfreq = stm32l4_tim_setfreq,
|
||||||
.setclock = stm32l4_tim_setclock,
|
.setclock = stm32l4_tim_setclock,
|
||||||
.getclock = stm32l4_tim_getclock,
|
.getclock = stm32l4_tim_getclock,
|
||||||
.setperiod = stm32l4_tim_setperiod,
|
.setperiod = stm32l4_tim_setperiod,
|
||||||
@ -312,8 +317,6 @@ static const struct stm32l4_tim_ops_s stm32l4_tim_ops =
|
|||||||
.disableint = stm32l4_tim_disableint,
|
.disableint = stm32l4_tim_disableint,
|
||||||
.ackint = stm32l4_tim_ackint,
|
.ackint = stm32l4_tim_ackint,
|
||||||
.checkint = stm32l4_tim_checkint,
|
.checkint = stm32l4_tim_checkint,
|
||||||
.enable = stm32l4_tim_enable,
|
|
||||||
.disable = stm32l4_tim_disable,
|
|
||||||
.dump_regs = stm32l4_tim_dumpregs,
|
.dump_regs = stm32l4_tim_dumpregs,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -689,6 +692,166 @@ static int stm32l4_tim_setmode(FAR struct stm32l4_tim_dev_s *dev,
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: stm32l4_tim_setfreq
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static int stm32l4_tim_setfreq(FAR struct stm32l4_tim_dev_s *dev,
|
||||||
|
uint32_t freq)
|
||||||
|
{
|
||||||
|
uint32_t freqin;
|
||||||
|
int prescaler;
|
||||||
|
uint32_t reload;
|
||||||
|
uint32_t timclk;
|
||||||
|
|
||||||
|
DEBUGASSERT(dev != NULL);
|
||||||
|
|
||||||
|
/* Disable Timer? */
|
||||||
|
|
||||||
|
if (freq == 0)
|
||||||
|
{
|
||||||
|
stm32l4_tim_disable(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the input clock frequency for this timer. These vary with
|
||||||
|
* different timer clock sources, MCU-specific timer configuration, and
|
||||||
|
* board-specific clock configuration. The correct input clock frequency
|
||||||
|
* must be defined in the board.h header file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (((struct stm32l4_tim_priv_s *)dev)->base)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_STM32L4_TIM1
|
||||||
|
case STM32L4_TIM1_BASE:
|
||||||
|
freqin = BOARD_TIM1_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM2
|
||||||
|
case STM32L4_TIM2_BASE:
|
||||||
|
freqin = BOARD_TIM2_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM3
|
||||||
|
case STM32L4_TIM3_BASE:
|
||||||
|
freqin = BOARD_TIM3_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM4
|
||||||
|
case STM32L4_TIM4_BASE:
|
||||||
|
freqin = BOARD_TIM4_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM5
|
||||||
|
case STM32L4_TIM5_BASE:
|
||||||
|
freqin = BOARD_TIM5_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM6
|
||||||
|
case STM32L4_TIM6_BASE:
|
||||||
|
freqin = BOARD_TIM6_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM7
|
||||||
|
case STM32L4_TIM7_BASE:
|
||||||
|
freqin = BOARD_TIM7_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM8
|
||||||
|
case STM32L4_TIM8_BASE:
|
||||||
|
freqin = BOARD_TIM8_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM15
|
||||||
|
case STM32L4_TIM15_BASE:
|
||||||
|
freqin = BOARD_TIM15_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_STM32L4_TIM16
|
||||||
|
case STM32L4_TIM16_BASE:
|
||||||
|
freqin = BOARD_TIM16_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32L4_TIM17
|
||||||
|
case STM32L4_TIM17_BASE:
|
||||||
|
freqin = BOARD_TIM17_FREQUENCY;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select a pre-scaler value for this timer using the input clock frequency.
|
||||||
|
*
|
||||||
|
* Calculate optimal values for the timer prescaler and for the timer
|
||||||
|
* reload register. If freq is the desired frequency, then
|
||||||
|
*
|
||||||
|
* reload = timclk / freq
|
||||||
|
* reload = (pclck / prescaler) / freq
|
||||||
|
*
|
||||||
|
* There are many solutions to do this, but the best solution will be the
|
||||||
|
* one that has the largest reload value and the smallest prescaler value.
|
||||||
|
* That is the solution that should give us the most accuracy in the timer
|
||||||
|
* control. Subject to:
|
||||||
|
*
|
||||||
|
* 0 <= prescaler <= 65536
|
||||||
|
* 1 <= reload <= 65535
|
||||||
|
*
|
||||||
|
* So ( prescaler = pclck / 65535 / freq ) would be optimal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
prescaler = (freqin / freq + 65534) / 65535;
|
||||||
|
|
||||||
|
/* We need to decrement value for '1', but only if that will not to
|
||||||
|
* cause underflow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (prescaler < 1)
|
||||||
|
{
|
||||||
|
awarn("WARNING: Prescaler underflowed.\n");
|
||||||
|
prescaler = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for overflow as well. */
|
||||||
|
|
||||||
|
if (prescaler > 65536)
|
||||||
|
{
|
||||||
|
awarn("WARNING: Prescaler overflowed.\n");
|
||||||
|
prescaler = 65536;
|
||||||
|
}
|
||||||
|
|
||||||
|
timclk = freqin / prescaler;
|
||||||
|
|
||||||
|
reload = timclk / freq;
|
||||||
|
if (reload < 1)
|
||||||
|
{
|
||||||
|
awarn("WARNING: Reload value underflowed.\n");
|
||||||
|
reload = 1;
|
||||||
|
}
|
||||||
|
else if (reload > 65535)
|
||||||
|
{
|
||||||
|
awarn("WARNING: Reload value overflowed.\n");
|
||||||
|
reload = 65535;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the reload and prescaler values */
|
||||||
|
|
||||||
|
stm32l4_putreg16(dev, STM32L4_GTIM_PSC_OFFSET, prescaler - 1);
|
||||||
|
stm32l4_putreg16(dev, STM32L4_GTIM_ARR_OFFSET, reload);
|
||||||
|
|
||||||
|
return (timclk / reload);
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: stm32l4_tim_setclock
|
* Name: stm32l4_tim_setclock
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
/* Helpers *******************************************************************/
|
/* Helpers *******************************************************************/
|
||||||
|
|
||||||
#define STM32L4_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode))
|
#define STM32L4_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode))
|
||||||
|
#define STM32L4_TIM_SETFREQ(d,freq) ((d)->ops->setfreq(d,freq))
|
||||||
#define STM32L4_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq))
|
#define STM32L4_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq))
|
||||||
#define STM32L4_TIM_GETCLOCK(d) ((d)->ops->getclock(d))
|
#define STM32L4_TIM_GETCLOCK(d) ((d)->ops->getclock(d))
|
||||||
#define STM32L4_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period))
|
#define STM32L4_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period))
|
||||||
@ -173,8 +174,11 @@ struct stm32l4_tim_ops_s
|
|||||||
{
|
{
|
||||||
/* Basic Timers */
|
/* Basic Timers */
|
||||||
|
|
||||||
|
void (*enable)(FAR struct stm32l4_tim_dev_s *dev);
|
||||||
|
void (*disable)(FAR struct stm32l4_tim_dev_s *dev);
|
||||||
int (*setmode)(FAR struct stm32l4_tim_dev_s *dev,
|
int (*setmode)(FAR struct stm32l4_tim_dev_s *dev,
|
||||||
enum stm32l4_tim_mode_e mode);
|
enum stm32l4_tim_mode_e mode);
|
||||||
|
int (*setfreq)(FAR struct stm32l4_tim_dev_s *dev, uint32_t freq);
|
||||||
int (*setclock)(FAR struct stm32l4_tim_dev_s *dev, uint32_t freq);
|
int (*setclock)(FAR struct stm32l4_tim_dev_s *dev, uint32_t freq);
|
||||||
uint32_t (*getclock)(FAR struct stm32l4_tim_dev_s *dev);
|
uint32_t (*getclock)(FAR struct stm32l4_tim_dev_s *dev);
|
||||||
void (*setperiod)(FAR struct stm32l4_tim_dev_s *dev, uint32_t period);
|
void (*setperiod)(FAR struct stm32l4_tim_dev_s *dev, uint32_t period);
|
||||||
@ -197,8 +201,9 @@ struct stm32l4_tim_ops_s
|
|||||||
void (*disableint)(FAR struct stm32l4_tim_dev_s *dev, int source);
|
void (*disableint)(FAR struct stm32l4_tim_dev_s *dev, int source);
|
||||||
void (*ackint)(FAR struct stm32l4_tim_dev_s *dev, int source);
|
void (*ackint)(FAR struct stm32l4_tim_dev_s *dev, int source);
|
||||||
int (*checkint)(FAR struct stm32l4_tim_dev_s *dev, int source);
|
int (*checkint)(FAR struct stm32l4_tim_dev_s *dev, int source);
|
||||||
void (*enable)(FAR struct stm32l4_tim_dev_s *dev);
|
|
||||||
void (*disable)(FAR struct stm32l4_tim_dev_s *dev);
|
/* Debug */
|
||||||
|
|
||||||
void (*dump_regs)(FAR struct stm32l4_tim_dev_s *dev);
|
void (*dump_regs)(FAR struct stm32l4_tim_dev_s *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -359,7 +359,6 @@ static int spwm_tim6_setup(FAR struct spwm_s *spwm)
|
|||||||
{
|
{
|
||||||
FAR struct stm32l4_tim_dev_s *tim = NULL;
|
FAR struct stm32l4_tim_dev_s *tim = NULL;
|
||||||
uint64_t freq = 0;
|
uint64_t freq = 0;
|
||||||
uint32_t per = 0;
|
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
/* Get TIM6 interface */
|
/* Get TIM6 interface */
|
||||||
@ -380,18 +379,8 @@ static int spwm_tim6_setup(FAR struct spwm_s *spwm)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
freq = spwm->samples * spwm->waveform_freq;
|
freq = spwm->samples * spwm->waveform_freq;
|
||||||
per = BOARD_TIM6_FREQUENCY / freq;
|
|
||||||
if (per > 0xffff)
|
|
||||||
{
|
|
||||||
printf("ERROR: can not achieve TIM6 frequency\n");
|
|
||||||
ret = -1;
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: TIM_SETFREQ */
|
STM32L4_TIM_SETFREQ(tim, freq);
|
||||||
|
|
||||||
STM32L4_TIM_SETCLOCK(tim, BOARD_TIM6_FREQUENCY);
|
|
||||||
STM32L4_TIM_SETPERIOD(tim, per);
|
|
||||||
STM32L4_TIM_ENABLE(tim);
|
STM32L4_TIM_ENABLE(tim);
|
||||||
|
|
||||||
/* Attach TIM6 ram vector */
|
/* Attach TIM6 ram vector */
|
||||||
|
Loading…
Reference in New Issue
Block a user