Fix QEncoder driver, based on STM32L4 driver

This commit is contained in:
Alan Carvalho de Assis
2017-02-24 16:10:28 -06:00
committed by Gregory Nutt
parent 8ee2e8d8b0
commit 37298504e6
2 changed files with 61 additions and 75 deletions
+30 -24
View File
@@ -6768,11 +6768,12 @@ config STM32_TIM1_QE
if STM32_TIM1_QE
config STM32_TIM1_QECLKOUT
int "TIM1 output clock"
default 2800000
config STM32_TIM1_QEPSC
int "TIM1 pulse prescaler"
default 1
---help---
The output clock of TIM1.
This prescaler divides the number of recorded encoder pulses,
limiting the count rate at the expense of resolution.
endif
@@ -6785,11 +6786,12 @@ config STM32_TIM2_QE
if STM32_TIM2_QE
config STM32_TIM2_QECLKOUT
int "TIM2 output clock"
default 2800000
config STM32_TIM2_QEPSC
int "TIM2 pulse prescaler"
default 1
---help---
The output clock of TIM2.
This prescaler divides the number of recorded encoder pulses,
limiting the count rate at the expense of resolution.
endif
@@ -6802,11 +6804,12 @@ config STM32_TIM3_QE
if STM32_TIM3_QE
config STM32_TIM3_QECLKOUT
int "TIM3 output clock"
default 2800000
config STM32_TIM3_QEPSC
int "TIM3 pulse prescaler"
default 1
---help---
The output clock of TIM3.
This prescaler divides the number of recorded encoder pulses,
limiting the count rate at the expense of resolution.
endif
@@ -6819,11 +6822,12 @@ config STM32_TIM4_QE
if STM32_TIM4_QE
config STM32_TIM4_QECLKOUT
int "TIM4 output clock"
default 2800000
config STM32_TIM4_QEPSC
int "TIM4 pulse prescaler"
default 1
---help---
The output clock of TIM4.
This prescaler divides the number of recorded encoder pulses,
limiting the count rate at the expense of resolution.
endif
@@ -6836,11 +6840,12 @@ config STM32_TIM5_QE
if STM32_TIM5_QE
config STM32_TIM5_QECLKOUT
int "TIM5 output clock"
default 2800000
config STM32_TIM5_QEPSC
int "TIM5 pulse prescaler"
default 1
---help---
The output clock of TIM5.
This prescaler divides the number of recorded encoder pulses,
limiting the count rate at the expense of resolution.
endif
@@ -6853,11 +6858,12 @@ config STM32_TIM8_QE
if STM32_TIM8_QE
config STM32_TIM8_QECLKOUT
int "TIM8 output clock"
default 2800000
config STM32_TIM8_QEPSC
int "TIM8 pulse prescaler"
default 1
---help---
The output clock of TIM8.
This prescaler divides the number of recorded encoder pulses,
limiting the count rate at the expense of resolution.
endif
+31 -51
View File
@@ -65,32 +65,6 @@
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Clocking *************************************************************************/
/* The CLKOUT value should not exceed the CLKIN value */
#if defined(CONFIG_STM32_TIM1_QE) && CONFIG_STM32_TIM1_QECLKOUT > STM32_APB2_TIM1_CLKIN
# warning "CONFIG_STM32_TIM1_QECLKOUT exceeds STM32_APB2_TIM1_CLKIN"
#endif
#if defined(CONFIG_STM32_TIM2_QE) && CONFIG_STM32_TIM2_QECLKOUT > STM32_APB1_TIM2_CLKIN
# warning "CONFIG_STM32_TIM2_QECLKOUT exceeds STM32_APB2_TIM2_CLKIN"
#endif
#if defined(CONFIG_STM32_TIM3_QE) && CONFIG_STM32_TIM3_QECLKOUT > STM32_APB1_TIM3_CLKIN
# warning "CONFIG_STM32_TIM3_QECLKOUT exceeds STM32_APB2_TIM3_CLKIN"
#endif
#if defined(CONFIG_STM32_TIM4_QE) && CONFIG_STM32_TIM4_QECLKOUT > STM32_APB1_TIM4_CLKIN
# warning "CONFIG_STM32_TIM4_QECLKOUT exceeds STM32_APB2_TIM4_CLKIN"
#endif
#if defined(CONFIG_STM32_TIM5_QE) && CONFIG_STM32_TIM5_QECLKOUT > STM32_APB1_TIM5_CLKIN
# warning "CONFIG_STM32_TIM5_QECLKOUT exceeds STM32_APB2_TIM5_CLKIN"
#endif
#if defined(CONFIG_STM32_TIM8_QE) && CONFIG_STM32_TIM8_QECLKOUT > STM32_APB2_TIM8_CLKIN
# warning "CONFIG_STM32_TIM8_QECLKOUT exceeds STM32_APB2_TIM8_CLKIN"
#endif
/* Timers ***************************************************************************/
@@ -382,7 +356,7 @@ static const struct stm32_qeconfig_s g_tim1config =
.width = TIM1_BITWIDTH,
#endif
.base = STM32_TIM1_BASE,
.psc = (STM32_APB2_TIM1_CLKIN / CONFIG_STM32_TIM1_QECLKOUT) - 1,
.psc = CONFIG_STM32_TIM1_QEPSC,
.ti1cfg = GPIO_TIM1_CH1IN,
.ti2cfg = GPIO_TIM1_CH2IN,
#if TIM1_BITWIDTH == 16
@@ -408,7 +382,7 @@ static const struct stm32_qeconfig_s g_tim2config =
.width = TIM2_BITWIDTH,
#endif
.base = STM32_TIM2_BASE,
.psc = (STM32_APB1_TIM2_CLKIN / CONFIG_STM32_TIM2_QECLKOUT) - 1,
.psc = CONFIG_STM32_TIM2_QEPSC,
.ti1cfg = GPIO_TIM2_CH1IN,
.ti2cfg = GPIO_TIM2_CH2IN,
#if TIM2_BITWIDTH == 16
@@ -434,7 +408,7 @@ static const struct stm32_qeconfig_s g_tim3config =
.width = TIM3_BITWIDTH,
#endif
.base = STM32_TIM3_BASE,
.psc = (STM32_APB1_TIM3_CLKIN / CONFIG_STM32_TIM3_QECLKOUT) - 1,
.psc = CONFIG_STM32_TIM3_QEPSC,
.ti1cfg = GPIO_TIM3_CH1IN,
.ti2cfg = GPIO_TIM3_CH2IN,
#if TIM3_BITWIDTH == 16
@@ -460,7 +434,7 @@ static const struct stm32_qeconfig_s g_tim4config =
.width = TIM4_BITWIDTH,
#endif
.base = STM32_TIM4_BASE,
.psc = (STM32_APB1_TIM4_CLKIN / CONFIG_STM32_TIM4_QECLKOUT) - 1,
.psc = CONFIG_STM32_TIM4_QEPSC,
.ti1cfg = GPIO_TIM4_CH1IN,
.ti2cfg = GPIO_TIM4_CH2IN,
#if TIM4_BITWIDTH == 16
@@ -486,7 +460,7 @@ static const struct stm32_qeconfig_s g_tim5config =
.width = TIM5_BITWIDTH,
#endif
.base = STM32_TIM5_BASE,
.psc = (STM32_APB1_TIM5_CLKIN / CONFIG_STM32_TIM5_QECLKOUT) - 1,
.psc = CONFIG_STM32_TIM5_QEPSC,
.ti1cfg = GPIO_TIM5_CH1IN,
.ti2cfg = GPIO_TIM5_CH2IN,
#if TIM5_BITWIDTH == 16
@@ -512,7 +486,7 @@ static const struct stm32_qeconfig_s g_tim8config =
.width = TIM8_BITWIDTH,
#endif
.base = STM32_TIM8_BASE,
.psc = (STM32_APB2_TIM8_CLKIN / CONFIG_STM32_TIM8_QECLKOUT) - 1,
.psc = CONFIG_STM32_TIM8_QEPSC,
.ti1cfg = GPIO_TIM8_CH1IN,
.ti2cfg = GPIO_TIM8_CH2IN,
#if TIM8_BITWIDTH == 16
@@ -757,7 +731,7 @@ static int stm32_interrupt(FAR struct stm32_lowerhalf_s *priv)
#endif
/************************************************************************************
* Name: stm32_intNinterrupt
* Name: stm32_timNinterrupt
*
* Description:
* TIMN interrupt handler
@@ -820,8 +794,8 @@ static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
{
FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
uint16_t dier;
uint16_t smcr;
uint16_t ccmr1;
uint32_t smcr;
uint32_t ccmr1;
uint16_t ccer;
uint16_t cr1;
#ifdef HAVE_16BIT_TIMERS
@@ -859,10 +833,14 @@ static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
stm32_putreg16(priv, STM32_GTIM_ARR_OFFSET, 0xffff);
#endif
/* Set the timer prescaler value. The clock input value (CLKIN) is based on the
* peripheral clock (PCLK) and a multiplier. These CLKIN values are provided in
* the board.h file. The prescaler value is then that CLKIN value divided by the
* configured CLKOUT value (minus one)
/* Set the timer prescaler value.
*
* If we are doing precise shaft positioning, each qe pulse is important.
* So the STM32 has direct config control on the pulse count prescaler.
* This input clock just limits the incoming pulse rate, which should be
* lower than the peripheral clock due to resynchronization, but it is the
* responsibility of the system designer to decide the correct prescaler
* value, because it has a direct influence on the encoder resolution.
*/
stm32_putreg16(priv, STM32_GTIM_PSC_OFFSET, (uint16_t)priv->config->psc);
@@ -889,10 +867,10 @@ static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
/* Set the encoder Mode 3 */
smcr = stm32_getreg16(priv, STM32_GTIM_SMCR_OFFSET);
smcr = stm32_getreg32(priv, STM32_GTIM_SMCR_OFFSET);
smcr &= ~GTIM_SMCR_SMS_MASK;
smcr |= GTIM_SMCR_ENCMD3;
stm32_putreg16(priv, STM32_GTIM_SMCR_OFFSET, smcr);
stm32_putreg32(priv, STM32_GTIM_SMCR_OFFSET, smcr);
/* TI1 Channel Configuration */
/* Disable the Channel 1: Reset the CC1E Bit */
@@ -901,8 +879,8 @@ static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
ccer &= ~GTIM_CCER_CC1E;
stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET);
ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET);
ccmr1 = stm32_getreg32(priv, STM32_GTIM_CCMR1_OFFSET);
ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET);
/* Select the Input IC1=TI1 and set the filter fSAMPLING=fDTS/4, N=6 */
@@ -917,17 +895,17 @@ static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
/* Write to TIM CCMR1 and CCER registers */
stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
stm32_putreg32(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
/* Set the Input Capture Prescaler value: Capture performed each time an
* edge is detected on the capture input.
*/
ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET);
ccmr1 = stm32_getreg32(priv, STM32_GTIM_CCMR1_OFFSET);
ccmr1 &= ~GTIM_CCMR1_IC1PSC_MASK;
ccmr1 |= (GTIM_CCMR_ICPSC_NOPSC << GTIM_CCMR1_IC1PSC_SHIFT);
stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
stm32_putreg32(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
/* TI2 Channel Configuration */
/* Disable the Channel 2: Reset the CC2E Bit */
@@ -936,7 +914,7 @@ static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
ccer &= ~GTIM_CCER_CC2E;
stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET);
ccmr1 = stm32_getreg32(priv, STM32_GTIM_CCMR1_OFFSET);
ccer = stm32_getreg16(priv, STM32_GTIM_CCER_OFFSET);
/* Select the Input IC2=TI2 and set the filter fSAMPLING=fDTS/4, N=6 */
@@ -952,21 +930,21 @@ static int stm32_setup(FAR struct qe_lowerhalf_s *lower)
/* Write to TIM CCMR1 and CCER registers */
stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
stm32_putreg32(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
stm32_putreg16(priv, STM32_GTIM_CCER_OFFSET, ccer);
/* Set the Input Capture Prescaler value: Capture performed each time an
* edge is detected on the capture input.
*/
ccmr1 = stm32_getreg16(priv, STM32_GTIM_CCMR1_OFFSET);
ccmr1 = stm32_getreg32(priv, STM32_GTIM_CCMR1_OFFSET);
ccmr1 &= ~GTIM_CCMR1_IC2PSC_MASK;
ccmr1 |= (GTIM_CCMR_ICPSC_NOPSC << GTIM_CCMR1_IC2PSC_SHIFT);
stm32_putreg16(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
stm32_putreg32(priv, STM32_GTIM_CCMR1_OFFSET, ccmr1);
/* Disable the update interrupt */
dier = stm32_getreg16(priv, STM32_GTIM_DIER_OFFSET);
dier = stm32_getreg16(priv, STM32_GTIM_DIER_OFFSET);
dier &= ~GTIM_DIER_UIE;
stm32_putreg16(priv, STM32_GTIM_DIER_OFFSET, dier);
@@ -1239,6 +1217,8 @@ static int stm32_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, unsigned long
{
/* No ioctl commands supported */
/* TODO add an IOCTL to control the encoder pulse count prescaler */
return -ENOTTY;
}