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,
|
||||
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,
|
||||
uint32_t freq);
|
||||
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 =
|
||||
{
|
||||
.enable = stm32l4_tim_enable,
|
||||
.disable = stm32l4_tim_disable,
|
||||
.setmode = stm32l4_tim_setmode,
|
||||
.setfreq = stm32l4_tim_setfreq,
|
||||
.setclock = stm32l4_tim_setclock,
|
||||
.getclock = stm32l4_tim_getclock,
|
||||
.setperiod = stm32l4_tim_setperiod,
|
||||
@ -312,8 +317,6 @@ static const struct stm32l4_tim_ops_s stm32l4_tim_ops =
|
||||
.disableint = stm32l4_tim_disableint,
|
||||
.ackint = stm32l4_tim_ackint,
|
||||
.checkint = stm32l4_tim_checkint,
|
||||
.enable = stm32l4_tim_enable,
|
||||
.disable = stm32l4_tim_disable,
|
||||
.dump_regs = stm32l4_tim_dumpregs,
|
||||
};
|
||||
|
||||
@ -689,6 +692,166 @@ static int stm32l4_tim_setmode(FAR struct stm32l4_tim_dev_s *dev,
|
||||
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
|
||||
************************************************************************************/
|
||||
|
@ -58,6 +58,7 @@
|
||||
/* Helpers *******************************************************************/
|
||||
|
||||
#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_GETCLOCK(d) ((d)->ops->getclock(d))
|
||||
#define STM32L4_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period))
|
||||
@ -173,8 +174,11 @@ struct stm32l4_tim_ops_s
|
||||
{
|
||||
/* 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,
|
||||
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);
|
||||
uint32_t (*getclock)(FAR struct stm32l4_tim_dev_s *dev);
|
||||
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 (*ackint)(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);
|
||||
};
|
||||
|
||||
|
@ -359,7 +359,6 @@ static int spwm_tim6_setup(FAR struct spwm_s *spwm)
|
||||
{
|
||||
FAR struct stm32l4_tim_dev_s *tim = NULL;
|
||||
uint64_t freq = 0;
|
||||
uint32_t per = 0;
|
||||
int ret = OK;
|
||||
|
||||
/* Get TIM6 interface */
|
||||
@ -380,18 +379,8 @@ static int spwm_tim6_setup(FAR struct spwm_s *spwm)
|
||||
*/
|
||||
|
||||
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_SETCLOCK(tim, BOARD_TIM6_FREQUENCY);
|
||||
STM32L4_TIM_SETPERIOD(tim, per);
|
||||
STM32L4_TIM_SETFREQ(tim, freq);
|
||||
STM32L4_TIM_ENABLE(tim);
|
||||
|
||||
/* Attach TIM6 ram vector */
|
||||
|
Loading…
Reference in New Issue
Block a user