diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index c511faaae6..83dbffe78c 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -721,8 +721,8 @@ if STM32L4_TIM1_CHANNEL1 config STM32L4_TIM1_CH1MODE int "TIM1 Channel 1 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -745,8 +745,8 @@ if STM32L4_TIM1_CHANNEL2 config STM32L4_TIM1_CH2MODE int "TIM1 Channel 2 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -769,8 +769,8 @@ if STM32L4_TIM1_CHANNEL3 config STM32L4_TIM1_CH3MODE int "TIM1 Channel 3 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -793,8 +793,8 @@ if STM32L4_TIM1_CHANNEL4 config STM32L4_TIM1_CH4MODE int "TIM1 Channel 4 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -821,8 +821,8 @@ config STM32L4_TIM1_CHANNEL config STM32L4_TIM1_CHMODE int "TIM1 Channel Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -865,8 +865,8 @@ if STM32L4_TIM2_CHANNEL1 config STM32L4_TIM2_CH1MODE int "TIM2 Channel 1 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -889,8 +889,8 @@ if STM32L4_TIM2_CHANNEL2 config STM32L4_TIM2_CH2MODE int "TIM2 Channel 2 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -913,8 +913,8 @@ if STM32L4_TIM2_CHANNEL3 config STM32L4_TIM2_CH3MODE int "TIM2 Channel 3 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -937,8 +937,8 @@ if STM32L4_TIM2_CHANNEL4 config STM32L4_TIM2_CH4MODE int "TIM2 Channel 4 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -965,8 +965,8 @@ config STM32L4_TIM2_CHANNEL config STM32L4_TIM2_CHMODE int "TIM2 Channel Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1009,8 +1009,8 @@ if STM32L4_TIM3_CHANNEL1 config STM32L4_TIM3_CH1MODE int "TIM3 Channel 1 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1033,8 +1033,8 @@ if STM32L4_TIM3_CHANNEL2 config STM32L4_TIM3_CH2MODE int "TIM3 Channel 2 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1057,8 +1057,8 @@ if STM32L4_TIM3_CHANNEL3 config STM32L4_TIM3_CH3MODE int "TIM3 Channel 3 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1081,8 +1081,8 @@ if STM32L4_TIM3_CHANNEL4 config STM32L4_TIM3_CH4MODE int "TIM3 Channel 4 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1109,8 +1109,8 @@ config STM32L4_TIM3_CHANNEL config STM32L4_TIM3_CHMODE int "TIM3 Channel Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1153,8 +1153,8 @@ if STM32L4_TIM4_CHANNEL1 config STM32L4_TIM4_CH1MODE int "TIM4 Channel 1 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1177,8 +1177,8 @@ if STM32L4_TIM4_CHANNEL2 config STM32L4_TIM4_CH2MODE int "TIM4 Channel 2 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1201,8 +1201,8 @@ if STM32L4_TIM4_CHANNEL3 config STM32L4_TIM4_CH3MODE int "TIM4 Channel 3 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1225,8 +1225,8 @@ if STM32L4_TIM4_CHANNEL4 config STM32L4_TIM4_CH4MODE int "TIM4 Channel 4 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1253,8 +1253,8 @@ config STM32L4_TIM4_CHANNEL config STM32L4_TIM4_CHMODE int "TIM4 Channel Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1297,8 +1297,8 @@ if STM32L4_TIM5_CHANNEL1 config STM32L4_TIM5_CH1MODE int "TIM5 Channel 1 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1321,8 +1321,8 @@ if STM32L4_TIM5_CHANNEL2 config STM32L4_TIM5_CH2MODE int "TIM5 Channel 2 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1345,8 +1345,8 @@ if STM32L4_TIM5_CHANNEL3 config STM32L4_TIM5_CH3MODE int "TIM5 Channel 3 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1369,8 +1369,8 @@ if STM32L4_TIM5_CHANNEL4 config STM32L4_TIM5_CH4MODE int "TIM5 Channel 4 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1397,8 +1397,8 @@ config STM32L4_TIM5_CHANNEL config STM32L4_TIM5_CHMODE int "TIM5 Channel Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1441,8 +1441,8 @@ if STM32L4_TIM8_CHANNEL1 config STM32L4_TIM8_CH1MODE int "TIM8 Channel 1 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1465,8 +1465,8 @@ if STM32L4_TIM8_CHANNEL2 config STM32L4_TIM8_CH2MODE int "TIM8 Channel 2 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1489,8 +1489,8 @@ if STM32L4_TIM8_CHANNEL3 config STM32L4_TIM8_CH3MODE int "TIM8 Channel 3 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1513,8 +1513,8 @@ if STM32L4_TIM8_CHANNEL4 config STM32L4_TIM8_CH4MODE int "TIM8 Channel 4 Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1541,8 +1541,8 @@ config STM32L4_TIM8_CHANNEL config STM32L4_TIM8_CHMODE int "TIM8 Channel Mode" default 0 - range 0 5 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 5 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1577,8 +1577,8 @@ if STM32L4_TIM15_CHANNEL1 config STM32L4_TIM15_CH1MODE int "TIM15 Channel 1 Mode" default 0 - range 0 3 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 3 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1601,8 +1601,8 @@ if STM32L4_TIM15_CHANNEL2 config STM32L4_TIM15_CH2MODE int "TIM15 Channel 2 Mode" default 0 - range 0 3 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 3 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -1629,8 +1629,8 @@ config STM32L4_TIM15_CHANNEL config STM32L4_TIM15_CHMODE int "TIM15 Channel Mode" default 0 - range 0 3 if STM32_STM32F30XX - range 0 1 if !STM32_STM32F30XX + range 0 3 if STM32L4_STM32F30XX + range 0 1 if !STM32L4_STM32F30XX ---help--- Specifies the channel mode. @@ -2750,4 +2750,175 @@ config STM32L4_CAN_REGDEBUG endmenu +menu "QEncoder Driver" + depends on QENCODER + depends on STM32L4_TIM1 || STM32L4_TIM2 || STM32L4_TIM3 || STM32L4_TIM4 || STM32L4_TIM5 || STM32L4_TIM8 + +config STM32L4_TIM1_QE + bool "TIM1" + default n + depends on STM32L4_TIM1 + ---help--- + Reserve TIM1 for use by QEncoder. + +if STM32L4_TIM1_QE + +config STM32L4_TIM1_QECLKOUT + int "TIM1 output clock" + default 2800000 + ---help--- + The output clock of TIM1. + +endif + +config STM32L4_TIM2_QE + bool "TIM2" + default n + depends on STM32L4_TIM2 + ---help--- + Reserve TIM2 for use by QEncoder. + +if STM32L4_TIM2_QE + +config STM32L4_TIM2_QECLKOUT + int "TIM2 output clock" + default 2800000 + ---help--- + The output clock of TIM2. + +endif + +config STM32L4_TIM3_QE + bool "TIM3" + default n + depends on STM32L4_TIM3 + ---help--- + Reserve TIM3 for use by QEncoder. + +if STM32L4_TIM3_QE + +config STM32L4_TIM3_QECLKOUT + int "TIM3 output clock" + default 2800000 + ---help--- + The output clock of TIM3. + +endif + +config STM32L4_TIM4_QE + bool "TIM4" + default n + depends on STM32L4_TIM4 + ---help--- + Reserve TIM4 for use by QEncoder. + +if STM32L4_TIM4_QE + +config STM32L4_TIM4_QECLKOUT + int "TIM4 output clock" + default 2800000 + ---help--- + The output clock of TIM4. + +endif + +config STM32L4_TIM5_QE + bool "TIM5" + default n + depends on STM32L4_TIM5 + ---help--- + Reserve TIM5 for use by QEncoder. + +if STM32L4_TIM5_QE + +config STM32L4_TIM5_QECLKOUT + int "TIM5 output clock" + default 2800000 + ---help--- + The output clock of TIM5. + +endif + +config STM32L4_TIM8_QE + bool "TIM8" + default n + depends on STM32L4_TIM8 + ---help--- + Reserve TIM8 for use by QEncoder. + +if STM32L4_TIM8_QE + +config STM32L4_TIM8_QECLKOUT + int "TIM8 output clock" + default 2800000 + ---help--- + The output clock of TIM8. + +endif + +config STM32L4_QENCODER_FILTER + bool "Enable filtering on STM32 QEncoder input" + default y + +choice + depends on STM32L4_QENCODER_FILTER + prompt "Input channel sampling frequency" + default STM32L4_QENCODER_SAMPLE_FDTS_4 + +config STM32L4_QENCODER_SAMPLE_FDTS + bool "fDTS" + +config STM32L4_QENCODER_SAMPLE_CKINT + bool "fCK_INT" + +config STM32L4_QENCODER_SAMPLE_FDTS_2 + bool "fDTS/2" + +config STM32L4_QENCODER_SAMPLE_FDTS_4 + bool "fDTS/4" + +config STM32L4_QENCODER_SAMPLE_FDTS_8 + bool "fDTS/8" + +config STM32L4_QENCODER_SAMPLE_FDTS_16 + bool "fDTS/16" + +config STM32L4_QENCODER_SAMPLE_FDTS_32 + bool "fDTS/32" + +endchoice + +choice + depends on STM32L4_QENCODER_FILTER + prompt "Input channel event count" + default STM32L4_QENCODER_SAMPLE_EVENT_6 + +config STM32L4_QENCODER_SAMPLE_EVENT_1 + depends on STM32L4_QENCODER_SAMPLE_FDTS + bool "1" + +config STM32L4_QENCODER_SAMPLE_EVENT_2 + depends on STM32L4_QENCODER_SAMPLE_CKINT + bool "2" + +config STM32L4_QENCODER_SAMPLE_EVENT_4 + depends on STM32L4_QENCODER_SAMPLE_CKINT + bool "4" + +config STM32L4_QENCODER_SAMPLE_EVENT_5 + depends on STM32L4_QENCODER_SAMPLE_FDTS_16 || STM32L4_QENCODER_SAMPLE_FDTS_32 + bool "5" + +config STM32L4_QENCODER_SAMPLE_EVENT_6 + depends on !STM32L4_QENCODER_SAMPLE_FDTS && !STM32L4_QENCODER_SAMPLE_CKINT + bool "6" + +config STM32L4_QENCODER_SAMPLE_EVENT_8 + depends on !STM32L4_QENCODER_SAMPLE_FDTS + bool "8" + +endchoice + +endmenu + endif # ARCH_CHIP_STM32L4 diff --git a/arch/arm/src/stm32l4/Make.defs b/arch/arm/src/stm32l4/Make.defs index d265c2a4f5..70199cceee 100644 --- a/arch/arm/src/stm32l4/Make.defs +++ b/arch/arm/src/stm32l4/Make.defs @@ -195,6 +195,10 @@ ifeq ($(CONFIG_PWM),y) CHIP_CSRCS += stm32l4_pwm.c endif +ifeq ($(CONFIG_QENCODER),y) +CHIP_CSRCS += stm32l4_qencoder.c +endif + ifeq ($(CONFIG_STM32L4_QSPI),y) CHIP_CSRCS += stm32l4_qspi.c endif diff --git a/arch/arm/src/stm32l4/chip/stm32l4x6xx_pinmap.h b/arch/arm/src/stm32l4/chip/stm32l4x6xx_pinmap.h index c4ebc1413c..00fa2fa37a 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4x6xx_pinmap.h +++ b/arch/arm/src/stm32l4/chip/stm32l4x6xx_pinmap.h @@ -500,14 +500,22 @@ /* Timers */ -#define GPIO_TIM1_CH1_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN8) -#define GPIO_TIM1_CH1_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTE|GPIO_PIN9) -#define GPIO_TIM1_CH2_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN9) -#define GPIO_TIM1_CH2_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTE|GPIO_PIN11) -#define GPIO_TIM1_CH3_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN10) -#define GPIO_TIM1_CH3_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTE|GPIO_PIN13) -#define GPIO_TIM1_CH4_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN11) -#define GPIO_TIM1_CH4_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTE|GPIO_PIN14) +#define GPIO_TIM1_CH1IN_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM1_CH1IN_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN9) +#define GPIO_TIM1_CH1OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM1_CH1OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN9) +#define GPIO_TIM1_CH2IN_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN9) +#define GPIO_TIM1_CH2IN_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN11) +#define GPIO_TIM1_CH2OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN9) +#define GPIO_TIM1_CH2OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN11) +#define GPIO_TIM1_CH3IN_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM1_CH3IN_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN13) +#define GPIO_TIM1_CH3OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM1_CH3OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN13) +#define GPIO_TIM1_CH4IN_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_CH4IN_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN14) +#define GPIO_TIM1_CH4OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_CH4OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN14) #define GPIO_TIM1_CH1N_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN7) #define GPIO_TIM1_CH1N_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN13) #define GPIO_TIM1_CH1N_3 (GPIO_ALT|GPIO_AF1 |GPIO_PORTE|GPIO_PIN8) @@ -529,61 +537,104 @@ #define GPIO_TIM1_ETR_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN12) #define GPIO_TIM1_ETR_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTE|GPIO_PIN7) -#define GPIO_TIM2_CH1_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN0) -#define GPIO_TIM2_CH1_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN5) -#define GPIO_TIM2_CH1_3 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN15) -#define GPIO_TIM2_CH2_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN1) -#define GPIO_TIM2_CH2_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN3) -#define GPIO_TIM2_CH3_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN2) -#define GPIO_TIM2_CH3_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN10) -#define GPIO_TIM2_CH4_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN3) -#define GPIO_TIM2_CH4_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN11) +#define GPIO_TIM2_CH1IN_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_CH1IN_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM2_CH1IN_3 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_CH1OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_CH1OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM2_CH1OUT_3 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_CH2IN_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM2_CH2IN_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN3) +#define GPIO_TIM2_CH2OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM2_CH2OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN3) +#define GPIO_TIM2_CH3IN_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM2_CH3IN_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN10) +#define GPIO_TIM2_CH3OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM2_CH3OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN10) +#define GPIO_TIM2_CH4IN_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM2_CH4IN_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN11) +#define GPIO_TIM2_CH4OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM2_CH4OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN11) #define GPIO_TIM2_BKIN (GPIO_ALT|GPIO_AF2 |GPIO_PORTE|GPIO_PIN14) #define GPIO_TIM2_ETR_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN0) #define GPIO_TIM2_ETR_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN5) #define GPIO_TIM2_ETR_3 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN15) -#define GPIO_TIM3_CH1_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN6) -#define GPIO_TIM3_CH1_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTB|GPIO_PIN4) -#define GPIO_TIM3_CH1_3 (GPIO_ALT|GPIO_AF2 |GPIO_PORTC|GPIO_PIN6) -#define GPIO_TIM3_CH1_4 (GPIO_ALT|GPIO_AF2 |GPIO_PORTE|GPIO_PIN3) -#define GPIO_TIM3_CH2_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN7) -#define GPIO_TIM3_CH2_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTB|GPIO_PIN5) -#define GPIO_TIM3_CH2_3 (GPIO_ALT|GPIO_AF2 |GPIO_PORTC|GPIO_PIN7) -#define GPIO_TIM3_CH2_4 (GPIO_ALT|GPIO_AF2 |GPIO_PORTE|GPIO_PIN4) -#define GPIO_TIM3_CH3_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTB|GPIO_PIN0) -#define GPIO_TIM3_CH3_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTC|GPIO_PIN8) -#define GPIO_TIM3_CH3_3 (GPIO_ALT|GPIO_AF2 |GPIO_PORTE|GPIO_PIN5) -#define GPIO_TIM3_CH4_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTB|GPIO_PIN1) -#define GPIO_TIM3_CH4_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTC|GPIO_PIN9) -#define GPIO_TIM3_CH4_3 (GPIO_ALT|GPIO_AF2 |GPIO_PORTE|GPIO_PIN6) +#define GPIO_TIM3_CH1IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM3_CH1IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM3_CH1IN_3 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM3_CH1IN_4 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN3) +#define GPIO_TIM3_CH1OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM3_CH1OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM3_CH1OUT_3 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM3_CH1OUT_4 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN3) +#define GPIO_TIM3_CH2IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM3_CH2IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM3_CH2IN_3 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM3_CH2IN_4 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN4) +#define GPIO_TIM3_CH2OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM3_CH2OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM3_CH2OUT_3 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM3_CH2OUT_4 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN4) +#define GPIO_TIM3_CH3IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM3_CH3IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM3_CH3IN_3 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TIM3_CH3OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN0) +#define GPIO_TIM3_CH3OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM3_CH3OUT_3 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN5) +#define GPIO_TIM3_CH4IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM3_CH4IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM3_CH4IN_3 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN6) +#define GPIO_TIM3_CH4OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN1) +#define GPIO_TIM3_CH4OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM3_CH4OUT_3 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN6) #define GPIO_TIM3_ETR_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTD|GPIO_PIN2) #define GPIO_TIM3_ETR_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTE|GPIO_PIN2) -#define GPIO_TIM4_CH1_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTB|GPIO_PIN6) -#define GPIO_TIM4_CH1_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTD|GPIO_PIN12) -#define GPIO_TIM4_CH2_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTB|GPIO_PIN7) -#define GPIO_TIM4_CH2_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTD|GPIO_PIN13) -#define GPIO_TIM4_CH3_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTB|GPIO_PIN8) -#define GPIO_TIM4_CH3_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTD|GPIO_PIN14) -#define GPIO_TIM4_CH4_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTB|GPIO_PIN9) -#define GPIO_TIM4_CH4_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTD|GPIO_PIN15) +#define GPIO_TIM4_CH1IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM4_CH1IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN12) +#define GPIO_TIM4_CH1OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM4_CH1OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN12) +#define GPIO_TIM4_CH2IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM4_CH2IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN13) +#define GPIO_TIM4_CH2OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM4_CH2OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN13) +#define GPIO_TIM4_CH3IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM4_CH3IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN14) +#define GPIO_TIM4_CH3OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM4_CH3OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN14) +#define GPIO_TIM4_CH4IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM4_CH4IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTD|GPIO_PIN15) +#define GPIO_TIM4_CH4OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM4_CH4OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTD|GPIO_PIN15) #define GPIO_TIM4_ETR (GPIO_ALT|GPIO_AF2 |GPIO_PORTE|GPIO_PIN0) -#define GPIO_TIM5_CH1_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN0) -#define GPIO_TIM5_CH1_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTF|GPIO_PIN6) -#define GPIO_TIM5_CH2_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN1) -#define GPIO_TIM5_CH2_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTF|GPIO_PIN7) -#define GPIO_TIM5_CH3_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN2) -#define GPIO_TIM5_CH3_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTF|GPIO_PIN8) -#define GPIO_TIM5_CH4_1 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN3) -#define GPIO_TIM5_CH4_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTF|GPIO_PIN9) +#define GPIO_TIM5_CH1IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN6) +#define GPIO_TIM5_CH1OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM5_CH1OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN6) +#define GPIO_TIM5_CH2IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN7) +#define GPIO_TIM5_CH2OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM5_CH2OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN7) +#define GPIO_TIM5_CH3IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN8) +#define GPIO_TIM5_CH3OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM5_CH3OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN8) +#define GPIO_TIM5_CH4IN_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4IN_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN9) +#define GPIO_TIM5_CH4OUT_1 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM5_CH4OUT_2 (GPIO_ALT|GPIO_AF2 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN9) #define GPIO_TIM5_ETR (GPIO_ALT|GPIO_AF1 |GPIO_PORTF|GPIO_PIN6) -#define GPIO_TIM8_CH1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTC|GPIO_PIN6) -#define GPIO_TIM8_CH2 (GPIO_ALT|GPIO_AF3 |GPIO_PORTC|GPIO_PIN7) -#define GPIO_TIM8_CH3 (GPIO_ALT|GPIO_AF3 |GPIO_PORTC|GPIO_PIN8) -#define GPIO_TIM8_CH4 (GPIO_ALT|GPIO_AF3 |GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_CH1IN (GPIO_ALT|GPIO_AF3 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH1OUT (GPIO_ALT|GPIO_AF3 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN6) +#define GPIO_TIM8_CH2IN (GPIO_ALT|GPIO_AF3 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH2OUT (GPIO_ALT|GPIO_AF3 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN7) +#define GPIO_TIM8_CH3IN (GPIO_ALT|GPIO_AF3 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH3OUT (GPIO_ALT|GPIO_AF3 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8) +#define GPIO_TIM8_CH4IN (GPIO_ALT|GPIO_AF3 |GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTC|GPIO_PIN9) +#define GPIO_TIM8_CH4OUT (GPIO_ALT|GPIO_AF3 |GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN9) #define GPIO_TIM8_CH1N_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN5) #define GPIO_TIM8_CH1N_2 (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN7) #define GPIO_TIM8_CH2N_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTB|GPIO_PIN0) @@ -600,29 +651,43 @@ #define GPIO_TIM8_BKIN2_COMP2 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN6) #define GPIO_TIM8_ETR (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN0) -#define GPIO_TIM15_CH1_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN2) -#define GPIO_TIM15_CH1_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN14) -#define GPIO_TIM15_CH1_3 (GPIO_ALT|GPIO_AF14|GPIO_PORTF|GPIO_PIN9) -#define GPIO_TIM15_CH1_4 (GPIO_ALT|GPIO_AF14|GPIO_PORTG|GPIO_PIN10) -#define GPIO_TIM15_CH2_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN3) -#define GPIO_TIM15_CH2_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN15) -#define GPIO_TIM15_CH2_3 (GPIO_ALT|GPIO_AF14|GPIO_PORTF|GPIO_PIN10) -#define GPIO_TIM15_CH2_4 (GPIO_ALT|GPIO_AF14|GPIO_PORTG|GPIO_PIN11) +#define GPIO_TIM15_CH1IN_1 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM15_CH1IN_2 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM15_CH1IN_3 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN9) +#define GPIO_TIM15_CH1IN_4 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTG|GPIO_PIN10) +#define GPIO_TIM15_CH1OUT_1 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM15_CH1OUT_2 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM15_CH1OUT_3 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN9) +#define GPIO_TIM15_CH1OUT_4 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN10) +#define GPIO_TIM15_CH2IN_1 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM15_CH2IN_2 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN15) +#define GPIO_TIM15_CH2IN_3 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTF|GPIO_PIN10) +#define GPIO_TIM15_CH2IN_4 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTG|GPIO_PIN11) +#define GPIO_TIM15_CH2OUT_1 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM15_CH2OUT_2 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN15) +#define GPIO_TIM15_CH2OUT_3 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTF|GPIO_PIN10) +#define GPIO_TIM15_CH2OUT_4 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTG|GPIO_PIN11) #define GPIO_TIM15_CH1N_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN1) #define GPIO_TIM15_CH1N_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN13) #define GPIO_TIM15_CH1N_3 (GPIO_ALT|GPIO_AF14|GPIO_PORTG|GPIO_PIN9) #define GPIO_TIM15_BKIN_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN9) #define GPIO_TIM15_BKIN_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN12) -#define GPIO_TIM16_CH1_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN6) -#define GPIO_TIM16_CH1_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN8) -#define GPIO_TIM16_CH1_3 (GPIO_ALT|GPIO_AF14|GPIO_PORTE|GPIO_PIN0) +#define GPIO_TIM16_CH1IN_1 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM16_CH1IN_2 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM16_CH1IN_3 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN0) +#define GPIO_TIM16_CH1OUT_1 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM16_CH1OUT_2 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM16_CH1OUT_3 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN0) #define GPIO_TIM16_CH1N (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN6) #define GPIO_TIM16_BKIN (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN5) -#define GPIO_TIM17_CH1_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN7) -#define GPIO_TIM17_CH1_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN9) -#define GPIO_TIM17_CH1_3 (GPIO_ALT|GPIO_AF14|GPIO_PORTE|GPIO_PIN1) +#define GPIO_TIM17_CH1IN_1 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM17_CH1IN_2 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM17_CH1IN_3 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_FLOAT|GPIO_PORTE|GPIO_PIN1) +#define GPIO_TIM17_CH1OUT_1 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM17_CH1OUT_2 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM17_CH1OUT_3 (GPIO_ALT|GPIO_AF14|GPIO_SPEED_50MHz|GPIO_PUSHPULL|GPIO_PORTE|GPIO_PIN1) #define GPIO_TIM17_CH1N (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN7) #define GPIO_TIM17_BKIN_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN10) #define GPIO_TIM17_BKIN_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN4) diff --git a/arch/arm/src/stm32l4/stm32l4_qencoder.c b/arch/arm/src/stm32l4/stm32l4_qencoder.c new file mode 100644 index 0000000000..7c9426de29 --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4_qencoder.c @@ -0,0 +1,1248 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/stm32;4_qencoder.c + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * Diego Sanchez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "stm32l4.h" +#include "stm32l4_gpio.h" +#include "stm32l4_tim.h" +#include "stm32l4_qencoder.h" + +#ifdef CONFIG_QENCODER + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ +/* Clocking *************************************************************************/ +/* The CLKOUT value should not exceed the CLKIN value */ + +#if defined(CONFIG_STM32L4_TIM1_QE) && CONFIG_STM32L4_TIM1_QECLKOUT > STM32L4_APB2_TIM1_CLKIN +# warning "CONFIG_STM32L4_TIM1_QECLKOUT exceeds STM32L4_APB2_TIM1_CLKIN" +#endif + +#if defined(CONFIG_STM32L4_TIM2_QE) && CONFIG_STM32L4_TIM2_QECLKOUT > STM32L4_APB1_TIM2_CLKIN +# warning "CONFIG_STM32L4_TIM2_QECLKOUT exceeds STM32L4_APB2_TIM2_CLKIN" +#endif + +#if defined(CONFIG_STM32L4_TIM3_QE) && CONFIG_STM32L4_TIM3_QECLKOUT > STM32L4_APB1_TIM3_CLKIN +# warning "CONFIG_STM32L4_TIM3_QECLKOUT exceeds STM32L4_APB2_TIM3_CLKIN" +#endif + +#if defined(CONFIG_STM32L4_TIM4_QE) && CONFIG_STM32L4_TIM4_QECLKOUT > STM32L4_APB1_TIM4_CLKIN +# warning "CONFIG_STM32L4_TIM4_QECLKOUT exceeds STM32L4_APB2_TIM4_CLKIN" +#endif + +#if defined(CONFIG_STM32L4_TIM5_QE) && CONFIG_STM32L4_TIM5_QECLKOUT > STM32L4_APB1_TIM5_CLKIN +# warning "CONFIG_STM32L4_TIM5_QECLKOUT exceeds STM32L4_APB2_TIM5_CLKIN" +#endif + +#if defined(CONFIG_STM32L4_TIM8_QE) && CONFIG_STM32L4_TIM8_QECLKOUT > STM32L4_APB2_TIM8_CLKIN +# warning "CONFIG_STM32L4_TIM8_QECLKOUT exceeds STM32L4_APB2_TIM8_CLKIN" +#endif + +/* Timers ***************************************************************************/ + +#undef HAVE_32BIT_TIMERS +#undef HAVE_16BIT_TIMERS + +/* On the L4 series, TIM2 and TIM5 are 32-bit. All of the rest are 16-bit */ + +/* If TIM2 or TIM5 are enabled, then we have 32-bit timers */ + +#if defined(CONFIG_STM32L4_TIM2_QE) || defined(CONFIG_STM32L4_TIM5_QE) +# define HAVE_32BIT_TIMERS 1 +#endif + +/* If TIM1,3,4, or 8 are enabled, then we have 16-bit timers */ + +#if defined(CONFIG_STM32L4_TIM1_QE) || defined(CONFIG_STM32L4_TIM3_QE) || \ + defined(CONFIG_STM32L4_TIM4_QE) || defined(CONFIG_STM32L4_TIM8_QE) +# define HAVE_16BIT_TIMERS 1 +#endif + + /* The width in bits of each timer */ + +#define TIM1_BITWIDTH 16 +#define TIM2_BITWIDTH 32 +#define TIM3_BITWIDTH 16 +#define TIM4_BITWIDTH 16 +#define TIM5_BITWIDTH 32 +#define TIM8_BITWIDTH 16 + +/* Do we need to support mixed 16- and 32-bit timers */ + +#undef HAVE_MIXEDWIDTH_TIMERS +#if defined(HAVE_16BIT_TIMERS) && defined(HAVE_32BIT_TIMERS) +# define HAVE_MIXEDWIDTH_TIMERS 1 +#endif + +/* Input filter *********************************************************************/ + +#ifdef CONFIG_STM32L4_QENCODER_FILTER +# if defined(CONFIG_STM32L4_QENCODER_SAMPLE_FDTS) +# if defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_1) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_NOFILT +# endif +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_CKINT) +# if defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_2) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FCKINT2 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_4) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FCKINT4 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_8) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FCKINT8 +# endif +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_FDTS_2) +# if defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_6) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd26 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_8) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd28 +# endif +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_FDTS_4) +# if defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_6) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd46 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_8) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd48 +# endif +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_FDTS_8) +# if defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_6) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd86 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_8) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd88 +# endif +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_FDTS_16) +# if defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_5) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd165 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_6) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd166 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_8) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd168 +# endif +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_FDTS_32) +# if defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_5) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd325 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_6) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd326 +# elif defined(CONFIG_STM32L4_QENCODER_SAMPLE_EVENT_8) +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_FDTSd328 +# endif +# endif + +# ifndef STM32L4_QENCODER_ICF +# warning "Invalid encoder filter combination, filter disabled" +# endif +#endif + +#ifndef STM32L4_QENCODER_ICF +# define STM32L4_QENCODER_ICF GTIM_CCMR_ICF_NOFILT +#endif + +#define STM32L4_GPIO_INPUT_FLOAT (GPIO_INPUT | GPIO_FLOAT) + +/* Debug ****************************************************************************/ +/* Non-standard debug that may be enabled just for testing the quadrature encoder */ + +#ifndef CONFIG_DEBUG_FEATURES +# undef CONFIG_DEBUG_SENSORS +#endif + +#ifdef CONFIG_DEBUG_SENSORS +# ifdef CONFIG_DEBUG_INFO +# define qe_dumpgpio(p,m) stm32l4_dumpgpio(p,m) +# else +# define qe_dumpgpio(p,m) +# endif +#else +# define qe_dumpgpio(p,m) +#endif + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* Constant configuration structure that is retained in FLASH */ + +struct stm32l4_qeconfig_s +{ + uint8_t timid; /* Timer ID {1,2,3,4,5,8} */ + uint8_t irq; /* Timer update IRQ */ +#ifdef HAVE_MIXEDWIDTH_TIMERS + uint8_t width; /* Timer width (16- or 32-bits) */ +#endif + uint32_t ti1cfg; /* TI1 input pin configuration (20-bit encoding) */ + uint32_t ti2cfg; /* TI2 input pin configuration (20-bit encoding) */ + uint32_t base; /* Register base address */ + uint32_t psc; /* Timer input clock prescaler */ + xcpt_t handler; /* Interrupt handler for this IRQ */ +}; + +/* Overall, RAM-based state structure */ + +struct stm32l4_lowerhalf_s +{ + /* The first field of this state structure must be a pointer to the lower- + * half callback structure: + */ + + FAR const struct qe_ops_s *ops; /* Lower half callback structure */ + + /* STM32 driver-specific fields: */ + + FAR const struct stm32l4_qeconfig_s *config; /* static onfiguration */ + + bool inuse; /* True: The lower-half driver is in-use */ + +#ifdef HAVE_16BIT_TIMERS + volatile int32_t position; /* The current position offset */ +#endif +}; + +/************************************************************************************ + * Private Function Prototypes + ************************************************************************************/ +/* Helper functions */ + +static uint16_t stm32l4_getreg16(FAR struct stm32l4_lowerhalf_s *priv, int offset); +static void stm32l4_putreg16(FAR struct stm32l4_lowerhalf_s *priv, int offset, uint16_t value); +static uint32_t stm32l4_getreg32(FAR struct stm32l4_lowerhalf_s *priv, int offset); +static void stm32l4_putreg32(FAR struct stm32l4_lowerhalf_s *priv, int offset, uint32_t value); + +#if defined(CONFIG_DEBUG_SENSORS) && defined(CONFIG_DEBUG_INFO) +static void stm32l4_dumpregs(FAR struct stm32l4_lowerhalf_s *priv, FAR const char *msg); +#else +# define stm32l4_dumpregs(priv,msg) +#endif + +static FAR struct stm32l4_lowerhalf_s *stm32l4_tim2lower(int tim); + +/* Interrupt handling */ + +#ifdef HAVE_16BIT_TIMERS +static int stm32l4_interrupt(FAR struct stm32l4_lowerhalf_s *priv); +#if defined(CONFIG_STM32L4_TIM1_QE) && TIM1_BITWIDTH == 16 +static int stm32l4_tim1interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32L4_TIM2_QE) && TIM2_BITWIDTH == 16 +static int stm32l4_tim2interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32L4_TIM3_QE) && TIM3_BITWIDTH == 16 +static int stm32l4_tim3interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32L4_TIM4_QE) && TIM4_BITWIDTH == 16 +static int stm32l4_tim4interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32L4_TIM5_QE) && TIM5_BITWIDTH == 16 +static int stm32l4_tim5interrupt(int irq, FAR void *context); +#endif +#if defined(CONFIG_STM32L4_TIM8_QE) && TIM8_BITWIDTH == 16 +static int stm32l4_tim8interrupt(int irq, FAR void *context); +#endif +#endif + +/* Lower-half Quadrature Encoder Driver Methods */ + +static int stm32l4_setup(FAR struct qe_lowerhalf_s *lower); +static int stm32l4_shutdown(FAR struct qe_lowerhalf_s *lower); +static int stm32l4_position(FAR struct qe_lowerhalf_s *lower, FAR int32_t *pos); +static int stm32l4_reset(FAR struct qe_lowerhalf_s *lower); +static int stm32l4_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, unsigned long arg); + +/************************************************************************************ + * Private Data + ************************************************************************************/ +/* The lower half callback structure */ + +static const struct qe_ops_s g_qecallbacks = +{ + .setup = stm32l4_setup, + .shutdown = stm32l4_shutdown, + .position = stm32l4_position, + .reset = stm32l4_reset, + .ioctl = stm32l4_ioctl, +}; + +/* Per-timer state structures */ + +#ifdef CONFIG_STM32L4_TIM1_QE +static const struct stm32l4_qeconfig_s g_tim1config = +{ + .timid = 1, + .irq = STM32L4_IRQ_TIM1UP, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM1_BITWIDTH, +#endif + .base = STM32L4_TIM1_BASE, + .psc = (STM32L4_APB2_TIM1_CLKIN / CONFIG_STM32L4_TIM1_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM1_CH1IN, + .ti2cfg = GPIO_TIM1_CH2IN, +#if TIM1_BITWIDTH == 16 + .handler = stm32l4_tim1interrupt, +#endif +}; + +static struct stm32l4_lowerhalf_s g_tim1lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim1config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32L4_TIM2_QE +static const struct stm32l4_qeconfig_s g_tim2config = +{ + .timid = 2, + .irq = STM32L4_IRQ_TIM2, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM2_BITWIDTH, +#endif + .base = STM32L4_TIM2_BASE, + .psc = (STM32L4_APB1_TIM2_CLKIN / CONFIG_STM32L4_TIM2_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM2_CH1IN, + .ti2cfg = GPIO_TIM2_CH2IN, +#if TIM2_BITWIDTH == 16 + .handler = stm32l4_tim2interrupt, +#endif +}; + +static struct stm32l4_lowerhalf_s g_tim2lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim2config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32L4_TIM3_QE +static const struct stm32l4_qeconfig_s g_tim3config = +{ + .timid = 3, + .irq = STM32L4_IRQ_TIM3, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM3_BITWIDTH, +#endif + .base = STM32L4_TIM3_BASE, + .psc = (STM32L4_APB1_TIM3_CLKIN / CONFIG_STM32L4_TIM3_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM3_CH1IN, + .ti2cfg = GPIO_TIM3_CH2IN, +#if TIM3_BITWIDTH == 16 + .handler = stm32l4_tim3interrupt, +#endif +}; + +static struct stm32l4_lowerhalf_s g_tim3lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim3config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32L4_TIM4_QE +static const struct stm32l4_qeconfig_s g_tim4config = +{ + .timid = 4, + .irq = STM32L4_IRQ_TIM4, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM4_BITWIDTH, +#endif + .base = STM32L4_TIM4_BASE, + .psc = (STM32L4_APB1_TIM4_CLKIN / CONFIG_STM32L4_TIM4_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM4_CH1IN, + .ti2cfg = GPIO_TIM4_CH2IN, +#if TIM4_BITWIDTH == 16 + .handler = stm32l4_tim4interrupt, +#endif +}; + +static struct stm32l4_lowerhalf_s g_tim4lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim4config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32L4_TIM5_QE +static const struct stm32l4_qeconfig_s g_tim5config = +{ + .timid = 5, + .irq = STM32L4_IRQ_TIM5, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM5_BITWIDTH, +#endif + .base = STM32L4_TIM5_BASE, + .psc = (STM32L4_APB1_TIM5_CLKIN / CONFIG_STM32L4_TIM5_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM5_CH1IN, + .ti2cfg = GPIO_TIM5_CH2IN, +#if TIM5_BITWIDTH == 16 + .handler = stm32l4_tim5interrupt, +#endif +}; + +static struct stm32l4_lowerhalf_s g_tim5lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim5config, + .inuse = false, +}; + +#endif + +#ifdef CONFIG_STM32L4_TIM8_QE +static const struct stm32l4_qeconfig_s g_tim8config = +{ + .timid = 8, + .irq = STM32L4_IRQ_TIM8UP, +#ifdef HAVE_MIXEDWIDTH_TIMERS + .width = TIM8_BITWIDTH, +#endif + .base = STM32L4_TIM8_BASE, + .psc = (STM32L4_APB2_TIM8_CLKIN / CONFIG_STM32L4_TIM8_QECLKOUT) - 1, + .ti1cfg = GPIO_TIM8_CH1IN, + .ti2cfg = GPIO_TIM8_CH2IN, +#if TIM8_BITWIDTH == 16 + .handler = stm32l4_tim8interrupt, +#endif +}; + +static struct stm32l4_lowerhalf_s g_tim8lower = +{ + .ops = &g_qecallbacks, + .config = &g_tim8config, + .inuse = false, +}; + +#endif + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32l4_getreg16 + * + * Description: + * Read the value of a 16-bit timer register. + * + * Input Parameters: + * priv - A reference to the lower half status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ************************************************************************************/ + +static uint16_t stm32l4_getreg16(struct stm32l4_lowerhalf_s *priv, int offset) +{ + return getreg16(priv->config->base + offset); +} + +/************************************************************************************ + * Name: stm32l4_putreg16 + * + * Description: + * Write a value to a 16-bit timer register. + * + * Input Parameters: + * priv - A reference to the lower half status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void stm32l4_putreg16(FAR struct stm32l4_lowerhalf_s *priv, int offset, + uint16_t value) +{ + putreg16(value, priv->config->base + offset); +} + +/************************************************************************************ + * Name: stm32l4_getreg32 + * + * Description: + * Read the value of a 32-bit timer register. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5 (but works OK + * with the 16-bit TIM1,8 and F1 registers as well). + * + * Input Parameters: + * priv - A reference to the lower half status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ************************************************************************************/ + +static uint32_t stm32l4_getreg32(FAR struct stm32l4_lowerhalf_s *priv, int offset) +{ + return getreg32(priv->config->base + offset); +} + +/************************************************************************************ + * Name: stm32l4_putreg16 + * + * Description: + * Write a value to a 32-bit timer register. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5 (but works OK + * with the 16-bit TIM1,8 and F1 registers). + * + * Input Parameters: + * priv - A reference to the lower half status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ************************************************************************************/ + +static void stm32l4_putreg32(FAR struct stm32l4_lowerhalf_s *priv, int offset, + uint32_t value) +{ + putreg32(value, priv->config->base + offset); +} + +/**************************************************************************** + * Name: stm32l4_dumpregs + * + * Description: + * Dump all timer registers. + * + * Input parameters: + * priv - A reference to the QENCODER block status + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_SENSORS) && defined(CONFIG_DEBUG_INFO) +static void stm32l4_dumpregs(FAR struct stm32l4_lowerhalf_s *priv, + FAR const char *msg) +{ + sninfo("%s:\n", msg); + sninfo(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n", + stm32l4_getreg16(priv, STM32L4_GTIM_CR1_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_CR2_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_SMCR_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_DIER_OFFSET)); + sninfo(" SR: %04x EGR: %04x CCMR1: %04x CCMR2: %04x\n", + stm32l4_getreg16(priv, STM32L4_GTIM_SR_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_EGR_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_CCMR1_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_CCMR2_OFFSET)); + sninfo(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n", + stm32l4_getreg16(priv, STM32L4_GTIM_CCER_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_CNT_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_PSC_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_ARR_OFFSET)); + sninfo(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n", + stm32l4_getreg16(priv, STM32L4_GTIM_CCR1_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_CCR2_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_CCR3_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_CCR4_OFFSET)); +#if defined(CONFIG_STM32L4_TIM1_QE) || defined(CONFIG_STM32L4_TIM8_QE) + if (priv->config->timid == 1 || priv->config->timid == 8) + { + sninfo(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n", + stm32l4_getreg16(priv, STM32L4_ATIM_RCR_OFFSET), + stm32l4_getreg16(priv, STM32L4_ATIM_BDTR_OFFSET), + stm32l4_getreg16(priv, STM32L4_ATIM_DCR_OFFSET), + stm32l4_getreg16(priv, STM32L4_ATIM_DMAR_OFFSET)); + } + else +#endif + { + sninfo(" DCR: %04x DMAR: %04x\n", + stm32l4_getreg16(priv, STM32L4_GTIM_DCR_OFFSET), + stm32l4_getreg16(priv, STM32L4_GTIM_DMAR_OFFSET)); + } +} +#endif + +/************************************************************************************ + * Name: stm32l4_tim2lower + * + * Description: + * Map a timer number to a device structure + * + ************************************************************************************/ + +static FAR struct stm32l4_lowerhalf_s *stm32l4_tim2lower(int tim) +{ + switch (tim) + { +#ifdef CONFIG_STM32L4_TIM1_QE + case 1: + return &g_tim1lower; +#endif +#ifdef CONFIG_STM32L4_TIM2_QE + case 2: + return &g_tim2lower; +#endif +#ifdef CONFIG_STM32L4_TIM3_QE + case 3: + return &g_tim3lower; +#endif +#ifdef CONFIG_STM32L4_TIM4_QE + case 4: + return &g_tim4lower; +#endif +#ifdef CONFIG_STM32L4_TIM5_QE + case 5: + return &g_tim5lower; +#endif +#ifdef CONFIG_STM32L4_TIM8_QE + case 8: + return &g_tim8lower; +#endif + default: + return NULL; + } +} + +/************************************************************************************ + * Name: stm32l4_interrupt + * + * Description: + * Common timer interrupt handling. NOTE: Only 16-bit timers require timer + * interrupts. + * + ************************************************************************************/ + +#ifdef HAVE_16BIT_TIMERS +static int stm32l4_interrupt(FAR struct stm32l4_lowerhalf_s *priv) +{ + uint16_t regval; + + /* Verify that this is an update interrupt. Nothing else is expected. */ + + regval = stm32l4_getreg16(priv, STM32L4_GTIM_SR_OFFSET); + DEBUGASSERT((regval & ATIM_SR_UIF) != 0); + + /* Clear the UIF interrupt bit */ + + stm32l4_putreg16(priv, STM32L4_GTIM_SR_OFFSET, regval & ~GTIM_SR_UIF); + + /* Check the direction bit in the CR1 register and add or subtract the + * maximum value, as appropriate. + */ + + regval = stm32l4_getreg16(priv, STM32L4_GTIM_CR1_OFFSET); + if ((regval & ATIM_CR1_DIR) != 0) + { + priv->position -= (int32_t)0x0000ffff; + } + else + { + priv->position += (int32_t)0x0000ffff; + } + + return OK; +} +#endif + +/************************************************************************************ + * Name: stm32l4_timNinterrupt + * + * Description: + * TIMN interrupt handler + * + ************************************************************************************/ + +#if defined(CONFIG_STM32L4_TIM1_QE) && TIM1_BITWIDTH == 16 +static int stm32l4_tim1interrupt(int irq, FAR void *context) +{ + return stm32l4_interrupt(&g_tim1lower); +} +#endif + +#if defined(CONFIG_STM32L4_TIM2_QE) && TIM2_BITWIDTH == 16 +static int stm32l4_tim2interrupt(int irq, FAR void *context) +{ + return stm32l4_interrupt(&g_tim2lower); +} +#endif + +#if defined(CONFIG_STM32L4_TIM3_QE) && TIM3_BITWIDTH == 16 +static int stm32l4_tim3interrupt(int irq, FAR void *context) +{ + return stm32l4_interrupt(&g_tim3lower); +} +#endif + +#if defined(CONFIG_STM32L4_TIM4_QE) && TIM4_BITWIDTH == 16 +static int stm32l4_tim4interrupt(int irq, FAR void *context) +{ + return stm32l4_interrupt(&g_tim4lower); +} +#endif + +#if defined(CONFIG_STM32L4_TIM5_QE) && TIM5_BITWIDTH == 16 +static int stm32l4_tim5interrupt(int irq, FAR void *context) +{ + return stm32l4_interrupt(&g_tim5lower); +} +#endif + +#if defined(CONFIG_STM32L4_TIM8_QE) && TIM8_BITWIDTH == 16 +static int stm32l4_tim8interrupt(int irq, FAR void *context) +{ + return stm32l4_interrupt(&g_tim8lower); +} +#endif + +/************************************************************************************ + * Name: stm32l4_setup + * + * Description: + * This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * The initial position value should be zero. * + * + ************************************************************************************/ + +static int stm32l4_setup(FAR struct qe_lowerhalf_s *lower) +{ + FAR struct stm32l4_lowerhalf_s *priv = (FAR struct stm32l4_lowerhalf_s *)lower; + uint16_t dier; + uint16_t smcr; + uint16_t ccmr1; + uint16_t ccer; + uint16_t cr1; +#ifdef HAVE_16BIT_TIMERS + uint16_t regval; + int ret; +#endif + + /* NOTE: Clocking should have been enabled in the low-level RCC logic at boot-up */ + + /* Timer base configuration */ + + cr1 = stm32l4_getreg16(priv, STM32L4_GTIM_CR1_OFFSET); + + /* Clear the direction bit (0=count up) and select the Counter Mode (0=Edge aligned) + * (Timers 2-5 and 1-8 only) + */ + + cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK); + stm32l4_putreg16(priv, STM32L4_GTIM_CR1_OFFSET, cr1); + + /* Set the Autoreload value */ + +#if defined(HAVE_MIXEDWIDTH_TIMERS) + if (priv->config->width == 32) + { + stm32l4_putreg32(priv, STM32L4_GTIM_ARR_OFFSET, 0xffffffff); + } + else + { + stm32l4_putreg16(priv, STM32L4_GTIM_ARR_OFFSET, 0xffff); + } +#elif defined(HAVE_32BIT_TIMERS) + stm32l4_putreg32(priv, STM32L4_GTIM_ARR_OFFSET, 0xffffffff); +#else + stm32l4_putreg16(priv, STM32L4_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) + */ + + stm32l4_putreg16(priv, STM32L4_GTIM_PSC_OFFSET, (uint16_t)priv->config->psc); + +#if defined(CONFIG_STM32L4_TIM1_QE) || defined(CONFIG_STM32L4_TIM8_QE) + if (priv->config->timid == 1 || priv->config->timid == 8) + { + /* Clear the Repetition Counter value */ + + stm32l4_putreg16(priv, STM32L4_ATIM_RCR_OFFSET, 0); + } +#endif + + /* Generate an update event to reload the Prescaler + * and the repetition counter (only for TIM1 and TIM8) value immediately + */ + + stm32l4_putreg16(priv, STM32L4_GTIM_EGR_OFFSET, GTIM_EGR_UG); + + /* GPIO pin configuration */ + + stm32l4_configgpio(priv->config->ti1cfg); + stm32l4_configgpio(priv->config->ti2cfg); + + /* Set the encoder Mode 3 */ + + smcr = stm32l4_getreg16(priv, STM32L4_GTIM_SMCR_OFFSET); + smcr &= ~GTIM_SMCR_SMS_MASK; + smcr |= GTIM_SMCR_ENCMD3; + stm32l4_putreg16(priv, STM32L4_GTIM_SMCR_OFFSET, smcr); + + /* TI1 Channel Configuration */ + /* Disable the Channel 1: Reset the CC1E Bit */ + + ccer = stm32l4_getreg16(priv, STM32L4_GTIM_CCER_OFFSET); + ccer &= ~GTIM_CCER_CC1E; + stm32l4_putreg16(priv, STM32L4_GTIM_CCER_OFFSET, ccer); + + ccmr1 = stm32l4_getreg16(priv, STM32L4_GTIM_CCMR1_OFFSET); + ccer = stm32l4_getreg16(priv, STM32L4_GTIM_CCER_OFFSET); + + /* Select the Input IC1=TI1 and set the filter fSAMPLING=fDTS/4, N=6 */ + + ccmr1 &= ~(GTIM_CCMR1_CC1S_MASK | GTIM_CCMR1_IC1F_MASK); + ccmr1 |= GTIM_CCMR_CCS_CCIN1 << GTIM_CCMR1_CC1S_SHIFT; + ccmr1 |= STM32L4_QENCODER_ICF << GTIM_CCMR1_IC1F_SHIFT; + + /* Select the Polarity=rising and set the CC1E Bit */ + + ccer &= ~(GTIM_CCER_CC1P | GTIM_CCER_CC1NP); + ccer |= GTIM_CCER_CC1E; + + /* Write to TIM CCMR1 and CCER registers */ + + stm32l4_putreg16(priv, STM32L4_GTIM_CCMR1_OFFSET, ccmr1); + stm32l4_putreg16(priv, STM32L4_GTIM_CCER_OFFSET, ccer); + + /* Set the Input Capture Prescaler value: Capture performed each time an + * edge is detected on the capture input. + */ + + ccmr1 = stm32l4_getreg16(priv, STM32L4_GTIM_CCMR1_OFFSET); + ccmr1 &= ~GTIM_CCMR1_IC1PSC_MASK; + ccmr1 |= (GTIM_CCMR_ICPSC_NOPSC << GTIM_CCMR1_IC1PSC_SHIFT); + stm32l4_putreg16(priv, STM32L4_GTIM_CCMR1_OFFSET, ccmr1); + + /* TI2 Channel Configuration */ + /* Disable the Channel 2: Reset the CC2E Bit */ + + ccer = stm32l4_getreg16(priv, STM32L4_GTIM_CCER_OFFSET); + ccer &= ~GTIM_CCER_CC2E; + stm32l4_putreg16(priv, STM32L4_GTIM_CCER_OFFSET, ccer); + + ccmr1 = stm32l4_getreg16(priv, STM32L4_GTIM_CCMR1_OFFSET); + ccer = stm32l4_getreg16(priv, STM32L4_GTIM_CCER_OFFSET); + + /* Select the Input IC2=TI2 and set the filter fSAMPLING=fDTS/4, N=6 */ + + ccmr1 &= ~(GTIM_CCMR1_CC2S_MASK | GTIM_CCMR1_IC2F_MASK); + ccmr1 |= GTIM_CCMR_CCS_CCIN1 << GTIM_CCMR1_CC2S_SHIFT; + ccmr1 |= STM32L4_QENCODER_ICF << GTIM_CCMR1_IC2F_SHIFT; + + /* Select the Polarity=rising and set the CC2E Bit */ + + ccer &= ~(GTIM_CCER_CC2P | GTIM_CCER_CC2NP); + ccer |= GTIM_CCER_CC2E; + + /* Write to TIM CCMR1 and CCER registers */ + + stm32l4_putreg16(priv, STM32L4_GTIM_CCMR1_OFFSET, ccmr1); + stm32l4_putreg16(priv, STM32L4_GTIM_CCER_OFFSET, ccer); + + /* Set the Input Capture Prescaler value: Capture performed each time an + * edge is detected on the capture input. + */ + + ccmr1 = stm32l4_getreg16(priv, STM32L4_GTIM_CCMR1_OFFSET); + ccmr1 &= ~GTIM_CCMR1_IC2PSC_MASK; + ccmr1 |= (GTIM_CCMR_ICPSC_NOPSC << GTIM_CCMR1_IC2PSC_SHIFT); + stm32l4_putreg16(priv, STM32L4_GTIM_CCMR1_OFFSET, ccmr1); + + /* Disable the update interrupt */ + + dier = stm32l4_getreg16(priv, STM32L4_GTIM_DIER_OFFSET); + dier &= ~GTIM_DIER_UIE; + stm32l4_putreg16(priv, STM32L4_GTIM_DIER_OFFSET, dier); + + /* There is no need for interrupts with 32-bit timers */ + +#ifdef HAVE_16BIT_TIMERS +#ifdef HAVE_MIXEDWIDTH_TIMERS + if (priv->config->width != 32) +#endif + { + /* Attach the interrupt handler */ + + ret = irq_attach(priv->config->irq, priv->config->handler); + if (ret < 0) + { + stm32l4_shutdown(lower); + return ret; + } + + /* Enable the update/global interrupt at the NVIC */ + + up_enable_irq(priv->config->irq); + } +#endif + + /* Reset the Update Disable Bit */ + + cr1 = stm32l4_getreg16(priv, STM32L4_GTIM_CR1_OFFSET); + cr1 &= ~GTIM_CR1_UDIS; + stm32l4_putreg16(priv, STM32L4_GTIM_CR1_OFFSET, cr1); + + /* Reset the URS Bit */ + + cr1 &= ~GTIM_CR1_URS; + stm32l4_putreg16(priv, STM32L4_GTIM_CR1_OFFSET, cr1); + + /* There is no need for interrupts with 32-bit timers */ + +#ifdef HAVE_16BIT_TIMERS +#ifdef HAVE_MIXEDWIDTH_TIMERS + if (priv->config->width != 32) +#endif + { + /* Clear any pending update interrupts */ + + regval = stm32l4_getreg16(priv, STM32L4_GTIM_SR_OFFSET); + stm32l4_putreg16(priv, STM32L4_GTIM_SR_OFFSET, regval & ~GTIM_SR_UIF); + + /* Then enable the update interrupt */ + + dier = stm32l4_getreg16(priv, STM32L4_GTIM_DIER_OFFSET); + dier |= GTIM_DIER_UIE; + stm32l4_putreg16(priv, STM32L4_GTIM_DIER_OFFSET, dier); + } +#endif + + /* Enable the TIM Counter */ + + cr1 = stm32l4_getreg16(priv, STM32L4_GTIM_CR1_OFFSET); + cr1 |= GTIM_CR1_CEN; + stm32l4_putreg16(priv, STM32L4_GTIM_CR1_OFFSET, cr1); + + return OK; +} + +/************************************************************************************ + * Name: stm32l4_shutdown + * + * Description: + * This method is called when the driver is closed. The lower half driver + * should stop data collection, free any resources, disable timer hardware, and + * put the system into the lowest possible power usage state * + * + ************************************************************************************/ + +static int stm32l4_shutdown(FAR struct qe_lowerhalf_s *lower) +{ + FAR struct stm32l4_lowerhalf_s *priv = (FAR struct stm32l4_lowerhalf_s *)lower; + irqstate_t flags; + uint32_t regaddr; + uint32_t regval; + uint32_t resetbit; + uint32_t pincfg; + + /* Disable the update/global interrupt at the NVIC */ + + flags = enter_critical_section(); + up_disable_irq(priv->config->irq); + + /* Detach the interrupt handler */ + + (void)irq_detach(priv->config->irq); + + /* Disable interrupts momentary to stop any ongoing timer processing and + * to prevent any concurrent access to the reset register. + */ + + /* Disable further interrupts and stop the timer */ + + stm32l4_putreg16(priv, STM32L4_GTIM_DIER_OFFSET, 0); + stm32l4_putreg16(priv, STM32L4_GTIM_SR_OFFSET, 0); + + /* Determine which timer to reset */ + + switch (priv->config->timid) + { +#ifdef CONFIG_STM32L4_TIM1_QE + case 1: + regaddr = STM32L4_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM1RST; + break; +#endif +#ifdef CONFIG_STM32L4_TIM2_QE + case 2: + regaddr = STM32L4_RCC_APB1RSTR1; + resetbit = RCC_APB1RSTR1_TIM2RST; + break; +#endif +#ifdef CONFIG_STM32L4_TIM3_QE + case 3: + regaddr = STM32L4_RCC_APB1RSTR1; + resetbit = RCC_APB1RSTR1_TIM3RST; + break; +#endif +#ifdef CONFIG_STM32L4_TIM4_QE + case 4: + regaddr = STM32L4_RCC_APB1RSTR1; + resetbit = RCC_APB1RSTR1_TIM4RST; + break; +#endif +#ifdef CONFIG_STM32L4_TIM5_QE + case 5: + regaddr = STM32L4_RCC_APB1RSTR1; + resetbit = RCC_APB1RSTR1_TIM5RST; + break; +#endif +#ifdef CONFIG_STM32L4_TIM8_QE + case 8: + regaddr = STM32L4_RCC_APB2RSTR; + resetbit = RCC_APB2RSTR_TIM8RST; + break; +#endif + default: + return -EINVAL; + } + + /* Reset the timer - stopping the output and putting the timer back + * into a state where stm32l4_start() can be called. + */ + + regval = getreg32(regaddr); + regval |= resetbit; + putreg32(regval, regaddr); + + regval &= ~resetbit; + putreg32(regval, regaddr); + leave_critical_section(flags); + + sninfo("regaddr: %08x resetbit: %08x\n", regaddr, resetbit); + stm32l4_dumpregs(priv, "After stop"); + + /* Put the TI1 GPIO pin back to its default state */ + + pincfg = priv->config->ti1cfg & (GPIO_PORT_MASK | GPIO_PIN_MASK); + pincfg |= STM32L4_GPIO_INPUT_FLOAT; + + stm32l4_configgpio(pincfg); + + /* Put the TI2 GPIO pin back to its default state */ + + pincfg = priv->config->ti2cfg & (GPIO_PORT_MASK | GPIO_PIN_MASK); + pincfg |= STM32L4_GPIO_INPUT_FLOAT; + + stm32l4_configgpio(pincfg); + return OK; +} + +/************************************************************************************ + * Name: stm32l4_position + * + * Description: + * Return the current position measurement. + * + ************************************************************************************/ + +static int stm32l4_position(FAR struct qe_lowerhalf_s *lower, FAR int32_t *pos) +{ + FAR struct stm32l4_lowerhalf_s *priv = (FAR struct stm32l4_lowerhalf_s *)lower; +#ifdef HAVE_16BIT_TIMERS + int32_t position; + int32_t verify; + uint32_t count; + + DEBUGASSERT(lower && priv->inuse); + + /* Loop until we are certain that no interrupt occurred between samples */ + + do + { + /* Don't let another task pre-empt us until we get the measurement. The timer + * interrupt may still be processed + */ + + sched_lock(); + position = priv->position; + count = stm32l4_getreg32(priv, STM32L4_GTIM_CNT_OFFSET); + verify = priv->position; + sched_unlock(); + } + while (position != verify); + + /* Return the position measurement */ + + *pos = position + (int32_t)count; +#else + /* Return the counter value */ + + *pos = (int32_t)stm32l4_getreg32(priv, STM32L4_GTIM_CNT_OFFSET); +#endif + return OK; +} + +/************************************************************************************ + * Name: stm32l4_reset + * + * Description: + * Reset the position measurement to zero. + * + ************************************************************************************/ + +static int stm32l4_reset(FAR struct qe_lowerhalf_s *lower) +{ + FAR struct stm32l4_lowerhalf_s *priv = (FAR struct stm32l4_lowerhalf_s *)lower; +#ifdef HAVE_16BIT_TIMERS + irqstate_t flags; + + sninfo("Resetting position to zero\n"); + DEBUGASSERT(lower && priv->inuse); + + /* Reset the timer and the counter. Interrupts are disabled to make this atomic + * (if possible) + */ + + flags = enter_critical_section(); + stm32l4_putreg32(priv, STM32L4_GTIM_CNT_OFFSET, 0); + priv->position = 0; + leave_critical_section(flags); +#else + sninfo("Resetting position to zero\n"); + DEBUGASSERT(lower && priv->inuse); + + /* Reset the counter to zero */ + + stm32l4_putreg32(priv, STM32L4_GTIM_CNT_OFFSET, 0); +#endif + return OK; +} + +/************************************************************************************ + * Name: stm32l4_ioctl + * + * Description: + * Lower-half logic may support platform-specific ioctl commands + * + ************************************************************************************/ + +static int stm32l4_ioctl(FAR struct qe_lowerhalf_s *lower, int cmd, unsigned long arg) +{ + /* No ioctl commands supported */ + + return -ENOTTY; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32l4_qeinitialize + * + * Description: + * Initialize a quadrature encoder interface. This function must be called from + * board-specific logic. + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/qe0" + * tim - The timer number to used. 'tim' must be an element of {1,2,3,4,5,8} + * + * Returned Values: + * Zero on success; A negated errno value is returned on failure. + * + ************************************************************************************/ + +int stm32l4_qeinitialize(FAR const char *devpath, int tim) +{ + FAR struct stm32l4_lowerhalf_s *priv; + int ret; + + /* Find the pre-allocated timer state structure corresponding to this timer */ + + priv = stm32l4_tim2lower(tim); + if (!priv) + { + snerr("ERROR: TIM%d support not configured\n", tim); + return -ENXIO; + } + + /* Make sure that it is available */ + + if (priv->inuse) + { + snerr("ERROR: TIM%d is in-use\n", tim); + return -EBUSY; + } + + /* Register the priv-half driver */ + + ret = qe_register(devpath, (FAR struct qe_lowerhalf_s *)priv); + if (ret < 0) + { + snerr("ERROR: qe_register failed: %d\n", ret); + return ret; + } + + /* Make sure that the timer is in the shutdown state */ + + stm32l4_shutdown((FAR struct qe_lowerhalf_s *)priv); + + /* The driver is now in-use */ + + priv->inuse = true; + return OK; +} + +#endif /* CONFIG_QENCODER */ diff --git a/arch/arm/src/stm32l4/stm32l4_qencoder.h b/arch/arm/src/stm32l4/stm32l4_qencoder.h new file mode 100644 index 0000000000..fca0b88b8b --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4_qencoder.h @@ -0,0 +1,141 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/stm32l4_qencoder.h + * + * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32L4_STM32L4_QENCODER_H +#define __ARCH_ARM_SRC_STM32L4_STM32L4_QENCODER_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#include "chip.h" + +#ifdef CONFIG_QENCODER + +/************************************************************************************ + * Included Files + ************************************************************************************/ +/* Timer devices may be used for different purposes. One special purpose is as + * a quadrature encoder input device. If CONFIG_STM32L4_TIMn is defined then the + * CONFIG_STM32L4_TIMn_QE must also be defined to indicate that timer "n" is intended + * to be used for as a quadrature encoder. + */ + +#ifndef CONFIG_STM32L4_TIM1 +# undef CONFIG_STM32L4_TIM1_QE +#endif +#ifndef CONFIG_STM32L4_TIM2 +# undef CONFIG_STM32L4_TIM2_QE +#endif +#ifndef CONFIG_STM32L4_TIM3 +# undef CONFIG_STM32L4_TIM3_QE +#endif +#ifndef CONFIG_STM32L4_TIM4 +# undef CONFIG_STM32L4_TIM4_QE +#endif +#ifndef CONFIG_STM32L4_TIM5 +# undef CONFIG_STM32L4_TIM5_QE +#endif +#ifndef CONFIG_STM32L4_TIM8 +# undef CONFIG_STM32L4_TIM8_QE +#endif + +/* Only timers 2-5, and 1 & 8 can be used as a quadrature encoder + */ + +#undef CONFIG_STM32L4_TIM6_QE +#undef CONFIG_STM32L4_TIM7_QE +#undef CONFIG_STM32L4_TIM9_QE +#undef CONFIG_STM32L4_TIM10_QE +#undef CONFIG_STM32L4_TIM11_QE +#undef CONFIG_STM32L4_TIM12_QE +#undef CONFIG_STM32L4_TIM13_QE +#undef CONFIG_STM32L4_TIM14_QE + +/* Clock out frequency. This value is used to calculation the timer CLKIN in + * prescaler value. + */ + +#ifndef CONFIG_STM32L4_TIM1_QECLKOUT +# define CONFIG_STM32L4_TIM1_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32L4_TIM2_QECLKOUT +# define CONFIG_STM32L4_TIM2_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32L4_TIM3_QECLKOUT +# define CONFIG_STM32L4_TIM3_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32L4_TIM4_QECLKOUT +# define CONFIG_STM32L4_TIM4_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32L4_TIM5_QECLKOUT +# define CONFIG_STM32L4_TIM5_QECLKOUT 28000000 +#endif + +#ifndef CONFIG_STM32L4_TIM8_QECLKOUT +# define CONFIG_STM32L4_TIM8_QECLKOUT 28000000 +#endif + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +/************************************************************************************ + * Name: stm32l4_qeinitialize + * + * Description: + * Initialize a quadrature encoder interface. This function must be called from + * board-specific logic.. + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/qe0" + * tim - The timer number to used. 'tim' must be an element of {1,2,3,4,5,8} + * + * Returned Values: + * Zero on success; A negated errno value is returned on failure. + * + ************************************************************************************/ + +int stm32l4_qeinitialize(FAR const char *devpath, int tim); + +#endif /* CONFIG_QENCODER */ +#endif /* __ARCH_ARM_SRC_STM32L4_STM32L4_QENCODER_H */ +