diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index 3d372197c6e..d5e5bda9e4f 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -1878,6 +1878,12 @@ endchoice endif # STM32L4_LPTIM2_PWM +config STM32L4_PWM_LL_OPS + bool "PWM low-level operations" + default n + ---help--- + Enable low-level PWM ops. + config STM32L4_TIM1_PWM bool "TIM1 PWM" default n @@ -1901,6 +1907,27 @@ config STM32L4_TIM1_MODE ---help--- Specifies the timer mode. +config STM32L4_TIM1_LOCK + int "TIM1 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 1 lock level configuration + +config STM32L4_TIM1_TDTS + int "TIM1 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 1 dead-time and sampling clock (t_DTS) division + +config STM32L4_TIM1_DEADTIME + int "TIM1 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 1 initial dead-time + if STM32L4_PWM_MULTICHAN config STM32L4_TIM1_CHANNEL1 @@ -1913,10 +1940,10 @@ if STM32L4_TIM1_CHANNEL1 config STM32L4_TIM1_CH1MODE int "TIM1 Channel 1 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM1_CH1OUT bool "TIM1 Channel 1 Output" @@ -1943,10 +1970,10 @@ if STM32L4_TIM1_CHANNEL2 config STM32L4_TIM1_CH2MODE int "TIM1 Channel 2 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM1_CH2OUT bool "TIM1 Channel 2 Output" @@ -1973,10 +2000,10 @@ if STM32L4_TIM1_CHANNEL3 config STM32L4_TIM1_CH3MODE int "TIM1 Channel 3 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM1_CH3OUT bool "TIM1 Channel 3 Output" @@ -2003,10 +2030,10 @@ if STM32L4_TIM1_CHANNEL4 config STM32L4_TIM1_CH4MODE int "TIM1 Channel 4 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM1_CH4OUT bool "TIM1 Channel 4 Output" @@ -2028,12 +2055,70 @@ config STM32L4_TIM1_CHANNEL If TIM1 is enabled for PWM usage, you also need specifies the timer output channel {1,..,4} +if STM32L4_TIM1_CHANNEL = 1 + +config STM32L4_TIM1_CH1OUT + bool "TIM1 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32L4_TIM1_CH1NOUT + bool "TIM1 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32L4_TIM1_CHANNEL = 1 + +if STM32L4_TIM1_CHANNEL = 2 + +config STM32L4_TIM1_CH2OUT + bool "TIM1 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config STM32L4_TIM1_CH2NOUT + bool "TIM1 Channel 2 Complementary Output" + default n + ---help--- + Enables channel 2 Complementary Output. + +endif # STM32L4_TIM1_CHANNEL = 2 + +if STM32L4_TIM1_CHANNEL = 3 + +config STM32L4_TIM1_CH3OUT + bool "TIM1 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +config STM32L4_TIM1_CH3NOUT + bool "TIM1 Channel 3 Complementary Output" + default n + ---help--- + Enables channel 3 Complementary Output. + +endif # STM32L4_TIM1_CHANNEL = 3 + +if STM32L4_TIM1_CHANNEL = 4 + +config STM32L4_TIM1_CH4OUT + bool "TIM1 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32L4_TIM1_CHANNEL = 4 + config STM32L4_TIM1_CHMODE int "TIM1 Channel Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -2074,10 +2159,10 @@ if STM32L4_TIM2_CHANNEL1 config STM32L4_TIM2_CH1MODE int "TIM2 Channel 1 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM2_CH1OUT bool "TIM2 Channel 1 Output" @@ -2097,10 +2182,10 @@ if STM32L4_TIM2_CHANNEL2 config STM32L4_TIM2_CH2MODE int "TIM2 Channel 2 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM2_CH2OUT bool "TIM2 Channel 2 Output" @@ -2120,10 +2205,10 @@ if STM32L4_TIM2_CHANNEL3 config STM32L4_TIM2_CH3MODE int "TIM2 Channel 3 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM2_CH3OUT bool "TIM2 Channel 3 Output" @@ -2143,10 +2228,10 @@ if STM32L4_TIM2_CHANNEL4 config STM32L4_TIM2_CH4MODE int "TIM2 Channel 4 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM2_CH4OUT bool "TIM2 Channel 4 Output" @@ -2168,12 +2253,52 @@ config STM32L4_TIM2_CHANNEL If TIM2 is enabled for PWM usage, you also need specifies the timer output channel {1,..,4} +if STM32L4_TIM2_CHANNEL = 1 + +config STM32L4_TIM2_CH1OUT + bool "TIM2 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32L4_TIM2_CHANNEL = 1 + +if STM32L4_TIM2_CHANNEL = 2 + +config STM32L4_TIM2_CH2OUT + bool "TIM2 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32L4_TIM2_CHANNEL = 2 + +if STM32L4_TIM2_CHANNEL = 3 + +config STM32L4_TIM2_CH3OUT + bool "TIM2 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32L4_TIM2_CHANNEL = 3 + +if STM32L4_TIM2_CHANNEL = 4 + +config STM32L4_TIM2_CH4OUT + bool "TIM2 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32L4_TIM2_CHANNEL = 4 + config STM32L4_TIM2_CHMODE int "TIM2 Channel Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -2214,10 +2339,10 @@ if STM32L4_TIM3_CHANNEL1 config STM32L4_TIM3_CH1MODE int "TIM3 Channel 1 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM3_CH1OUT bool "TIM3 Channel 1 Output" @@ -2237,10 +2362,10 @@ if STM32L4_TIM3_CHANNEL2 config STM32L4_TIM3_CH2MODE int "TIM3 Channel 2 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM3_CH2OUT bool "TIM3 Channel 2 Output" @@ -2260,10 +2385,10 @@ if STM32L4_TIM3_CHANNEL3 config STM32L4_TIM3_CH3MODE int "TIM3 Channel 3 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM3_CH3OUT bool "TIM3 Channel 3 Output" @@ -2283,10 +2408,10 @@ if STM32L4_TIM3_CHANNEL4 config STM32L4_TIM3_CH4MODE int "TIM3 Channel 4 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM3_CH4OUT bool "TIM3 Channel 4 Output" @@ -2308,12 +2433,52 @@ config STM32L4_TIM3_CHANNEL If TIM3 is enabled for PWM usage, you also need specifies the timer output channel {1,..,4} +if STM32L4_TIM3_CHANNEL = 1 + +config STM32L4_TIM3_CH1OUT + bool "TIM3 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32L4_TIM3_CHANNEL = 1 + +if STM32L4_TIM3_CHANNEL = 2 + +config STM32L4_TIM3_CH2OUT + bool "TIM3 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32L4_TIM3_CHANNEL = 2 + +if STM32L4_TIM3_CHANNEL = 3 + +config STM32L4_TIM3_CH3OUT + bool "TIM3 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32L4_TIM3_CHANNEL = 3 + +if STM32L4_TIM3_CHANNEL = 4 + +config STM32L4_TIM3_CH4OUT + bool "TIM3 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32L4_TIM3_CHANNEL = 4 + config STM32L4_TIM3_CHMODE int "TIM3 Channel Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -2354,10 +2519,10 @@ if STM32L4_TIM4_CHANNEL1 config STM32L4_TIM4_CH1MODE int "TIM4 Channel 1 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM4_CH1OUT bool "TIM4 Channel 1 Output" @@ -2377,10 +2542,10 @@ if STM32L4_TIM4_CHANNEL2 config STM32L4_TIM4_CH2MODE int "TIM4 Channel 2 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM4_CH2OUT bool "TIM4 Channel 2 Output" @@ -2400,10 +2565,10 @@ if STM32L4_TIM4_CHANNEL3 config STM32L4_TIM4_CH3MODE int "TIM4 Channel 3 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM4_CH3OUT bool "TIM4 Channel 3 Output" @@ -2423,10 +2588,10 @@ if STM32L4_TIM4_CHANNEL4 config STM32L4_TIM4_CH4MODE int "TIM4 Channel 4 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM4_CH4OUT bool "TIM4 Channel 4 Output" @@ -2448,12 +2613,52 @@ config STM32L4_TIM4_CHANNEL If TIM4 is enabled for PWM usage, you also need specifies the timer output channel {1,..,4} +if STM32L4_TIM4_CHANNEL = 1 + +config STM32L4_TIM4_CH1OUT + bool "TIM4 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32L4_TIM4_CHANNEL = 1 + +if STM32L4_TIM4_CHANNEL = 2 + +config STM32L4_TIM4_CH2OUT + bool "TIM4 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32L4_TIM4_CHANNEL = 2 + +if STM32L4_TIM4_CHANNEL = 3 + +config STM32L4_TIM4_CH3OUT + bool "TIM4 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32L4_TIM4_CHANNEL = 3 + +if STM32L4_TIM4_CHANNEL = 4 + +config STM32L4_TIM4_CH4OUT + bool "TIM4 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32L4_TIM4_CHANNEL = 4 + config STM32L4_TIM4_CHMODE int "TIM4 Channel Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -2494,10 +2699,10 @@ if STM32L4_TIM5_CHANNEL1 config STM32L4_TIM5_CH1MODE int "TIM5 Channel 1 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM5_CH1OUT bool "TIM5 Channel 1 Output" @@ -2517,10 +2722,10 @@ if STM32L4_TIM5_CHANNEL2 config STM32L4_TIM5_CH2MODE int "TIM5 Channel 2 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM5_CH2OUT bool "TIM5 Channel 2 Output" @@ -2540,10 +2745,10 @@ if STM32L4_TIM5_CHANNEL3 config STM32L4_TIM5_CH3MODE int "TIM5 Channel 3 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM5_CH3OUT bool "TIM5 Channel 3 Output" @@ -2563,10 +2768,10 @@ if STM32L4_TIM5_CHANNEL4 config STM32L4_TIM5_CH4MODE int "TIM5 Channel 4 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM5_CH4OUT bool "TIM5 Channel 4 Output" @@ -2588,12 +2793,52 @@ config STM32L4_TIM5_CHANNEL If TIM5 is enabled for PWM usage, you also need specifies the timer output channel {1,..,4} +if STM32L4_TIM5_CHANNEL = 1 + +config STM32L4_TIM5_CH1OUT + bool "TIM5 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32L4_TIM5_CHANNEL = 1 + +if STM32L4_TIM5_CHANNEL = 2 + +config STM32L4_TIM5_CH2OUT + bool "TIM5 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32L4_TIM5_CHANNEL = 2 + +if STM32L4_TIM5_CHANNEL = 3 + +config STM32L4_TIM5_CH3OUT + bool "TIM5 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32L4_TIM5_CHANNEL = 3 + +if STM32L4_TIM5_CHANNEL = 4 + +config STM32L4_TIM5_CH4OUT + bool "TIM5 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32L4_TIM5_CHANNEL = 4 + config STM32L4_TIM5_CHMODE int "TIM5 Channel Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -2622,6 +2867,27 @@ config STM32L4_TIM8_MODE ---help--- Specifies the timer mode. +config STM32L4_TIM8_LOCK + int "TIM1 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 8 lock level configuration + +config STM32L4_TIM8_TDTS + int "TIM8 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 8 dead-time and sampling clock (t_DTS) division + +config STM32L4_TIM8_DEADTIME + int "TIM8 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 8 initial dead-time + if STM32L4_PWM_MULTICHAN config STM32L4_TIM8_CHANNEL1 @@ -2634,10 +2900,10 @@ if STM32L4_TIM8_CHANNEL1 config STM32L4_TIM8_CH1MODE int "TIM8 Channel 1 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM8_CH1OUT bool "TIM8 Channel 1 Output" @@ -2664,10 +2930,10 @@ if STM32L4_TIM8_CHANNEL2 config STM32L4_TIM8_CH2MODE int "TIM8 Channel 2 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM8_CH2OUT bool "TIM8 Channel 2 Output" @@ -2694,10 +2960,10 @@ if STM32L4_TIM8_CHANNEL3 config STM32L4_TIM8_CH3MODE int "TIM8 Channel 3 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM8_CH3OUT bool "TIM8 Channel 3 Output" @@ -2724,10 +2990,10 @@ if STM32L4_TIM8_CHANNEL4 config STM32L4_TIM8_CH4MODE int "TIM8 Channel 4 Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM8_CH4OUT bool "TIM8 Channel 4 Output" @@ -2749,12 +3015,70 @@ config STM32L4_TIM8_CHANNEL If TIM8 is enabled for PWM usage, you also need specifies the timer output channel {1,..,4} +if STM32L4_TIM8_CHANNEL = 1 + +config STM32L4_TIM8_CH1OUT + bool "TIM8 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32L4_TIM8_CH1NOUT + bool "TIM8 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32L4_TIM8_CHANNEL = 1 + +if STM32L4_TIM8_CHANNEL = 2 + +config STM32L4_TIM8_CH2OUT + bool "TIM8 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config STM32L4_TIM8_CH2NOUT + bool "TIM8 Channel 2 Complementary Output" + default n + ---help--- + Enables channel 2 Complementary Output. + +endif # STM32L4_TIM8_CHANNEL = 2 + +if STM32L4_TIM8_CHANNEL = 3 + +config STM32L4_TIM8_CH3OUT + bool "TIM8 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +config STM32L4_TIM8_CH3NOUT + bool "TIM8 Channel 3 Complementary Output" + default n + ---help--- + Enables channel 3 Complementary Output. + +endif # STM32L4_TIM8_CHANNEL = 3 + +if STM32L4_TIM8_CHANNEL = 4 + +config STM32L4_TIM8_CH4OUT + bool "TIM8 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32L4_TIM8_CHANNEL = 4 + config STM32L4_TIM8_CHMODE int "TIM8 Channel Mode" - default 0 - range 0 5 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -2775,6 +3099,27 @@ config STM32L4_TIM15_PWM if STM32L4_TIM15_PWM +config STM32L4_TIM15_LOCK + int "TIM15 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 15 lock level configuration + +config STM32L4_TIM15_TDTS + int "TIM15 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 15 dead-time and sampling clock (t_DTS) division + +config STM32L4_TIM15_DEADTIME + int "TIM15 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 15 initial dead-time + if STM32L4_PWM_MULTICHAN config STM32L4_TIM15_CHANNEL1 @@ -2787,10 +3132,10 @@ if STM32L4_TIM15_CHANNEL1 config STM32L4_TIM15_CH1MODE int "TIM15 Channel 1 Mode" - default 0 - range 0 3 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM15_CH1OUT bool "TIM15 Channel 1 Output" @@ -2817,10 +3162,10 @@ if STM32L4_TIM15_CHANNEL2 config STM32L4_TIM15_CH2MODE int "TIM15 Channel 2 Mode" - default 0 - range 0 3 + default 6 + range 0 11 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM15_CH2OUT bool "TIM15 Channel 2 Output" @@ -2842,12 +3187,44 @@ config STM32L4_TIM15_CHANNEL If TIM15 is enabled for PWM usage, you also need specifies the timer output channel {1,2} +if STM32L4_TIM15_CHANNEL = 1 + +config STM32L4_TIM15_CH1OUT + bool "TIM15 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32L4_TIM15_CH1NOUT + bool "TIM15 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32L4_TIM15_CHANNEL = 1 + +if STM32L4_TIM15_CHANNEL = 2 + +config STM32L4_TIM15_CH2OUT + bool "TIM15 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config STM32L4_TIM15_CH2NOUT + bool "TIM15 Channel 2 Complementary Output" + default n + ---help--- + Enables channel 2 Complementary Output. + +endif # STM32L4_TIM15_CHANNEL = 2 + config STM32L4_TIM15_CHMODE int "TIM15 Channel Mode" - default 0 - range 0 3 + default 6 + range 0 9 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -2868,6 +3245,27 @@ config STM32L4_TIM16_PWM if STM32L4_TIM16_PWM +config STM32L4_TIM16_LOCK + int "TIM16 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 16 lock level configuration + +config STM32L4_TIM16_TDTS + int "TIM16 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 16 dead-time and sampling clock (t_DTS) division + +config STM32L4_TIM16_DEADTIME + int "TIM16 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 16 initial dead-time + if STM32L4_PWM_MULTICHAN config STM32L4_TIM16_CHANNEL1 @@ -2880,10 +3278,10 @@ if STM32L4_TIM16_CHANNEL1 config STM32L4_TIM16_CH1MODE int "TIM16 Channel 1 Mode" - default 0 - range 0 1 + default 6 + range 0 7 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM16_CH1OUT bool "TIM16 Channel 1 Output" @@ -2912,12 +3310,22 @@ config STM32L4_TIM16_CHANNEL If TIM16 is enabled for PWM usage, you also need specifies the timer output channel {1} +if STM32L4_TIM16_CHANNEL = 1 + +config STM32L4_TIM16_CH1OUT + bool "TIM16 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32L4_TIM16_CHANNEL = 1 + config STM32L4_TIM16_CHMODE int "TIM16 Channel Mode" - default 0 - range 0 1 + default 6 + range 0 7 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -2938,6 +3346,27 @@ config STM32L4_TIM17_PWM if STM32L4_TIM17_PWM +config STM32L4_TIM17_LOCK + int "TIM17 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 17 lock level configuration + +config STM32L4_TIM17_TDTS + int "TIM17 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 17 dead-time and sampling clock (t_DTS) division + +config STM32L4_TIM17_DEADTIME + int "TIM17 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 17 initial dead-time + if STM32L4_PWM_MULTICHAN config STM32L4_TIM17_CHANNEL1 @@ -2950,10 +3379,10 @@ if STM32L4_TIM17_CHANNEL1 config STM32L4_TIM17_CH1MODE int "TIM17 Channel 1 Mode" - default 0 - range 0 1 + default 6 + range 0 7 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. config STM32L4_TIM17_CH1OUT bool "TIM17 Channel 1 Output" @@ -2982,12 +3411,22 @@ config STM32L4_TIM17_CHANNEL If TIM17 is enabled for PWM usage, you also need specifies the timer output channel {1} +if STM32_TIM17_CHANNEL = 1 + +config STM32L4_TIM17_CH1OUT + bool "TIM17 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32L4_TIM17_CHANNEL = 1 + config STM32L4_TIM17_CHMODE int "TIM17 Channel Mode" - default 0 - range 0 1 + default 6 + range 0 7 ---help--- - Specifies the channel mode. + Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h. endif # !STM32L4_PWM_MULTICHAN @@ -3032,6 +3471,22 @@ config STM32L4_LPTIM1_CHANNEL If LPTIM1 is enabled for PWM usage, you also need specifies the timer output channel {1} +if STM32L4_LPTIM1_CHANNEL = 1 + +config STM32L4_LPTIM1_CH1OUT + bool "LPTIM1 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32L4_LPTIM1_CH1NOUT + bool "LPTIM1 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32L4_LPTIM1_CHANNEL = 1 + endif # !STM32L4_PWM_MULTICHAN endif # STM32L4_LPTIM1_PWM @@ -3075,6 +3530,22 @@ config STM32L4_LPTIM2_CHANNEL If LPTIM2 is enabled for PWM usage, you also need specifies the timer output channel {1} +if STM32L4_LPTIM2_CHANNEL = 1 + +config STM32L4_LPTIM2_CH1OUT + bool "LPTIM2 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32L4_LPTIM2_CH1NOUT + bool "LPTIM2 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32L4_LPTIM2_CHANNEL = 1 + endif # !STM32L4_PWM_MULTICHAN endif # STM32L4_LPTIM2_PWM @@ -3744,6 +4215,778 @@ config STM32L4_TIM8_CAP Timer devices may be used for different purposes. One special purpose is to capture input. +menu "STM32L4 TIMx Outputs Configuration" + +config STM32L4_TIM1_CH1POL + int "TIM1 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH1OUT + ---help--- + TIM1 Channel 1 output polarity + +config STM32L4_TIM1_CH1IDLE + int "TIM1 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH1OUT + ---help--- + TIM1 Channel 1 output IDLE + +config STM32L4_TIM1_CH1NPOL + int "TIM1 Channel 1 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH1NOUT + ---help--- + TIM1 Channel 1 Complementary Output polarity + +config STM32L4_TIM1_CH1NIDLE + int "TIM1 Channel 1 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH1NOUT + ---help--- + TIM1 Channel 1 Complementary Output IDLE + +config STM32L4_TIM1_CH2POL + int "TIM1 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH2OUT + ---help--- + TIM1 Channel 2 output polarity + +config STM32L4_TIM1_CH2IDLE + int "TIM1 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH2OUT + ---help--- + TIM1 Channel 2 output IDLE + +config STM32L4_TIM1_CH2NPOL + int "TIM1 Channel 2 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH2NOUT + ---help--- + TIM1 Channel 2 Complementary Output polarity + +config STM32L4_TIM1_CH2NIDLE + int "TIM1 Channel 2 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH2NOUT + ---help--- + TIM1 Channel 2 Complementary Output IDLE + +config STM32L4_TIM1_CH3POL + int "TIM1 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH3OUT + ---help--- + TIM1 Channel 3 output polarity + +config STM32L4_TIM1_CH3IDLE + int "TIM1 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH3OUT + ---help--- + TIM1 Channel 3 output IDLE + +config STM32L4_TIM1_CH3NPOL + int "TIM1 Channel 3 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH3NOUT + ---help--- + TIM1 Channel 3 Complementary Output polarity + +config STM32L4_TIM1_CH3NIDLE + int "TIM1 Channel 3 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH3NOUT + ---help--- + TIM1 Channel 3 Complementary Output IDLE + +config STM32L4_TIM1_CH4POL + int "TIM1 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH4OUT + ---help--- + TIM1 Channel 4 output polarity + +config STM32L4_TIM1_CH4IDLE + int "TIM1 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH4OUT + ---help--- + TIM1 Channel 4 output IDLE + +config STM32L4_TIM1_CH5POL + int "TIM1 Channel 5 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH5OUT + ---help--- + TIM1 Channel 5 output polarity + +config STM32L4_TIM1_CH5IDLE + int "TIM1 Channel 5 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH5OUT + ---help--- + TIM1 Channel 5 output IDLE + +config STM32L4_TIM1_CH6POL + int "TIM1 Channel 6 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH6OUT + ---help--- + TIM1 Channel 6 output polarity + +config STM32L4_TIM1_CH6IDLE + int "TIM1 Channel 6 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM1_CH6OUT + ---help--- + TIM1 Channel 6 output IDLE + +config STM32L4_TIM2_CH1POL + int "TIM2 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM2_CH1OUT + ---help--- + TIM2 Channel 1 output polarity + +config STM32L4_TIM2_CH1IDLE + int "TIM2 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM2_CH1OUT + ---help--- + TIM2 Channel 1 output IDLE + +config STM32L4_TIM2_CH2POL + int "TIM2 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM2_CH2OUT + ---help--- + TIM2 Channel 2 output polarity + +config STM32L4_TIM2_CH2IDLE + int "TIM2 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM2_CH2OUT + ---help--- + TIM2 Channel 2 output IDLE + +config STM32L4_TIM2_CH3POL + int "TIM2 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM2_CH3OUT + ---help--- + TIM2 Channel 3 output polarity + +config STM32L4_TIM2_CH3IDLE + int "TIM2 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM2_CH3OUT + ---help--- + TIM2 Channel 3 output IDLE + +config STM32L4_TIM2_CH4POL + int "TIM2 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM2_CH4OUT + ---help--- + TIM2 Channel 4 output polarity + +config STM32L4_TIM2_CH4IDLE + int "TIM2 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM2_CH4OUT + ---help--- + TIM2 Channel 4 output IDLE + +config STM32L4_TIM3_CH1POL + int "TIM3 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM3_CH1OUT + ---help--- + TIM3 Channel 1 output polarity + +config STM32L4_TIM3_CH1IDLE + int "TIM3 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM3_CH1OUT + ---help--- + TIM3 Channel 1 output IDLE + +config STM32L4_TIM3_CH2POL + int "TIM3 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM3_CH2OUT + ---help--- + TIM3 Channel 2 output polarity + +config STM32L4_TIM3_CH2IDLE + int "TIM3 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM3_CH2OUT + ---help--- + TIM3 Channel 2 output IDLE + +config STM32L4_TIM3_CH3POL + int "TIM3 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM3_CH3OUT + ---help--- + TIM3 Channel 3 output polarity + +config STM32L4_TIM3_CH3IDLE + int "TIM3 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM3_CH3OUT + ---help--- + TIM3 Channel 3 output IDLE + +config STM32L4_TIM3_CH4POL + int "TIM3 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM3_CH4OUT + ---help--- + TIM3 Channel 4 output polarity + +config STM32L4_TIM3_CH4IDLE + int "TIM3 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM3_CH4OUT + ---help--- + TIM3 Channel 4 output IDLE + +config STM32L4_TIM4_CH1POL + int "TIM4 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM4_CH1OUT + ---help--- + TIM4 Channel 1 output polarity + +config STM32L4_TIM4_CH1IDLE + int "TIM4 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM4_CH1OUT + ---help--- + TIM4 Channel 1 output IDLE + +config STM32L4_TIM4_CH2POL + int "TIM4 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM4_CH2OUT + ---help--- + TIM4 Channel 2 output polarity + +config STM32L4_TIM4_CH2IDLE + int "TIM4 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM4_CH2OUT + ---help--- + TIM4 Channel 2 output IDLE + +config STM32L4_TIM4_CH3POL + int "TIM4 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM4_CH3OUT + ---help--- + TIM4 Channel 3 output polarity + +config STM32L4_TIM4_CH3IDLE + int "TIM4 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM4_CH3OUT + ---help--- + TIM4 Channel 3 output IDLE + +config STM32L4_TIM4_CH4POL + int "TIM4 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM4_CH4OUT + ---help--- + TIM4 Channel 4 output polarity + +config STM32L4_TIM4_CH4IDLE + int "TIM4 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM4_CH4OUT + ---help--- + TIM4 Channel 4 output IDLE + +config STM32L4_TIM5_CH1POL + int "TIM5 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM5_CH1OUT + ---help--- + TIM5 Channel 1 output polarity + +config STM32L4_TIM5_CH1IDLE + int "TIM5 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM5_CH1OUT + ---help--- + TIM5 Channel 1 output IDLE + +config STM32L4_TIM5_CH2POL + int "TIM5 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM5_CH2OUT + ---help--- + TIM5 Channel 2 output polarity + +config STM32L4_TIM5_CH2IDLE + int "TIM5 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM5_CH2OUT + ---help--- + TIM5 Channel 2 output IDLE + +config STM32L4_TIM5_CH3POL + int "TIM5 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM5_CH3OUT + ---help--- + TIM5 Channel 3 output polarity + +config STM32L4_TIM5_CH3IDLE + int "TIM5 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM5_CH3OUT + ---help--- + TIM5 Channel 3 output IDLE + +config STM32L4_TIM5_CH4POL + int "TIM5 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM5_CH4OUT + ---help--- + TIM5 Channel 4 output polarity + +config STM32L4_TIM5_CH4IDLE + int "TIM5 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM5_CH4OUT + ---help--- + TIM5 Channel 4 output IDLE + +config STM32L4_TIM8_CH1POL + int "TIM8 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH1OUT + ---help--- + TIM8 Channel 1 output polarity + +config STM32L4_TIM8_CH1IDLE + int "TIM8 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH1OUT + ---help--- + TIM8 Channel 1 output IDLE + +config STM32L4_TIM8_CH1NPOL + int "TIM8 Channel 1 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH1NOUT + ---help--- + TIM8 Channel 1 Complementary Output polarity + +config STM32L4_TIM8_CH1NIDLE + int "TIM8 Channel 1 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH1NOUT + ---help--- + TIM8 Channel 1 Complementary Output IDLE + +config STM32L4_TIM8_CH2POL + int "TIM8 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH2OUT + ---help--- + TIM8 Channel 2 output polarity + +config STM32L4_TIM8_CH2IDLE + int "TIM8 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH2OUT + ---help--- + TIM8 Channel 2 output IDLE + +config STM32L4_TIM8_CH2NPOL + int "TIM8 Channel 2 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH2NOUT + ---help--- + TIM8 Channel 2 Complementary Output polarity + +config STM32L4_TIM8_CH2NIDLE + int "TIM8 Channel 2 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH2NOUT + ---help--- + TIM8 Channel 2 Complementary Output IDLE + +config STM32L4_TIM8_CH3POL + int "TIM8 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH3OUT + ---help--- + TIM8 Channel 3 output polarity + +config STM32L4_TIM8_CH3IDLE + int "TIM8 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH3OUT + ---help--- + TIM8 Channel 3 output IDLE + +config STM32L4_TIM8_CH3NPOL + int "TIM8 Channel 3 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH3NOUT + ---help--- + TIM8 Channel 3 Complementary Output polarity + +config STM32L4_TIM8_CH3NIDLE + int "TIM8 Channel 3 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH3NOUT + ---help--- + TIM8 Channel 3 Complementary Output IDLE + +config STM32L4_TIM8_CH4POL + int "TIM8 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH4OUT + ---help--- + TIM8 Channel 4 output polarity + +config STM32L4_TIM8_CH4IDLE + int "TIM8 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH4OUT + ---help--- + TIM8 Channel 4 output IDLE + +config STM32L4_TIM8_CH5POL + int "TIM8 Channel 5 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH5OUT + ---help--- + TIM8 Channel 5 output polarity + +config STM32L4_TIM8_CH5IDLE + int "TIM8 Channel 5 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH5OUT + ---help--- + TIM8 Channel 5 output IDLE + +config STM32L4_TIM8_CH6POL + int "TIM8 Channel 6 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH6OUT + ---help--- + TIM8 Channel 6 output polarity + +config STM32L4_TIM8_CH6IDLE + int "TIM8 Channel 6 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM8_CH6OUT + ---help--- + TIM8 Channel 6 output IDLE + +config STM32L4_TIM9_CH1POL + int "TIM9 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM9_CH1OUT + ---help--- + TIM9 Channel 1 output polarity + +config STM32L4_TIM9_CH1IDLE + int "TIM9 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM9_CH1OUT + ---help--- + TIM9 Channel 1 output IDLE + +config STM32L4_TIM9_CH2POL + int "TIM9 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM9_CH2OUT + ---help--- + TIM9 Channel 2 output polarity + +config STM32L4_TIM9_CH2IDLE + int "TIM9 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM9_CH2OUT + ---help--- + TIM9 Channel 2 output IDLE + +config STM32L4_TIM10_CH1POL + int "TIM10 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM10_CH1OUT + ---help--- + TIM10 Channel 1 output polarity + +config STM32L4_TIM10_CH1IDLE + int "TIM10 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM10_CH1OUT + ---help--- + TIM10 Channel 1 output IDLE + +config STM32L4_TIM11_CH1POL + int "TIM11 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM11_CH1OUT + ---help--- + TIM11 Channel 1 output polarity + +config STM32L4_TIM11_CH1IDLE + int "TIM11 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM11_CH1OUT + ---help--- + TIM11 Channel 1 output IDLE + +config STM32L4_TIM12_CH1POL + int "TIM12 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM12_CH1OUT + ---help--- + TIM12 Channel 1 output polarity + +config STM32L4_TIM12_CH1IDLE + int "TIM12 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM12_CH1OUT + ---help--- + TIM12 Channel 1 output IDLE + +config STM32L4_TIM12_CH2POL + int "TIM12 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM12_CH2OUT + ---help--- + TIM12 Channel 2 output polarity + +config STM32L4_TIM12_CH2IDLE + int "TIM12 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM12_CH2OUT + ---help--- + TIM12 Channel 2 output IDLE + +config STM32L4_TIM13_CH1POL + int "TIM13 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM13_CH1OUT + ---help--- + TIM13 Channel 1 output polarity + +config STM32L4_TIM13_CH1IDLE + int "TIM13 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM13_CH1OUT + ---help--- + TIM13 Channel 1 output IDLE + +config STM32L4_TIM14_CH1POL + int "TIM14 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM14_CH1OUT + ---help--- + TIM14 Channel 1 output polarity + +config STM32L4_TIM14_CH1IDLE + int "TIM14 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM14_CH1OUT + ---help--- + TIM14 Channel 1 output IDLE + +config STM32L4_TIM15_CH1POL + int "TIM15 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM15_CH1OUT + ---help--- + TIM15 Channel 1 output polarity + +config STM32L4_TIM15_CH1IDLE + int "TIM15 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM15_CH1OUT + ---help--- + TIM15 Channel 1 output IDLE + +config STM32L4_TIM15_CH1NPOL + int "TIM15 Channel 1 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM15_CH1NOUT + ---help--- + TIM15 Channel 1 Complementary Output polarity + +config STM32L4_TIM15_CH1NIDLE + int "TIM15 Channel 1 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM15_CH1NOUT + ---help--- + TIM15 Channel 1 Complementary Output IDLE + +config STM32L4_TIM15_CH2POL + int "TIM15 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM15_CH2OUT + ---help--- + TIM15 Channel 2 output polarity + +config STM32L4_TIM15_CH2IDLE + int "TIM15 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM15_CH2OUT + ---help--- + TIM15 Channel 2 output IDLE + +config STM32L4_TIM15_CH2NPOL + int "TIM15 Channel 2 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM15_CH2NOUT + ---help--- + TIM15 Channel 2 Complementary Output polarity + +config STM32L4_TIM15_CH2NIDLE + int "TIM15 Channel 2 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM15_CH2NOUT + ---help--- + TIM15 Channel 2 Complementary Output IDLE + +config STM32L4_TIM16_CH1POL + int "TIM16 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM16_CH1OUT + ---help--- + TIM16 Channel 1 output polarity + +config STM32L4_TIM16_CH1IDLE + int "TIM16 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM16_CH1OUT + ---help--- + TIM16 Channel 1 output IDLE + +config STM32L4_TIM17_CH1POL + int "TIM17 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32L4_TIM17_CH1OUT + ---help--- + TIM17 Channel 1 output polarity + +config STM32L4_TIM17_CH1IDLE + int "TIM17 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32L4_TIM17_CH1OUT + ---help--- + TIM17 Channel 1 output IDLE + +endmenu #STM32L4 TIMx Outputs Configuration + endmenu # Timer Configuration menu "ADC Configuration" diff --git a/arch/arm/src/stm32l4/stm32l4_pwm.c b/arch/arm/src/stm32l4/stm32l4_pwm.c index 84b36eb5e6b..d9d34e9693d 100644 --- a/arch/arm/src/stm32l4/stm32l4_pwm.c +++ b/arch/arm/src/stm32l4/stm32l4_pwm.c @@ -77,12 +77,15 @@ /* The following definitions are used to identify the various time types */ -#define TIMTYPE_BASIC 0 /* Basic timers: TIM6,7 */ -#define TIMTYPE_GENERAL16 1 /* General 16-bit timers: TIM3,4 */ -#define TIMTYPE_COUNTUP16 2 /* General 16-bit count-up timers: TIM15-17 */ -#define TIMTYPE_GENERAL32 3 /* General 32-bit timers: TIM2,5 */ -#define TIMTYPE_ADVANCED 4 /* Advanced timers: TIM1,8 */ -#define TIMTYPE_LOWPOWER 5 /* Low Power timers: LPTIM1,2 */ +#define TIMTYPE_BASIC 0 /* Basic timers: TIM6,7 */ +#define TIMTYPE_GENERAL16 1 /* General 16-bit timers: TIM3,4 */ +#define TIMTYPE_COUNTUP16 2 /* General 16-bit count-up timers: TIM15-17 */ +#define TIMTYPE_COUNTUP16_N 3 /* General 16-bit count-up timers with + * complementary outptus + */ +#define TIMTYPE_GENERAL32 4 /* General 32-bit timers: TIM2,5 */ +#define TIMTYPE_ADVANCED 5 /* Advanced timers: TIM1,8 */ +#define TIMTYPE_LOWPOWER 6 /* Low Power timers: LPTIM1,2 */ #define TIMTYPE_TIM1 TIMTYPE_ADVANCED #define TIMTYPE_TIM2 TIMTYPE_GENERAL32 @@ -92,12 +95,60 @@ #define TIMTYPE_TIM6 TIMTYPE_BASIC #define TIMTYPE_TIM7 TIMTYPE_BASIC #define TIMTYPE_TIM8 TIMTYPE_ADVANCED -#define TIMTYPE_TIM15 TIMTYPE_COUNTUP16 -#define TIMTYPE_TIM16 TIMTYPE_COUNTUP16 -#define TIMTYPE_TIM17 TIMTYPE_COUNTUP16 +#define TIMTYPE_TIM15 TIMTYPE_COUNTUP16_N /* Treated as ADVTIM */ +#define TIMTYPE_TIM16 TIMTYPE_COUNTUP16_N /* Treated as ADVTIM */ +#define TIMTYPE_TIM17 TIMTYPE_COUNTUP16_N /* Treated as ADVTIM */ #define TIMTYPE_LPTIM1 TIMTYPE_LOWPOWER #define TIMTYPE_LPTIM2 TIMTYPE_LOWPOWER +/* Advanced Timer support + * NOTE: TIM15-17 are not ADVTIM but they support most of the + * ADVTIM functionality. The main difference is the number of + * supported capture/compare. + */ + +#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM) || \ + defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \ + defined(CONFIG_STM32L4_TIM17_PWM) +# define HAVE_ADVTIM +#else +# undef HAVE_ADVTIM +#endif + +/* Low power Timer support */ + +#if defined(CONFIG_STM32L4_LPTIM1_PWM) || defined(CONFIG_STM32L4_LPTIM2_PWM) +# define HAVE_LPTIM +#else +# undef HAVE_LPTIM +#endif + +/* Pulsecount support */ + +#ifdef CONFIG_PWM_PULSECOUNT +# ifndef HAVE_ADVTIM +# error "PWM_PULSECOUNT requires HAVE_ADVTIM" +# endif +# if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM) +# define HAVE_PWM_INTERRUPT +# endif +#endif + +/* Synchronisation support */ + +#ifdef CONFIG_STM32L4_PWM_TRGO +# define HAVE_TRGO +#endif + +/* Break support */ + +#if defined(CONFIG_STM32L4_TIM1_BREAK1) || defined(CONFIG_STM32L4_TIM1_BREAK2) || \ + defined(CONFIG_STM32L4_TIM8_BREAK1) || defined(CONFIG_STM32L4_TIM8_BREAK2) || \ + defined(CONFIG_STM32L4_TIM15_BREAK1) || defined(CONFIG_STM32L4_TIM16_BREAK1) || \ + defined(CONFIG_STM32L4_TIM17_BREAK1) +# defined HAVE_BREAK +#endif + /* Debug ********************************************************************/ #ifdef CONFIG_DEBUG_PWM_INFO @@ -110,44 +161,56 @@ * Private Types ****************************************************************************/ -enum stm32l4_timmode_e +/* PWM output configuration */ + +struct stm32l4_pwm_out_s { - STM32L4_TIMMODE_COUNTUP = 0, - STM32L4_TIMMODE_COUNTDOWN = 1, - STM32L4_TIMMODE_CENTER1 = 2, - STM32L4_TIMMODE_CENTER2 = 3, - STM32L4_TIMMODE_CENTER3 = 4, + uint8_t in_use:1; /* Output in use */ + uint8_t pol:1; /* Polarity. Default: positive */ + uint8_t idle:1; /* Idle state. Default: inactive */ + uint8_t _res:5; /* Reserved */ + uint32_t pincfg; /* Output pin configuration */ }; -enum stm32l4_chanmode_e -{ - STM32L4_CHANMODE_PWM1 = 0, - STM32L4_CHANMODE_PWM2 = 1, - STM32L4_CHANMODE_COMBINED1 = 2, - STM32L4_CHANMODE_COMBINED2 = 3, - STM32L4_CHANMODE_ASYMMETRIC1 = 4, - STM32L4_CHANMODE_ASYMMETRIC2 = 5, -}; +/* PWM channel configuration */ struct stm32l4_pwmchan_s { - uint8_t channel; /* Timer output channel: {1,..4} */ - enum stm32l4_chanmode_e mode; - uint32_t pincfg; /* Output pin configuration */ - uint32_t npincfg; /* Complementary output pin configuration - * (only TIM1,8 CH1-3 and TIM15,16,17 CH1) - */ + uint8_t channel:4; /* Timer output channel: {1,..4} */ + uint8_t mode:4; /* PWM channel mode (see stm32l4_pwm_chanmode_e) */ + struct stm32l4_pwm_out_s out1; /* PWM output configuration */ +#ifdef HAVE_BREAK + struct stm32l4_pwm_break_s brk; /* PWM break configuration */ +#endif +#ifdef HAVE_PWM_COMPLEMENTARY + struct stm32l4_pwm_out_s out2; /* PWM complementary output configuration */ +#endif }; /* This structure represents the state of one PWM timer */ struct stm32l4_pwmtimer_s { - FAR const struct pwm_ops_s *ops; /* PWM operations */ - struct stm32l4_pwmchan_s channels[PWM_NCHANNELS]; - uint8_t timid; /* Timer ID {1,...,17} */ - uint8_t timtype; /* See the TIMTYPE_* definitions */ - enum stm32l4_timmode_e mode; + FAR const struct pwm_ops_s *ops; /* PWM operations */ +#ifdef CONFIG_STM32L4_PWM_LL_OPS + FAR const struct stm32l4_pwm_ops_s *llops; /* Low-level PWM ops */ +#endif + FAR struct stm32l4_pwmchan_s *channels; /* Channels configuration */ + uint8_t timid:5; /* Timer ID {1,...,17} */ + uint8_t chan_num:3; /* Number of configured channels */ + uint8_t timtype:3; /* See the TIMTYPE_* definitions */ + uint8_t mode:3; /* Timer mode (see stm32l4_pwm_tim_mode_e) */ + uint8_t lock:2; /* TODO: Lock configuration */ + uint8_t t_dts:3; /* Clock division for t_DTS */ + uint8_t _res:5; /* Reserved */ +#ifdef HAVE_PWM_COMPLEMENTARY + uint8_t deadtime; /* Dead-time value */ +#endif +#ifdef HAVE_TRGO + uint8_t trgo; /* TRGO configuration: + * 4 LSB = TRGO, 4 MSB = TRGO2 + */ +#endif #ifdef CONFIG_PWM_PULSECOUNT uint8_t irq; /* Timer update IRQ */ uint8_t prev; /* The previous value of the RCR (pre-loaded) */ @@ -157,7 +220,7 @@ struct stm32l4_pwmtimer_s uint32_t frequency; /* Current frequency setting */ #endif uint32_t base; /* The base address of the timer */ - uint32_t pclk; /* The frequency of the peripheral clock + uint32_t pclk; /* Frequency of the peripheral clock * that drives the timer module. */ #ifdef CONFIG_PWM_PULSECOUNT FAR void *handle; /* Handle used for upper-half callback */ @@ -170,55 +233,84 @@ struct stm32l4_pwmtimer_s /* Register access */ -static uint16_t stm32l4pwm_getreg(struct stm32l4_pwmtimer_s *priv, - int offset); -static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset, - uint16_t value); +static uint16_t pwm_getreg(struct stm32l4_pwmtimer_s *priv, int offset); +static void pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset, + uint16_t value); +static void pwm_modifyreg(struct stm32l4_pwmtimer_s *priv, uint32_t offset, + uint32_t clearbits, uint32_t setbits); #ifdef CONFIG_DEBUG_PWM_INFO -static void stm32l4pwm_dumpregs(struct stm32l4_pwmtimer_s *priv, - const char *msg); +static void pwm_dumpregs(FAR struct pwm_lowerhalf_s *dev, + FAR const char *msg); #else -# define stm32l4pwm_dumpregs(priv,msg) +# define pwm_dumpregs(priv,msg) #endif /* Timer management */ -static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, - FAR const struct pwm_info_s *info); - -static int stm32l4pwm_lptimer(FAR struct stm32l4_pwmtimer_s *priv, - FAR const struct pwm_info_s *info); - -#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32L4_TIM1_PWM) || \ - defined(CONFIG_STM32L4_TIM8_PWM)) -static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv); -#if defined(CONFIG_STM32L4_TIM1_PWM) -static int stm32l4pwm_tim1interrupt(int irq, void *context, FAR void *arg); +#ifdef CONFIG_PWM_PULSECOUNT +static int pwm_pulsecount_timer(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info); +#else +static int pwm_timer(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info); +# ifdef HAVE_LPTIM +static int pwm_lptimer(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info); +# endif +static int pwm_configure(FAR struct pwm_lowerhalf_s *dev); #endif -#if defined(CONFIG_STM32L4_TIM8_PWM) -static int stm32l4pwm_tim8interrupt(int irq, void *context, FAR void *arg); +static int pwm_soft_break(FAR struct pwm_lowerhalf_s *dev, bool state); /* REVISIT: valid for all timers? */ +static int pwm_ccr_update(FAR struct pwm_lowerhalf_s *dev, uint8_t index, + uint32_t ccr); +static int pwm_mode_configure(FAR struct pwm_lowerhalf_s *dev, + uint8_t channel, uint32_t mode); +#ifdef CONFIG_STM32L4_PWM_LL_OPS +static uint32_t pwm_ccr_get(FAR struct pwm_lowerhalf_s *dev, uint8_t index); #endif -static uint8_t stm32l4pwm_pulsecount(uint32_t count); +static int pwm_arr_update(FAR struct pwm_lowerhalf_s *dev, uint32_t arr); +static uint32_t pwm_arr_get(FAR struct pwm_lowerhalf_s *dev); +static int pwm_outputs_enable(FAR struct pwm_lowerhalf_s *dev, + uint16_t outputs, bool state); +static int pwm_soft_update(FAR struct pwm_lowerhalf_s *dev); +static int pwm_frequency_update(FAR struct pwm_lowerhalf_s *dev, + uint32_t frequency); +static int pwm_timer_enable(FAR struct pwm_lowerhalf_s *dev, bool state); +#if defined(HAVE_PWM_COMPLEMENTARY) && defined(CONFIG_STM32L4_PWM_LL_OPS) +static int pwm_deadtime_update(FAR struct pwm_lowerhalf_s *dev, uint8_t dt); +#endif +#ifdef CONFIG_STM32L4_PWM_LL_OPS +static uint32_t pwm_ccr_get(FAR struct pwm_lowerhalf_s *dev, uint8_t index); +#endif + +#ifdef HAVE_PWM_INTERRUPT +static int pwm_interrupt(FAR struct pwm_lowerhalf_s *dev); +# ifdef CONFIG_STM32L4_TIM1_PWM +static int pwm_tim1interrupt(int irq, void *context, FAR void *arg); +# endif +# ifdef CONFIG_STM32L4_TIM8_PWM +static int pwm_tim8interrupt(int irq, void *context, FAR void *arg); +# endif +static uint8_t pwm_pulsecount(uint32_t count); #endif /* PWM driver methods */ -static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev); -static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev); +static int pwm_setup(FAR struct pwm_lowerhalf_s *dev); +static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev); #ifdef CONFIG_PWM_PULSECOUNT -static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, - FAR const struct pwm_info_s *info, - FAR void *handle); +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info, + FAR void *handle); #else -static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, - FAR const struct pwm_info_s *info); +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info); #endif -static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev); -static int stm32l4pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, - int cmd, unsigned long arg); +static int pwm_stop(FAR struct pwm_lowerhalf_s *dev); +static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, + int cmd, unsigned long arg); /**************************************************************************** * Private Data @@ -230,416 +322,1032 @@ static int stm32l4pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, static const struct pwm_ops_s g_pwmops = { - .setup = stm32l4pwm_setup, - .shutdown = stm32l4pwm_shutdown, - .start = stm32l4pwm_start, - .stop = stm32l4pwm_stop, - .ioctl = stm32l4pwm_ioctl, + .setup = pwm_setup, + .shutdown = pwm_shutdown, + .start = pwm_start, + .stop = pwm_stop, + .ioctl = pwm_ioctl, }; +#ifdef CONFIG_STM32L4_PWM_LL_OPS +static const struct stm32l4_pwm_ops_s g_llpwmops = +{ + .configure = pwm_configure, + .soft_break = pwm_soft_break, + .ccr_update = pwm_ccr_update, + .mode_update = pwm_mode_configure, + .ccr_get = pwm_ccr_get, + .arr_update = pwm_arr_update, + .arr_get = pwm_arr_get, + .outputs_enable = pwm_outputs_enable, + .soft_update = pwm_soft_update, + .freq_update = pwm_frequency_update, + .tim_enable = pwm_timer_enable, +# ifdef CONFIG_DEBUG_PWM_INFO + .dump_regs = pwm_dumpregs, +# endif +# ifdef HAVE_PWM_COMPLEMENTARY + .dt_update = pwm_deadtime_update, +# endif +}; +#endif + #ifdef CONFIG_STM32L4_TIM1_PWM + +static struct stm32l4_pwmchan_s g_pwm1channels[] = +{ + /* TIM1 has 4 channels, 4 complementary */ + +#ifdef CONFIG_STM32L4_TIM1_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM1_CH1MODE, +#ifdef HAVE_BREAK + .brk = + { +#ifdef CONFIG_STM32L4_TIM1_BREAK1 + .en1 = 1, + .pol1 = CONFIG_STM32L4_TIM1_BRK1POL, +#endif +#ifdef CONFIG_STM32L4_TIM1_BREAK2 + .en2 = 1, + .pol2 = CONFIG_STM32L4_TIM1_BRK2POL, + .flt2 = CONFIG_STM32L4_TIM1_BRK2FLT, +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM1_CH1POL, + .idle = CONFIG_STM32L4_TIM1_CH1IDLE, + .pincfg = PWM_TIM1_CH1CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CH1NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM1_CH1NPOL, + .idle = CONFIG_STM32L4_TIM1_CH1NIDLE, + .pincfg = PWM_TIM1_CH1NCFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CHANNEL2 + { + .channel = 2, + .mode = CONFIG_STM32L4_TIM1_CH2MODE, +#ifdef CONFIG_STM32L4_TIM1_CH2OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM1_CH2POL, + .idle = CONFIG_STM32L4_TIM1_CH2IDLE, + .pincfg = PWM_TIM1_CH2CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CH2NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM1_CH2NPOL, + .idle = CONFIG_STM32L4_TIM1_CH2NIDLE, + .pincfg = PWM_TIM1_CH2NCFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CHANNEL3 + { + .channel = 3, + .mode = CONFIG_STM32L4_TIM1_CH3MODE, +#ifdef CONFIG_STM32L4_TIM1_CH3OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM1_CH3POL, + .idle = CONFIG_STM32L4_TIM1_CH3IDLE, + .pincfg = PWM_TIM1_CH3CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CH3NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM1_CH3NPOL, + .idle = CONFIG_STM32L4_TIM1_CH3NIDLE, + .pincfg = PWM_TIM1_CH3NCFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CHANNEL4 + { + .channel = 4, + .mode = CONFIG_STM32L4_TIM1_CH4MODE, +#ifdef CONFIG_STM32L4_TIM1_CH4OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4L4_TIM1_CH4POL, + .idle = CONFIG_STM32L4L4_TIM1_CH4IDLE, + .pincfg = PWM_TIM1_CH4CFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CHANNEL5 + { + .channel = 5, + .mode = CONFIG_STM32L4_TIM1_CH5MODE, +#ifdef CONFIG_STM32L4_TIM1_CH5OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM1_CH5POL, + .idle = CONFIG_STM32L4_TIM1_CH5IDLE, + .pincfg = 0, /* No available externaly */ + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM1_CHANNEL6 + { + .channel = 6, + .mode = CONFIG_STM32L4_TIM1_CH6MODE, +#ifdef CONFIG_STM32L4_TIM1_CH6OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM1_CH6POL, + .idle = CONFIG_STM32L4_TIM1_CH6IDLE, + .pincfg = 0, /* No available externaly */ + } +#endif + } +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm1dev = { .ops = &g_pwmops, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, +#endif .timid = 1, - .channels = - { -#ifdef CONFIG_STM32L4_TIM1_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM1_CH1CFG, - .mode = CONFIG_STM32L4_TIM1_CH1MODE, - .npincfg = PWM_TIM1_CH1NCFG, - }, -#endif -#ifdef CONFIG_STM32L4_TIM1_CHANNEL2 - { - .channel = 2, - .pincfg = PWM_TIM1_CH2CFG, - .mode = CONFIG_STM32L4_TIM1_CH2MODE, - .npincfg = PWM_TIM1_CH2NCFG, - }, -#endif -#ifdef CONFIG_STM32L4_TIM1_CHANNEL3 - { - .channel = 3, - .pincfg = PWM_TIM1_CH3CFG, - .mode = CONFIG_STM32L4_TIM1_CH3MODE, - .npincfg = PWM_TIM1_CH3NCFG, - }, -#endif -#ifdef CONFIG_STM32L4_TIM1_CHANNEL4 - { - .channel = 4, - .pincfg = PWM_TIM1_CH4CFG, - .mode = CONFIG_STM32L4_TIM1_CH4MODE, - .npincfg = 0, - }, -#endif - }, + .chan_num = PWM_TIM1_NCHANNELS, + .channels = g_pwm1channels, .timtype = TIMTYPE_TIM1, .mode = CONFIG_STM32L4_TIM1_MODE, + .lock = CONFIG_STM32L4_TIM1_LOCK, + .t_dts = CONFIG_STM32L4_TIM1_TDTS, +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = CONFIG_STM32L4_TIM1_DEADTIME, +#endif +#if defined(HAVE_TRGO) && defined(STM32L4_TIM1_TRGO) + .trgo = STM32L4_TIM1_TRGO, +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM1UP, #endif .base = STM32L4_TIM1_BASE, .pclk = STM32L4_APB2_TIM1_CLKIN, }; -#endif +#endif /* CONFIG_STM32L4_TIM1_PWM */ #ifdef CONFIG_STM32L4_TIM2_PWM + +static struct stm32l4_pwmchan_s g_pwm2channels[] = +{ + /* TIM2 has 4 channels */ + +#ifdef CONFIG_STM32L4_TIM2_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM2_CH1MODE, +#ifdef CONFIG_STM32L4_TIM2_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM2_CH1POL, + .idle = CONFIG_STM32L4_TIM2_CH1IDLE, + .pincfg = PWM_TIM2_CH1CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM2_CHANNEL2 + { + .channel = 2, + .mode = CONFIG_STM32L4_TIM2_CH2MODE, +#ifdef CONFIG_STM32L4_TIM2_CH2OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM2_CH2POL, + .idle = CONFIG_STM32L4_TIM2_CH2IDLE, + .pincfg = PWM_TIM2_CH2CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM2_CHANNEL3 + { + .channel = 3, + .mode = CONFIG_STM32L4_TIM2_CH3MODE, +#ifdef CONFIG_STM32L4_TIM2_CH3OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM2_CH3POL, + .idle = CONFIG_STM32L4_TIM2_CH3IDLE, + .pincfg = PWM_TIM2_CH3CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM2_CHANNEL4 + { + .channel = 4, + .mode = CONFIG_STM32L4_TIM2_CH4MODE, +#ifdef CONFIG_STM32L4_TIM2_CH4OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM2_CH4POL, + .idle = CONFIG_STM32L4_TIM2_CH4IDLE, + .pincfg = PWM_TIM2_CH4CFG, + } +#endif + /* No complementary outputs */ + } +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm2dev = { .ops = &g_pwmops, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, +#endif .timid = 2, - .channels = - { -#ifdef CONFIG_STM32L4_TIM2_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM2_CH1CFG, - .mode = CONFIG_STM32L4_TIM2_CH1MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM2_CHANNEL2 - { - .channel = 2, - .pincfg = PWM_TIM2_CH2CFG, - .mode = CONFIG_STM32L4_TIM2_CH2MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM2_CHANNEL3 - { - .channel = 3, - .pincfg = PWM_TIM2_CH3CFG, - .mode = CONFIG_STM32L4_TIM2_CH3MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM2_CHANNEL4 - { - .channel = 4, - .pincfg = PWM_TIM2_CH4CFG, - .mode = CONFIG_STM32L4_TIM2_CH4MODE, - .npincfg = 0, - }, -#endif - }, + .chan_num = PWM_TIM2_NCHANNELS, + .channels = g_pwm2channels, .timtype = TIMTYPE_TIM2, .mode = CONFIG_STM32L4_TIM2_MODE, + .lock = 0, /* No lock */ + .t_dts = 0, /* No t_dts */ +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = 0, /* No deadtime */ +#endif +#if defined(HAVE_TRGO) && defined(STM32L4_TIM2_TRGO) + .trgo = STM32L4_TIM2_TRGO, +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM2, #endif .base = STM32L4_TIM2_BASE, .pclk = STM32L4_APB1_TIM2_CLKIN, }; -#endif + +#endif /* CONFIG_STM32L4_TIM2_PWM */ #ifdef CONFIG_STM32L4_TIM3_PWM + +static struct stm32l4_pwmchan_s g_pwm3channels[] = +{ + /* TIM3 has 4 channels */ + +#ifdef CONFIG_STM32L4_TIM3_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM3_CH1MODE, +#ifdef CONFIG_STM32L4_TIM3_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM3_CH1POL, + .idle = CONFIG_STM32L4_TIM3_CH1IDLE, + .pincfg = PWM_TIM3_CH1CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM3_CHANNEL2 + { + .channel = 2, + .mode = CONFIG_STM32L4_TIM3_CH2MODE, +#ifdef CONFIG_STM32L4_TIM3_CH2OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM3_CH2POL, + .idle = CONFIG_STM32L4_TIM3_CH2IDLE, + .pincfg = PWM_TIM3_CH2CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM3_CHANNEL3 + { + .channel = 3, + .mode = CONFIG_STM32L4_TIM3_CH3MODE, +#ifdef CONFIG_STM32L4_TIM3_CH3OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM3_CH3POL, + .idle = CONFIG_STM32L4_TIM3_CH3IDLE, + .pincfg = PWM_TIM3_CH3CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM3_CHANNEL4 + { + .channel = 4, + .mode = CONFIG_STM32L4_TIM3_CH4MODE, +#ifdef CONFIG_STM32L4_TIM3_CH4OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM3_CH4POL, + .idle = CONFIG_STM32L4_TIM3_CH4IDLE, + .pincfg = PWM_TIM3_CH4CFG, + } +#endif + /* No complementary outputs */ + } +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm3dev = { .ops = &g_pwmops, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, +#endif .timid = 3, - .channels = - { -#ifdef CONFIG_STM32L4_TIM3_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM3_CH1CFG, - .mode = CONFIG_STM32L4_TIM3_CH1MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM3_CHANNEL2 - { - .channel = 2, - .pincfg = PWM_TIM3_CH2CFG, - .mode = CONFIG_STM32L4_TIM3_CH2MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM3_CHANNEL3 - { - .channel = 3, - .pincfg = PWM_TIM3_CH3CFG, - .mode = CONFIG_STM32L4_TIM3_CH3MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM3_CHANNEL4 - { - .channel = 4, - .pincfg = PWM_TIM3_CH4CFG, - .mode = CONFIG_STM32L4_TIM3_CH4MODE, - .npincfg = 0, - }, -#endif - }, + .chan_num = PWM_TIM3_NCHANNELS, + .channels = g_pwm3channels, .timtype = TIMTYPE_TIM3, .mode = CONFIG_STM32L4_TIM3_MODE, + .lock = 0, /* No lock */ + .t_dts = 0, /* No t_dts */ +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = 0, /* No deadtime */ +#endif +#if defined(HAVE_TRGO) && defined(STM32L4_TIM3_TRGO) + .trgo = STM32L4_TIM3_TRGO, +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM3, #endif .base = STM32L4_TIM3_BASE, .pclk = STM32L4_APB1_TIM3_CLKIN, }; -#endif +#endif /* CONFIG_STM32L4_TIM3_PWM */ #ifdef CONFIG_STM32L4_TIM4_PWM + +static struct stm32l4_pwmchan_s g_pwm4channels[] = +{ + /* TIM4 has 4 channels */ + +#ifdef CONFIG_STM32L4_TIM4_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM4_CH1MODE, +#ifdef CONFIG_STM32L4_TIM4_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM4_CH1POL, + .idle = CONFIG_STM32L4_TIM4_CH1IDLE, + .pincfg = PWM_TIM4_CH1CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM4_CHANNEL2 + { + .channel = 2, + .mode = CONFIG_STM32L4_TIM4_CH2MODE, +#ifdef CONFIG_STM32L4_TIM4_CH2OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM4_CH2POL, + .idle = CONFIG_STM32L4_TIM4_CH2IDLE, + .pincfg = PWM_TIM4_CH2CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM4_CHANNEL3 + { + .channel = 3, + .mode = CONFIG_STM32L4_TIM4_CH3MODE, +#ifdef CONFIG_STM32L4_TIM4_CH3OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM4_CH3POL, + .idle = CONFIG_STM32L4_TIM4_CH3IDLE, + .pincfg = PWM_TIM4_CH3CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM4_CHANNEL4 + { + .channel = 4, + .mode = CONFIG_STM32L4_TIM4_CH4MODE, +#ifdef CONFIG_STM32L4_TIM4_CH4OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM4_CH4POL, + .idle = CONFIG_STM32L4_TIM4_CH4IDLE, + .pincfg = PWM_TIM4_CH4CFG, + } +#endif + /* No complementary outputs */ + } +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm4dev = { .ops = &g_pwmops, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, +#endif .timid = 4, - .channels = - { -#ifdef CONFIG_STM32L4_TIM4_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM4_CH1CFG, - .mode = CONFIG_STM32L4_TIM4_CH1MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM4_CHANNEL2 - { - .channel = 2, - .pincfg = PWM_TIM4_CH2CFG, - .mode = CONFIG_STM32L4_TIM4_CH2MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM4_CHANNEL3 - { - .channel = 3, - .pincfg = PWM_TIM4_CH3CFG, - .mode = CONFIG_STM32L4_TIM4_CH3MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM4_CHANNEL4 - { - .channel = 4, - .pincfg = PWM_TIM4_CH4CFG, - .mode = CONFIG_STM32L4_TIM4_CH4MODE, - .npincfg = 0, - }, -#endif - }, + .chan_num = PWM_TIM4_NCHANNELS, + .channels = g_pwm4channels, .timtype = TIMTYPE_TIM4, .mode = CONFIG_STM32L4_TIM4_MODE, + .lock = 0, /* No lock */ + .t_dts = 0, /* No t_dts */ +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = 0, /* No deadtime */ +#endif +#if defined(HAVE_TRGO) && defined(STM32L4_TIM4_TRGO) + .trgo = STM32L4_TIM4_TRGO, +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM4, #endif .base = STM32L4_TIM4_BASE, .pclk = STM32L4_APB1_TIM4_CLKIN, }; -#endif +#endif /* CONFIG_STM32L4_TIM4_PWM */ #ifdef CONFIG_STM32L4_TIM5_PWM + +static struct stm32l4_pwmchan_s g_pwm5channels[] = +{ + /* TIM5 has 4 channels */ + +#ifdef CONFIG_STM32L4_TIM5_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM5_CH1MODE, +#ifdef CONFIG_STM32L4_TIM5_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM5_CH1POL, + .idle = CONFIG_STM32L4_TIM5_CH1IDLE, + .pincfg = PWM_TIM5_CH1CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM5_CHANNEL2 + { + .channel = 2, + .mode = CONFIG_STM32L4_TIM5_CH2MODE, +#ifdef CONFIG_STM32L4_TIM5_CH2OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM5_CH2POL, + .idle = CONFIG_STM32L4_TIM5_CH2IDLE, + .pincfg = PWM_TIM5_CH2CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM5_CHANNEL3 + { + .channel = 3, + .mode = CONFIG_STM32L4_TIM5_CH3MODE, +#ifdef CONFIG_STM32L4_TIM5_CH3OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM5_CH3POL, + .idle = CONFIG_STM32L4_TIM5_CH3IDLE, + .pincfg = PWM_TIM5_CH3CFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM5_CHANNEL4 + { + .channel = 4, + .mode = CONFIG_STM32L4_TIM5_CH4MODE, +#ifdef CONFIG_STM32L4_TIM5_CH4OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM5_CH4POL, + .idle = CONFIG_STM32L4_TIM5_CH4IDLE, + .pincfg = PWM_TIM5_CH4CFG, + } +#endif + }, +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm5dev = { .ops = &g_pwmops, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, +#endif .timid = 5, - .channels = - { -#ifdef CONFIG_STM32L4_TIM5_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM5_CH1CFG, - .mode = CONFIG_STM32L4_TIM5_CH1MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM5_CHANNEL2 - { - .channel = 2, - .pincfg = PWM_TIM5_CH2CFG, - .mode = CONFIG_STM32L4_TIM5_CH2MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM5_CHANNEL3 - { - .channel = 3, - .pincfg = PWM_TIM5_CH3CFG, - .mode = CONFIG_STM32L4_TIM5_CH3MODE, - .npincfg = 0, - }, -#endif -#ifdef CONFIG_STM32L4_TIM5_CHANNEL4 - { - .channel = 4, - .pincfg = PWM_TIM5_CH4CFG, - .mode = CONFIG_STM32L4_TIM5_CH4MODE, - .npincfg = 0, - }, -#endif - }, + .chan_num = PWM_TIM5_NCHANNELS, + .channels = g_pwm5channels, .timtype = TIMTYPE_TIM5, .mode = CONFIG_STM32L4_TIM5_MODE, + .lock = 0, /* No lock */ + .t_dts = 0, /* No t_dts */ +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = 0, /* No deadtime */ +#endif +#if defined(HAVE_TRGO) && defined(STM32L4_TIM5_TRGO) + .trgo = STM32L4_TIM5_TRGO +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM5, #endif .base = STM32L4_TIM5_BASE, .pclk = STM32L4_APB1_TIM5_CLKIN, }; -#endif +#endif /* CONFIG_STM32L4_TIM5_PWM */ #ifdef CONFIG_STM32L4_TIM8_PWM + +static struct stm32l4_pwmchan_s g_pwm8channels[] = +{ + /* TIM8 has 4 channels, 4 complementary */ + +#ifdef CONFIG_STM32L4_TIM8_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM8_CH1MODE, +#ifdef HAVE_BREAK + .brk = + { +#ifdef CONFIG_STM32L4_TIM8_BREAK1 + .en1 = 1, + .pol1 = CONFIG_STM32L4_TIM8_BRK1POL, +#endif +#ifdef CONFIG_STM32L4_TIM8_BREAK2 + .en2 = 1, + .pol2 = CONFIG_STM32L4_TIM8_BRK2POL, + .flt2 = CONFIG_STM32L4_TIM8_BRK2FLT, +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH1POL, + .idle = CONFIG_STM32L4_TIM8_CH1IDLE, + .pincfg = PWM_TIM8_CH1CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CH1NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH1NPOL, + .idle = CONFIG_STM32L4_TIM8_CH1NIDLE, + .pincfg = PWM_TIM8_CH1NCFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CHANNEL2 + { + .channel = 2, + .mode = CONFIG_STM32L4_TIM8_CH2MODE, +#ifdef CONFIG_STM32L4_TIM8_CH2OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH2POL, + .idle = CONFIG_STM32L4_TIM8_CH2IDLE, + .pincfg = PWM_TIM8_CH2CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CH2NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH2NPOL, + .idle = CONFIG_STM32L4_TIM8_CH2NIDLE, + .pincfg = PWM_TIM8_CH2NCFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CHANNEL3 + { + .channel = 3, + .mode = CONFIG_STM32L4_TIM8_CH3MODE, +#ifdef CONFIG_STM32L4_TIM8_CH3OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH3POL, + .idle = CONFIG_STM32L4_TIM8_CH3IDLE, + .pincfg = PWM_TIM8_CH3CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CH3NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH3NPOL, + .idle = CONFIG_STM32L4_TIM8_CH3NIDLE, + .pincfg = PWM_TIM8_CH3NCFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CHANNEL4 + { + .channel = 4, + .mode = CONFIG_STM32L4_TIM8_CH4MODE, +#ifdef CONFIG_STM32L4_TIM8_CH4OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH4POL, + .idle = CONFIG_STM32L4_TIM8_CH4IDLE, + .pincfg = PWM_TIM8_CH4CFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CHANNEL5 + { + .channel = 5, + .mode = CONFIG_STM32L4_TIM8_CH5MODE, +#ifdef CONFIG_STM32L4_TIM8_CH5OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH5POL, + .idle = CONFIG_STM32L4_TIM8_CH5IDLE, + .pincfg = 0, /* No available externaly */ + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM8_CHANNEL6 + { + .channel = 6, + .mode = CONFIG_STM32L4_TIM8_CH6MODE, +#ifdef CONFIG_STM32L4_TIM8_CH6OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM8_CH6POL, + .idle = CONFIG_STM32L4_TIM8_CH6IDLE, + .pincfg = 0, /* No available externaly */ + } +#endif + } +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm8dev = { .ops = &g_pwmops, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, +#endif .timid = 8, - .channels = - { -#ifdef CONFIG_STM32L4_TIM8_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM8_CH1CFG, - .mode = CONFIG_STM32L4_TIM8_CH1MODE, - .npincfg = PWM_TIM8_CH1NCFG, - }, -#endif -#ifdef CONFIG_STM32L4_TIM8_CHANNEL2 - { - .channel = 2, - .pincfg = PWM_TIM8_CH2CFG, - .mode = CONFIG_STM32L4_TIM8_CH2MODE, - .npincfg = PWM_TIM8_CH2NCFG, - }, -#endif -#ifdef CONFIG_STM32L4_TIM8_CHANNEL3 - { - .channel = 3, - .pincfg = PWM_TIM8_CH3CFG, - .mode = CONFIG_STM32L4_TIM8_CH3MODE, - .npincfg = PWM_TIM8_CH3NCFG, - }, -#endif -#ifdef CONFIG_STM32L4_TIM8_CHANNEL4 - { - .channel = 4, - .pincfg = PWM_TIM8_CH4CFG, - .mode = CONFIG_STM32L4_TIM8_CH4MODE, - .npincfg = 0, - }, -#endif - }, + .chan_num = PWM_TIM8_NCHANNELS, + .channels = g_pwm8channels, .timtype = TIMTYPE_TIM8, .mode = CONFIG_STM32L4_TIM8_MODE, + .lock = CONFIG_STM32L4_TIM8_LOCK, + .t_dts = CONFIG_STM32L4_TIM8_TDTS, +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = CONFIG_STM32L4_TIM8_DEADTIME, +#endif +#if defined(HAVE_TRGO) && defined(STM32L4_TIM8_TRGO) + .trgo = STM32L4_TIM8_TRGO, +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM8UP, #endif .base = STM32L4_TIM8_BASE, .pclk = STM32L4_APB2_TIM8_CLKIN, }; -#endif +#endif /* CONFIG_STM32L4_TIM8_PWM */ #ifdef CONFIG_STM32L4_TIM15_PWM + +static struct stm32l4_pwmchan_s g_pwm15channels[] = +{ + /* TIM15 has 2 channels, 1 complementary */ + +#ifdef CONFIG_STM32L4_TIM15_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM15_CH1MODE, +#ifdef HAVE_BREAK + .brk = + { +#ifdef CONFIG_STM32L4_TIM15_BREAK1 + .en1 = 1, + .pol1 = CONFIG_STM32L4_TIM15_BRK1POL, +#endif + /* No BREAK2 */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM15_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM15_CH1POL, + .idle = CONFIG_STM32L4_TIM15_CH1IDLE, + .pincfg = PWM_TIM15_CH1CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM15_CH1NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM15_CH1NPOL, + .idle = CONFIG_STM32L4_TIM15_CH1NIDLE, + .pincfg = PWM_TIM15_CH2CFG, + } +#endif + }, +#endif +#ifdef CONFIG_STM32L4_TIM15_CHANNEL2 + { + .channel = 2, + .mode = CONFIG_STM32L4_TIM15_CH2MODE, +#ifdef CONFIG_STM32L4_TIM12_CH2OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM15_CH2POL, + .idle = CONFIG_STM32L4_TIM15_CH2IDLE, + .pincfg = PWM_TIM15_CH2CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm15dev = { .ops = &g_pwmops, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, +#endif .timid = 15, - .channels = - { -#ifdef CONFIG_STM32L4_TIM15_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM15_CH1CFG, - .mode = CONFIG_STM32L4_TIM15_CH1MODE, - .npincfg = PWM_TIM15_CH1NCFG, - }, -#endif -#ifdef CONFIG_STM32L4_TIM15_CHANNEL2 - { - .channel = 2, - .pincfg = PWM_TIM15_CH2CFG, - .mode = CONFIG_STM32L4_TIM15_CH2MODE, - .npincfg = 0, - }, -#endif - }, + .chan_num = PWM_TIM15_NCHANNELS, + .channels = g_pwm15channels, .timtype = TIMTYPE_TIM15, .mode = STM32L4_TIMMODE_COUNTUP, + .lock = CONFIG_STM32L4_TIM15_LOCK, + .t_dts = CONFIG_STM32L4_TIM15_TDTS, +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = CONFIG_STM32L4_TIM15_DEADTIME, +#endif +#if defined(HAVE_TRGO) && defined(STM32L4_TIM15_TRGO) + .trgo = STM32L4_TIM15_TRGO, +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM15, #endif .base = STM32L4_TIM15_BASE, .pclk = STM32L4_APB2_TIM15_CLKIN, }; -#endif +#endif /* CONFIG_STM32L4_TIM15_PWM */ #ifdef CONFIG_STM32L4_TIM16_PWM + +static struct stm32l4_pwmchan_s g_pwm16channels[] = +{ + /* TIM16 has 1 channel, 1 complementary */ + +#ifdef CONFIG_STM32L4_TIM16_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM16_CH1MODE, +#ifdef HAVE_BREAK + .brk = + { +#ifdef CONFIG_STM32L4_TIM16_BREAK1 + .en1 = 1, + .pol1 = CONFIG_STM32L4_TIM16_BRK1POL, +#endif + /* No BREAK2 */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM16_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM16_CH1POL, + .idle = CONFIG_STM32L4_TIM16_CH1IDLE, + .pincfg = PWM_TIM16_CH1CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM16_CH1NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM16_CH1NPOL, + .idle = CONFIG_STM32L4_TIM16_CH1NIDLE, + .pincfg = PWM_TIM16_CH2CFG, + } +#endif + }, +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm16dev = { .ops = &g_pwmops, - .timid = 16, - .channels = - { -#ifdef CONFIG_STM32L4_TIM16_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM16_CH1CFG, - .mode = CONFIG_STM32L4_TIM16_CH1MODE, - .npincfg = PWM_TIM16_CH1NCFG, - }, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, #endif - }, + .timid = 16, + .chan_num = PWM_TIM16_NCHANNELS, + .channels = g_pwm16channels, .timtype = TIMTYPE_TIM16, .mode = STM32L4_TIMMODE_COUNTUP, + .lock = CONFIG_STM32L4_TIM16_LOCK, + .t_dts = CONFIG_STM32L4_TIM16_TDTS, +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = CONFIG_STM32L4_TIM16_DEADTIME, +#endif +#if defined(HAVE_TRGO) + .trgo = 0, /* TRGO not supported for TIM16 */ +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM16, #endif .base = STM32L4_TIM16_BASE, .pclk = STM32L4_APB2_TIM16_CLKIN, }; -#endif +#endif /* CONFIG_STM32L4_TIM16_PWM */ #ifdef CONFIG_STM32L4_TIM17_PWM + +static struct stm32l4_pwmchan_s g_pwm17channels[] = +{ + /* TIM17 has 1 channel, 1 complementary */ + +#ifdef CONFIG_STM32L4_TIM17_CHANNEL1 + { + .channel = 1, + .mode = CONFIG_STM32L4_TIM17_CH1MODE, +#ifdef HAVE_BREAK + .brk = + { +#ifdef CONFIG_STM32L4_TIM17_BREAK1 + .en1 = 1, + .pol1 = CONFIG_STM32L4_TIM17_BRK1POL, +#endif + /* No BREAK2 */ + }, +#endif +#ifdef CONFIG_STM32L4_TIM17_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM17_CH1POL, + .idle = CONFIG_STM32L4_TIM17_CH1IDLE, + .pincfg = PWM_TIM17_CH1CFG, + }, +#endif +#ifdef CONFIG_STM32L4_TIM17_CH1NOUT + .out2 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_TIM17_CH1NPOL, + .idle = CONFIG_STM32L4_TIM17_CH1NIDLE, + .pincfg = PWM_TIM17_CH2CFG, + } +#endif + }, +#endif +}; + static struct stm32l4_pwmtimer_s g_pwm17dev = { .ops = &g_pwmops, - .timid = 17, - .channels = - { -#ifdef CONFIG_STM32L4_TIM17_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_TIM17_CH1CFG, - .mode = CONFIG_STM32L4_TIM17_CH1MODE, - .npincfg = PWM_TIM17_CH1NCFG, - }, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, #endif - }, + .timid = 17, + .chan_num = PWM_TIM17_NCHANNELS, + .channels = g_pwm17channels, .timtype = TIMTYPE_TIM17, .mode = STM32L4_TIMMODE_COUNTUP, + .lock = CONFIG_STM32L4_TIM17_LOCK, + .t_dts = CONFIG_STM32L4_TIM17_TDTS, +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = CONFIG_STM32L4_TIM17_DEADTIME, +#endif +#if defined(HAVE_TRGO) + .trgo = 0, /* TRGO not supported for TIM17 */ +#endif #ifdef CONFIG_PWM_PULSECOUNT .irq = STM32L4_IRQ_TIM17, #endif .base = STM32L4_TIM17_BASE, .pclk = STM32L4_APB2_TIM17_CLKIN, }; -#endif +#endif /* CONFIG_STM32L4_TIM17_PWM */ #ifdef CONFIG_STM32L4_LPTIM1_PWM + +static struct stm32l4_pwmchan_s g_pwmlp1channels[] = +{ + /* LPTIM1 has 1 channel */ + +#ifdef CONFIG_STM32L4_LPTIM1_CHANNEL1 + { + .channel = 1, + .mode = 0, +#ifdef CONFIG_STM32L4_LPTIM1_CH1OUT + .out1 = + { + .in_use = 1, + .pol = CONFIG_STM32L4_LPTIM1_CH1POL, + .idle = 0, /* No idle */ + .pincfg = PWM_LPTIM1_CH1CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +}; + static struct stm32l4_pwmtimer_s g_pwmlp1dev = { .ops = &g_pwmops, - .timid = 1, - .channels = - { -#ifdef CONFIG_STM32L4_LPTIM1_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_LPTIM1_CH1CFG, - .npincfg = PWM_LPTIM1_CH1NCFG, - }, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, #endif - }, + .timid = 1, + .chan_num = PWM_LPTIM1_NCHANNELS, + .channels = g_pwmlp1channels, .timtype = TIMTYPE_LPTIM1, .mode = STM32L4_TIMMODE_COUNTUP, + .lock = 0, /* No lock */ + .t_dts = 0, /* No t_dts */ +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = 0, /* No deadtime */ +#endif +#if defined(HAVE_TRGO) + .trgo = 0, /* TRGO not supported for LPTIM1 */ +#endif +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32L4_IRQ_LPTIM1, +#endif .base = STM32L4_LPTIM1_BASE, #if defined(CONFIG_STM32L4_LPTIM1_CLK_APB1) .pclk = STM32L4_PCLK1_FREQUENCY, @@ -651,25 +1359,54 @@ static struct stm32l4_pwmtimer_s g_pwmlp1dev = .pclk = STM32L4_HSI_FREQUENCY, #endif }; -#endif +#endif /* CONFIG_STM32L4_LPTIM1_PWM */ #ifdef CONFIG_STM32L4_LPTIM2_PWM + +static struct stm32l4_pwmchan_s g_pwmlp2channels[] = +{ + /* LPTIM2 has 1 channel */ + +#ifdef CONFIG_STM32L4_LPTIM2_CHANNEL1 + { + .channel = 1, + .mode = 0, +#ifdef CONFIG_STM32L4_LPTIM2_CH1OUT + .out1 = + { + .in_use = 1, + .pol = 0, /* REVISIT: Configure using CONFIG_STM32L4_LPTIM2_CH1POL, */ + .idle = 0, /* No idle */ + .pincfg = PWM_LPTIM2_CH1CFG, + } +#endif + /* No complementary outputs */ + }, +#endif +}; + static struct stm32l4_pwmtimer_s g_pwmlp2dev = { .ops = &g_pwmops, - .timid = 2, - .channels = - { -#ifdef CONFIG_STM32L4_LPTIM2_CHANNEL1 - { - .channel = 1, - .pincfg = PWM_LPTIM2_CH1CFG, - .npincfg = PWM_LPTIM2_CH1NCFG, - }, +#ifdef CONFIG_STM32L4_PWM_LL_OPS + .llops = &g_llpwmops, #endif - }, + .timid = 2, + .chan_num = PWM_LPTIM2_NCHANNELS, + .channels = g_pwmlp2channels, .timtype = TIMTYPE_LPTIM2, .mode = STM32L4_TIMMODE_COUNTUP, + .lock = 0, /* No lock */ + .t_dts = 0, /* No t_dts */ +#ifdef HAVE_PWM_COMPLEMENTARY + .deadtime = 0, /* No deadtime */ +#endif +#if defined(HAVE_TRGO) + .trgo = 0, /* TRGO not supported for LPTIM2 */ +#endif +#ifdef CONFIG_PWM_PULSECOUNT + .irq = STM32L4_IRQ_LPTIM2, +#endif .base = STM32L4_LPTIM2_BASE, #if defined(CONFIG_STM32L4_LPTIM2_CLK_APB1) .pclk = STM32L4_PCLK1_FREQUENCY, @@ -681,14 +1418,14 @@ static struct stm32l4_pwmtimer_s g_pwmlp2dev = .pclk = STM32L4_HSI_FREQUENCY, #endif }; -#endif +#endif /* CONFIG_STM32L4_LPTIM2_PWM */ /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: stm32l4pwm_getreg + * Name: pwm_getreg * * Description: * Read the value of an PWM timer register. @@ -702,13 +1439,13 @@ static struct stm32l4_pwmtimer_s g_pwmlp2dev = * ****************************************************************************/ -static uint16_t stm32l4pwm_getreg(struct stm32l4_pwmtimer_s *priv, int offset) +static uint16_t pwm_getreg(struct stm32l4_pwmtimer_s *priv, int offset) { return getreg16(priv->base + offset); } /**************************************************************************** - * Name: stm32l4pwm_putreg + * Name: pwm_putreg * * Description: * Read the value of an PWM timer register. @@ -722,7 +1459,7 @@ static uint16_t stm32l4pwm_getreg(struct stm32l4_pwmtimer_s *priv, int offset) * ****************************************************************************/ -static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset, +static void pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset, uint16_t value) { if (priv->timtype == TIMTYPE_GENERAL32 && @@ -748,7 +1485,50 @@ static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset, } /**************************************************************************** - * Name: stm32l4pwm_dumpregs + * Name: pwm_modifyreg + * + * Description: + * Modify PWM register (32-bit or 16-bit) + * + * Input Parameters: + * priv - A reference to the PWM block status + * offset - The offset to the register to read + * clrbits - The bits to clear + * setbits - The bits to set + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void pwm_modifyreg(struct stm32l4_pwmtimer_s *priv, uint32_t offset, + uint32_t clearbits, uint32_t setbits) +{ + if (priv->timtype == TIMTYPE_GENERAL32 && + (offset == STM32L4_GTIM_CNT_OFFSET || + offset == STM32L4_GTIM_ARR_OFFSET || + offset == STM32L4_GTIM_CCR1_OFFSET || + offset == STM32L4_GTIM_CCR2_OFFSET || + offset == STM32L4_GTIM_CCR3_OFFSET || + offset == STM32L4_GTIM_CCR4_OFFSET)) + { + /* a 32 bit access is required for a 32 bit register: + * if only a 16 bit write would be performed, then the + * upper 16 bits of the 32 bit register will be a copy of + * the lower 16 bits. + */ + + modifyreg32(priv->base + offset, clearbits, setbits); + } + else + { + modifyreg16(priv->base + offset, (uint16_t)clearbits, + (uint16_t)setbits); + } +} + +/**************************************************************************** + * Name: pwm_dumpregs * * Description: * Dump all timer registers. @@ -762,136 +1542,373 @@ static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset, ****************************************************************************/ #ifdef CONFIG_DEBUG_PWM_INFO -static void stm32l4pwm_dumpregs(struct stm32l4_pwmtimer_s *priv, - FAR const char *msg) +static void pwm_dumpregs(FAR struct pwm_lowerhalf_s *dev, + FAR const char *msg) { + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + if (priv->timtype == TIMTYPE_LOWPOWER) { pwminfo("%s:\n", msg); pwminfo(" CFGR: %04x CR: %04x CMP: %04x ARR: %04x\n", - stm32l4pwm_getreg(priv, STM32L4_LPTIM_CFGR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_LPTIM_CMP_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET)); + pwm_getreg(priv, STM32L4_LPTIM_CFGR_OFFSET), + pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET), + pwm_getreg(priv, STM32L4_LPTIM_CMP_OFFSET), + pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET)); pwminfo(" ISR: %04x CNT: %04x\n", - stm32l4pwm_getreg(priv, STM32L4_LPTIM_ISR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_LPTIM_CNT_OFFSET)); + pwm_getreg(priv, STM32L4_LPTIM_ISR_OFFSET), + pwm_getreg(priv, STM32L4_LPTIM_CNT_OFFSET)); } else { pwminfo("%s:\n", msg); pwminfo(" CR1: %04x CR2: %04x SMCR: %04x DIER: %04x\n", - stm32l4pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_CR2_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_SMCR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_DIER_OFFSET)); + pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_CR2_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_SMCR_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_DIER_OFFSET)); pwminfo(" SR: %04x EGR: %04x CCMR1: %04x CCMR2: %04x\n", - stm32l4pwm_getreg(priv, STM32L4_GTIM_SR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_EGR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET)); + pwm_getreg(priv, STM32L4_GTIM_SR_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_EGR_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET)); pwminfo(" CCER: %04x CNT: %04x PSC: %04x ARR: %04x\n", - stm32l4pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_CNT_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_PSC_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET)); + pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_CNT_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_PSC_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET)); pwminfo(" CCR1: %04x CCR2: %04x CCR3: %04x CCR4: %04x\n", - stm32l4pwm_getreg(priv, STM32L4_GTIM_CCR1_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_CCR2_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_CCR3_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_CCR4_OFFSET)); + pwm_getreg(priv, STM32L4_GTIM_CCR1_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_CCR2_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_CCR3_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_CCR4_OFFSET)); #if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM) if (priv->timtype == TIMTYPE_ADVANCED) { pwminfo(" RCR: %04x BDTR: %04x DCR: %04x DMAR: %04x\n", - stm32l4pwm_getreg(priv, STM32L4_ATIM_RCR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_ATIM_DCR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_ATIM_DMAR_OFFSET)); + pwm_getreg(priv, STM32L4_ATIM_RCR_OFFSET), + pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET), + pwm_getreg(priv, STM32L4_ATIM_DCR_OFFSET), + pwm_getreg(priv, STM32L4_ATIM_DMAR_OFFSET)); } else #endif { pwminfo(" DCR: %04x DMAR: %04x\n", - stm32l4pwm_getreg(priv, STM32L4_GTIM_DCR_OFFSET), - stm32l4pwm_getreg(priv, STM32L4_GTIM_DMAR_OFFSET)); + pwm_getreg(priv, STM32L4_GTIM_DCR_OFFSET), + pwm_getreg(priv, STM32L4_GTIM_DMAR_OFFSET)); } } } #endif /**************************************************************************** - * Name: stm32l4pwm_timer + * Name: pwm_ccr_update + ****************************************************************************/ + +static int pwm_ccr_update(FAR struct pwm_lowerhalf_s *dev, uint8_t index, + uint32_t ccr) + +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint32_t offset = 0; + +#ifdef HAVE_LPTIM + if (priv->timtype == TIMTYPE_LOWPOWER) + { + /* REVISIT: What about index? Is it necessary for LPTIM? */ + + offset = STM32L4_LPTIM_CMP_OFFSET; + pwm_putreg(priv, offset, ccr); + + return OK; + } +#endif + + /* Only ADV timers have CC5 and CC6 */ + + if (priv->timtype != TIMTYPE_ADVANCED && (index == 5 || index == 6)) + { + pwmerr("ERROR: No such CCR: %u\n", index); + return -EINVAL; + } + + /* REVISIT: start index from 0? */ + + switch (index) + { + case STM32L4_PWM_CHAN1: + { + offset = STM32L4_GTIM_CCR1_OFFSET; + break; + } + + case STM32L4_PWM_CHAN2: + { + offset = STM32L4_GTIM_CCR2_OFFSET; + break; + } + + case STM32L4_PWM_CHAN3: + { + offset = STM32L4_GTIM_CCR3_OFFSET; + break; + } + + case STM32L4_PWM_CHAN4: + { + offset = STM32L4_GTIM_CCR4_OFFSET; + break; + } + + case STM32L4_PWM_CHAN5: + { + offset = STM32L4_ATIM_CCR5_OFFSET; + break; + } + + case STM32L4_PWM_CHAN6: + { + offset = STM32L4_ATIM_CCR6_OFFSET; + break; + } + + default: + { + pwmerr("ERROR: No such CCR: %u\n", index); + return -EINVAL; + } + } + + /* Update CCR register */ + + pwm_putreg(priv, offset, ccr); + + return OK; +} + +/**************************************************************************** + * Name: pwm_ccr_get + ****************************************************************************/ + +#ifdef CONFIG_STM32L4_PWM_LL_OPS +static uint32_t pwm_ccr_get(FAR struct pwm_lowerhalf_s *dev, uint8_t index) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint32_t offset = 0; + + switch (index) + { + case STM32L4_PWM_CHAN1: + { + offset = STM32L4_GTIM_CCR1_OFFSET; + break; + } + + case STM32L4_PWM_CHAN2: + { + offset = STM32L4_GTIM_CCR2_OFFSET; + break; + } + + case STM32L4_PWM_CHAN3: + { + offset = STM32L4_GTIM_CCR3_OFFSET; + break; + } + + case STM32L4_PWM_CHAN4: + { + offset = STM32L4_GTIM_CCR4_OFFSET; + break; + } + + case STM32L4_PWM_CHAN5: + { + offset = STM32L4_ATIM_CCR5_OFFSET; + break; + } + + case STM32L4_PWM_CHAN6: + { + offset = STM32L4_ATIM_CCR6_OFFSET; + break; + } + + default: + { + pwmerr("ERROR: No such CCR: %u\n", index); + return -EINVAL; + } + } + + /* Return CCR register */ + + return pwm_getreg(priv, offset); +} +#endif /* CONFIG_STM32L4_PWM_LL_OPS */ + +/**************************************************************************** + * Name: pwm_arr_update + ****************************************************************************/ + +static int pwm_arr_update(FAR struct pwm_lowerhalf_s *dev, uint32_t arr) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + + /* Update ARR register */ + + if (priv->timtype == TIMTYPE_LOWPOWER) + { + pwm_putreg(priv, STM32L4_LPTIM_ARR_OFFSET, arr); + } + else + { + pwm_putreg(priv, STM32L4_GTIM_ARR_OFFSET, arr); + } + + return OK; +} + +/**************************************************************************** + * Name: pwm_arr_get + ****************************************************************************/ + +static uint32_t pwm_arr_get(FAR struct pwm_lowerhalf_s *dev) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + + if (priv->timtype == TIMTYPE_LOWPOWER) + { + return pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET); + } + else + { + return pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET); + } +} + +/**************************************************************************** + * Name: pwm_duty_update * * Description: - * (Re-)initialize the timer resources and start the pulsed output + * Try to change only channel duty * * Input Parameters: - * priv - A reference to the lower half PWM driver state structure - * info - A reference to the characteristics of the pulsed output + * dev - A reference to the lower half PWM driver state structure + * channel - Channel to by updated + * duty - New duty * * Returned Value: * Zero on success; a negated errno value on failure * ****************************************************************************/ -static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, - FAR const struct pwm_info_s *info) +static int pwm_duty_update(FAR struct pwm_lowerhalf_s *dev, uint8_t channel, + ub16_t duty) { -#ifdef CONFIG_PWM_MULTICHAN - int i; + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint32_t reload = 0; + uint32_t ccr = 0; + + /* We don't want compilation warnings if no DEBUGASSERT */ + + UNUSED(priv); + + DEBUGASSERT(priv != NULL); + + pwminfo("TIM%u channel: %u duty: %08x\n", + priv->timid, channel, duty); + +#ifndef CONFIG_STM32L4_PWM_MULTICHAN + DEBUGASSERT(channel == priv->channels[0].channel); + DEBUGASSERT(duty >= 0 && duty < uitoub16(100)); #endif - /* Calculated values */ + /* Get the reload values */ - uint32_t prescaler; - uint32_t timclk; - uint32_t reload; - uint32_t ccr; + reload = pwm_arr_get(dev); - /* Register contents */ + /* Duty cycle: + * + * duty cycle = ccr / reload (fractional value) + */ - uint16_t cr1; - uint16_t ccer; - uint16_t cr2; - uint32_t ccmr1; - uint32_t ccmr2; + ccr = b16toi(duty * reload + b16HALF); - /* New timer register bit settings */ + pwminfo("ccr: %u\n", ccr); - uint16_t ccenable; - uint16_t ccnenable; - uint32_t ocmode1; - uint32_t ocmode2; + /* Write coresponding CCR register */ - DEBUGASSERT(priv != NULL && info != NULL); + pwm_ccr_update(dev, channel, ccr); -#if defined(CONFIG_PWM_MULTICHAN) - pwminfo("TIM%u frequency: %u\n", - priv->timid, info->frequency); -#elif defined(CONFIG_PWM_PULSECOUNT) - pwminfo("TIM%u channel: %u frequency: %u duty: %08x count: %u\n", - priv->timid, priv->channels[0].channel, info->frequency, - info->duty, info->count); -#else - pwminfo("TIM%u channel: %u frequency: %u duty: %08x\n", - priv->timid, priv->channels[0].channel, info->frequency, info->duty); + return OK; +} + +/**************************************************************************** + * Name: pwm_timer_enable + ****************************************************************************/ + +static int pwm_timer_enable(FAR struct pwm_lowerhalf_s *dev, bool state) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + +#ifdef HAVE_LPTIM + if (priv->timtype != TIMTYPE_LOWPOWER) + { +#endif + if (state == true) + { + /* Enable timer counter */ + + pwm_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, 0, GTIM_CR1_CEN); + } + else + { + /* Disable timer counter */ + + pwm_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, GTIM_CR1_CEN, 0); + } +#ifdef HAVE_LPTIM + } + else + { + if (state == true) + { + /* Enable timer counter */ + + pwm_modifyreg(priv, STM32L4_LPTIM_CR_OFFSET, 0, LPTIM_CR_ENABLE); + } + else + { + /* Disable timer counter */ + + pwm_modifyreg(priv, STM32L4_LPTIM_CR_OFFSET, LPTIM_CR_ENABLE, 0); + } + } #endif - DEBUGASSERT(info->frequency > 0); -#ifndef CONFIG_PWM_MULTICHAN - DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100)); -#endif + return OK; +} - /* Disable all interrupts and DMA requests, clear all pending status */ +/**************************************************************************** + * Name: pwm_frequency_update + * + * Description: + * Update a PWM timer frequency + * + ****************************************************************************/ -#ifdef CONFIG_PWM_PULSECOUNT - stm32l4pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, 0); - stm32l4pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0); -#endif +static int pwm_frequency_update(FAR struct pwm_lowerhalf_s *dev, + uint32_t frequency) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint32_t reload = 0; + uint32_t timclk = 0; + uint32_t prescaler = 0; - /* Calculate optimal values for the timer prescaler and for the timer reload - * register. If 'frequency' is the desired frequency, then + /* Calculate optimal values for the timer prescaler and for the timer + * reload register. If 'frequency' is the desired frequency, then * * reload = timclk / frequency * timclk = pclk / presc @@ -923,7 +1940,18 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, * = 60,000 */ - prescaler = (priv->pclk / info->frequency + 65534) / 65535; + /* If timer mode is center aligned the frequency of PWM is the half of + * intended so multiply by x2 + */ + + if ((priv->mode == STM32L4_TIMMODE_CENTER1) || + (priv->mode == STM32L4_TIMMODE_CENTER2) || + (priv->mode == STM32L4_TIMMODE_CENTER3)) + { + frequency = frequency * 2; + } + + prescaler = (priv->pclk / frequency + 65534) / 65535; if (prescaler < 1) { prescaler = 1; @@ -935,7 +1963,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, timclk = priv->pclk / prescaler; - reload = timclk / info->frequency; + reload = timclk / frequency; if (reload < 2) { reload = 1; @@ -950,543 +1978,40 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv, } pwminfo("TIM%u PCLK: %u frequency: %u TIMCLK: %u prescaler: %u reload: %u\n", - priv->timid, priv->pclk, info->frequency, timclk, prescaler, reload); - - /* Set up the timer CR1 register: - * - * 1,8 CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN - * 2-5 CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN - * 6-7 ARPE OPM URS UDIS CEN - * 9-14 CKD[1:0] ARPE URS UDIS CEN - * 15-17 CKD[1:0] ARPE OPM URS UDIS CEN - */ - - cr1 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET); - - /* Disable the timer until we get it configured */ - - cr1 &= ~GTIM_CR1_CEN; - - /* Set the counter mode for the advanced timers (1,8) and most general - * purpose timers (all 2-5, but not 9-17), i.e., all but TIMTYPE_COUNTUP16 - * and TIMTYPE_BASIC - */ - -#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM2_PWM) || \ - defined(CONFIG_STM32L4_TIM3_PWM) || defined(CONFIG_STM32L4_TIM4_PWM) || \ - defined(CONFIG_STM32L4_TIM5_PWM) || defined(CONFIG_STM32L4_TIM8_PWM) - - if (priv->timtype != TIMTYPE_BASIC && priv->timtype != TIMTYPE_COUNTUP16) - { - /* Select the Counter Mode: - * - * GTIM_CR1_EDGE: The counter counts up or down depending on the - * direction bit (DIR). - * GTIM_CR1_CENTER1, GTIM_CR1_CENTER2, GTIM_CR1_CENTER3: The counter - * counts up then down. - * GTIM_CR1_DIR: 0: count up, 1: count down - */ - - cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK); - - switch (priv->mode) - { - case STM32L4_TIMMODE_COUNTUP: - cr1 |= GTIM_CR1_EDGE; - break; - - case STM32L4_TIMMODE_COUNTDOWN: - cr1 |= GTIM_CR1_EDGE | GTIM_CR1_DIR; - break; - - case STM32L4_TIMMODE_CENTER1: - cr1 |= GTIM_CR1_CENTER1; - break; - - case STM32L4_TIMMODE_CENTER2: - cr1 |= GTIM_CR1_CENTER2; - break; - - case STM32L4_TIMMODE_CENTER3: - cr1 |= GTIM_CR1_CENTER3; - break; - - default: - pwmerr("ERROR: No such timer mode: %u\n", (unsigned int)priv->mode); - return -EINVAL; - } - } -#endif - - /* Set the clock division to zero for all (but the basic timers, but there - * should be no basic timers in this context - */ - - cr1 &= ~GTIM_CR1_CKD_MASK; - stm32l4pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1); + priv->timid, priv->pclk, frequency, timclk, prescaler, reload); /* Set the reload and prescaler values */ - stm32l4pwm_putreg(priv, STM32L4_GTIM_ARR_OFFSET, (uint16_t)reload); - stm32l4pwm_putreg(priv, STM32L4_GTIM_PSC_OFFSET, (uint16_t)(prescaler - 1)); + pwm_arr_update(dev, reload); + pwm_putreg(priv, STM32L4_GTIM_PSC_OFFSET, (uint16_t)(prescaler - 1)); - /* Set the advanced timer's repetition counter */ - -#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM) - if (priv->timtype == TIMTYPE_ADVANCED) - { - /* If a non-zero repetition count has been selected, then set the - * repitition counter to the count-1 (stm32l4pwm_start() has already - * assured us that the count value is within range). - */ - -#ifdef CONFIG_PWM_PULSECOUNT - if (info->count > 0) - { - /* Save the remaining count and the number of counts that will have - * elapsed on the first interrupt. - */ - - /* If the first interrupt occurs at the end end of the first - * repetition count, then the count will be the same as the RCR - * value. - */ - - priv->prev = stm32l4pwm_pulsecount(info->count); - stm32l4pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->prev - 1); - - /* Generate an update event to reload the prescaler. This should - * preload the RCR into active repetition counter. - */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_EGR_OFFSET, ATIM_EGR_UG); - - /* Now set the value of the RCR that will be loaded on the next - * update event. - */ - - priv->count = info->count; - priv->curr = stm32l4pwm_pulsecount(info->count - priv->prev); - stm32l4pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1); - } - - /* Otherwise, just clear the repetition counter */ - - else -#endif - { - /* Set the repetition counter to zero */ - - stm32l4pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, 0); - - /* Generate an update event to reload the prescaler */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_EGR_OFFSET, ATIM_EGR_UG); - } - } - else -#endif - { - /* Generate an update event to reload the prescaler (all timers) */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_EGR_OFFSET, ATIM_EGR_UG); - } - - /* Handle channel specific setup */ - - ccenable = 0; - ccnenable = 0; - ocmode1 = 0; - ocmode2 = 0; - -#ifdef CONFIG_PWM_MULTICHAN - for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) -#endif - { - ub16_t duty; - uint32_t chanmode; - uint32_t compout; /* Complementary output config */ - bool ocmbit = false; - uint8_t channel; -#ifdef CONFIG_PWM_MULTICHAN - int j; -#endif - enum stm32l4_chanmode_e mode; - -#ifdef CONFIG_PWM_MULTICHAN - duty = info->channels[i].duty; - channel = info->channels[i].channel; - - /* A value of zero means to skip this channel */ - - if (channel == 0) - { - continue; - } - - /* Find the channel */ - - for (j = 0; j < PWM_NCHANNELS; j++) - { - if (priv->channels[j].channel == channel) - { - mode = priv->channels[j].mode; - compout = priv->channels[j].npincfg; - break; - } - } - - if (j >= PWM_NCHANNELS) - { - pwmerr("ERROR: No such channel: %u\n", channel); - return -EINVAL; - } -#else - duty = info->duty; - channel = priv->channels[0].channel; - mode = priv->channels[0].mode; - compout = priv->channels[0].npincfg; -#endif - - /* Duty cycle: - * - * duty cycle = ccr / reload (fractional value) - */ - - ccr = b16toi(duty * reload + b16HALF); - - pwminfo("ccr: %u\n", ccr); - - switch (mode) - { - case STM32L4_CHANMODE_PWM1: - chanmode = ATIM_CCMR_MODE_PWM1; - break; - - case STM32L4_CHANMODE_PWM2: - chanmode = ATIM_CCMR_MODE_PWM2; - break; - - case STM32L4_CHANMODE_COMBINED1: - chanmode = ATIM_CCMR_MODE_COMBINED1; - ocmbit = true; - break; - - case STM32L4_CHANMODE_COMBINED2: - chanmode = ATIM_CCMR_MODE_COMBINED2; - ocmbit = true; - break; - - case STM32L4_CHANMODE_ASYMMETRIC1: - chanmode = ATIM_CCMR_MODE_ASYMMETRIC1; - ocmbit = true; - break; - - case STM32L4_CHANMODE_ASYMMETRIC2: - chanmode = ATIM_CCMR_MODE_ASYMMETRIC2; - ocmbit = true; - break; - - default: - pwmerr("ERROR: No such mode: %u\n", (unsigned int)mode); - return -EINVAL; - } - - switch (channel) - { - case 1: /* PWM Mode configuration: Channel 1 */ - { - /* Select the CCER enable bit for this channel */ - - ccenable |= ATIM_CCER_CC1E; - - /* Conditionally enable the complementary output */ - - if (compout) - { - ccnenable |= ATIM_CCER_CC1NE; - } - - /* Set the CCMR1 mode values (leave CCMR2 zero) */ - - ocmode1 |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) | - (chanmode << ATIM_CCMR1_OC1M_SHIFT) | - ATIM_CCMR1_OC1PE; - - if (ocmbit) - { - ocmode1 |= ATIM_CCMR1_OC1M; - } - - /* Set the duty cycle by writing to the CCR register for this channel */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_CCR1_OFFSET, (uint16_t)ccr); - } - break; - - case 2: /* PWM Mode configuration: Channel 2 */ - { - /* Select the CCER enable bit for this channel */ - - ccenable |= ATIM_CCER_CC2E; - - /* Conditionally enable the complementary output */ - - if (compout) - { - ccnenable |= ATIM_CCER_CC2NE; - } - - /* Set the CCMR1 mode values (leave CCMR2 zero) */ - - ocmode1 |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) | - (chanmode << ATIM_CCMR1_OC2M_SHIFT) | - ATIM_CCMR1_OC2PE; - - if (ocmbit) - { - ocmode1 |= ATIM_CCMR1_OC2M; - } - - /* Set the duty cycle by writing to the CCR register for this channel */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_CCR2_OFFSET, (uint16_t)ccr); - } - break; - - case 3: /* PWM Mode configuration: Channel 3 */ - { - /* Select the CCER enable bit for this channel */ - - ccenable |= ATIM_CCER_CC3E; - - /* Conditionally enable the complementary output */ - - if (compout) - { - ccnenable |= ATIM_CCER_CC3NE; - } - - /* Set the CCMR2 mode values (leave CCMR1 zero) */ - - ocmode2 |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) | - (chanmode << ATIM_CCMR2_OC3M_SHIFT) | - ATIM_CCMR2_OC3PE; - - if (ocmbit) - { - ocmode2 |= ATIM_CCMR2_OC3M; - } - - /* Set the duty cycle by writing to the CCR register for this channel */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_CCR3_OFFSET, (uint16_t)ccr); - } - break; - - case 4: /* PWM Mode configuration: Channel 4 */ - { - /* Select the CCER enable bit for this channel */ - - ccenable |= ATIM_CCER_CC4E; - - /* Set the CCMR2 mode values (leave CCMR1 zero) */ - - ocmode2 |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) | - (chanmode << ATIM_CCMR2_OC4M_SHIFT) | - ATIM_CCMR2_OC4PE; - - if (ocmbit) - { - ocmode2 |= ATIM_CCMR2_OC4M; - } - - /* Set the duty cycle by writing to the CCR register for this channel */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_CCR4_OFFSET, (uint16_t)ccr); - } - break; - - default: - pwmerr("ERROR: No such channel: %u\n", channel); - return -EINVAL; - } - } - - /* Disable the Channel by resetting the CCxE Bit in the CCER register */ - - ccer = stm32l4pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET); - ccer &= ~ccenable; - stm32l4pwm_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer); - - /* Fetch the CR2, CCMR1, and CCMR2 register (already have cr1 and ccer) */ - - cr2 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CR2_OFFSET); - ccmr1 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET); - ccmr2 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET); - - /* Reset the Output Compare Mode Bits and set the select output compare mode */ - - ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE | - ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE - | ATIM_CCMR1_OC1M | ATIM_CCMR1_OC2M - ); - ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE | - ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE - | ATIM_CCMR2_OC3M | ATIM_CCMR2_OC4M - ); - ccmr1 |= ocmode1; - ccmr2 |= ocmode2; - - /* Reset the output polarity level of all channels (selects high polarity)*/ - - ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P | ATIM_CCER_CC3P | ATIM_CCER_CC4P); - - /* Enable the output state of the selected channels */ - - ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E | ATIM_CCER_CC3E | ATIM_CCER_CC4E); - ccer |= ccenable; - - /* Some special setup for advanced timers */ - -#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM) - if (priv->timtype == TIMTYPE_ADVANCED) - { - uint16_t bdtr; - - /* Reset output N polarity level, output N state, output compare state, - * output compare N idle state. - */ - - ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | - ATIM_CCER_CC2NP | ATIM_CCER_CC3NE | ATIM_CCER_CC3NP); - - ccer |= ccnenable; - - /* Reset the output compare and output compare N IDLE State */ - - cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 | ATIM_CR2_OIS2N | - ATIM_CR2_OIS3 | ATIM_CR2_OIS3N | ATIM_CR2_OIS4); - - /* Set the main output enable (MOE) bit and clear the OSSI and OSSR - * bits in the BDTR register. - */ - - bdtr = stm32l4pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET); - bdtr &= ~(ATIM_BDTR_OSSI | ATIM_BDTR_OSSR); - bdtr |= ATIM_BDTR_MOE; - stm32l4pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, bdtr); - } - else -#if defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \ - defined(CONFIG_STM32L4_TIM17_PWM) - if (priv->timtype == TIMTYPE_COUNTUP16) - { - /* Reset output N polarity level, output N state, output compare state, - * output compare N idle state. - */ - - ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP); - ccer |= ccnenable; - } - else -#endif -#endif - { - ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP); /* Not sure why? */ - } - - /* Save the modified register values */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_CR2_OFFSET, cr2); - putreg32(ccmr1, priv->base + STM32L4_GTIM_CCMR1_OFFSET); - putreg32(ccmr2, priv->base + STM32L4_GTIM_CCMR2_OFFSET); - stm32l4pwm_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer); - - /* Set the ARR Preload Bit */ - - cr1 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET); - cr1 |= GTIM_CR1_ARPE; - stm32l4pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1); - - /* Setup update interrupt. If info->count is > 0, then we can be - * assured that stm32l4pwm_start() has already verified: (1) that this is an - * advanced timer, and that (2) the repetition count is within range. - */ - -#ifdef CONFIG_PWM_PULSECOUNT - if (info->count > 0) - { - /* Clear all pending interrupts and enable the update interrupt. */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0); - stm32l4pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, ATIM_DIER_UIE); - - /* Enable the timer */ - - cr1 |= GTIM_CR1_CEN; - stm32l4pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1); - - /* And enable timer interrupts at the NVIC */ - - up_enable_irq(priv->irq); - } - else -#endif - { - /* Just enable the timer, leaving all interrupts disabled */ - - cr1 |= GTIM_CR1_CEN; - stm32l4pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1); - } - - stm32l4pwm_dumpregs(priv, "After starting"); return OK; } /**************************************************************************** - * Name: stm32l4pwm_lptimer + * Name: pwm_lp_frequency_update * * Description: - * (Re-)initialize the low-power timer resources and start the - * pulsed output - * - * Input Parameters: - * priv - A reference to the lower half PWM driver state structure - * info - A reference to the characteristics of the pulsed output - * - * Returned Value: - * Zero on success; a negated errno value on failure + * Update a PWM timer frequency * ****************************************************************************/ -static int stm32l4pwm_lptimer(FAR struct stm32l4_pwmtimer_s *priv, - FAR const struct pwm_info_s *info) +#ifdef HAVE_LPTIM +static int pwm_lp_frequency_update(FAR struct pwm_lowerhalf_s *dev, + uint32_t frequency) { + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + /* Calculated values */ uint8_t prescaler; uint32_t timclk; uint32_t reload; - uint32_t ccr; /* Register contents */ - uint16_t cr; uint32_t cfgr; - DEBUGASSERT(priv != NULL && info != NULL); - - pwminfo("LPTIM%u frequency: %u duty: %08x\n", -#ifdef CONFIG_PWM_MULTICHAN - priv->timid, info->frequency, info->channels[0].duty); -#else - priv->timid, info->frequency, info->duty); -#endif - - DEBUGASSERT(info->frequency > 0); - DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100)); - /* LPTIM only has 8 possible prescaler values, from /1 to /128 * We will attempt to find the lowest prescaler that results * in a maximum reload value which can be represented in 16 bit. @@ -1497,7 +2022,7 @@ static int stm32l4pwm_lptimer(FAR struct stm32l4_pwmtimer_s *priv, for (prescaler = 0; prescaler < 8; prescaler++) { timclk = priv->pclk / (1 << prescaler); - reload = timclk / info->frequency; + reload = timclk / frequency; if (reload <= 65535) { @@ -1516,208 +2041,1324 @@ static int stm32l4pwm_lptimer(FAR struct stm32l4_pwmtimer_s *priv, reload = 65535; } - /* TODO: if the desired frequency is not possible this should give an error and - * not simply return the feasible frequency without complaining. + /* TODO: if the desired frequency is not possible this should give an error + * and not simply return the feasible frequency without complaining. */ pwminfo("LPTIM%u PCLK: %u frequency: %u TIMCLK: %u prescaler: %u reload: %u\n", - priv->timid, priv->pclk, info->frequency, timclk, prescaler, reload); + priv->timid, priv->pclk, frequency, timclk, prescaler, reload); - /* Disable the timer to set the prescaler */ + /* Set the reload register value */ - cr = stm32l4pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET); + pwm_arr_update(dev, reload); - cr &= ~LPTIM_CR_ENABLE; - stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr); + /* Set the prescaler value */ - /* We have to way two counter clocks before the clock is actually enabled */ - - up_udelay(2 * USEC_PER_SEC / timclk); - - /* Set the prescaler value and choose high polarity */ - - cfgr = getreg32(priv->base + STM32L4_LPTIM_CFGR_OFFSET); + cfgr = pwm_getreg(priv, STM32L4_LPTIM_CFGR_OFFSET); cfgr &= ~LPTIM_CFGR_PRESC_MASK; - cfgr |= (prescaler << LPTIM_CFGR_PRESC_SHIFT) | LPTIM_CFGR_WAVPOL; + cfgr |= (prescaler << LPTIM_CFGR_PRESC_SHIFT); - putreg32(cfgr, priv->base + STM32L4_LPTIM_CFGR_OFFSET); + pwm_putreg(priv, STM32L4_LPTIM_CFGR_OFFSET, cfgr); + + return OK; +} +#endif /* HAVE_LPTIM */ + +/**************************************************************************** + * Name: pwm_timer_configure + * + * Description: + * Initial configuration for PWM timer + * + ****************************************************************************/ + +static int pwm_timer_configure(FAR struct stm32l4_pwmtimer_s *priv) +{ + uint16_t cr1 = 0; + int ret = OK; + + /* Set up the timer CR1 register: + * + * 1,8 CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN + * 2-5 CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN + * 6-7 ARPE OPM URS UDIS CEN + * 9-14 CKD[1:0] ARPE URS UDIS CEN + * 15-17 CKD[1:0] ARPE OPM URS UDIS CEN + */ + + cr1 = pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET); + + /* Set the counter mode for the advanced timers (1,8) and most general + * purpose timers (all 2-5, but not 9-17), i.e., all but TIMTYPE_COUNTUP16 + * and TIMTYPE_BASIC + */ + + if (priv->timtype != TIMTYPE_BASIC && priv->timtype != TIMTYPE_COUNTUP16) + { + /* Select the Counter Mode: + * + * GTIM_CR1_EDGE: The counter counts up or down depending on the + * direction bit (DIR). + * GTIM_CR1_CENTER1, GTIM_CR1_CENTER2, GTIM_CR1_CENTER3: The counter + * counts up then down. + * GTIM_CR1_DIR: 0: count up, 1: count down + */ + + cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK); + + switch (priv->mode) + { + case STM32L4_TIMMODE_COUNTUP: + { + cr1 |= GTIM_CR1_EDGE; + break; + } + + case STM32L4_TIMMODE_COUNTDOWN: + { + cr1 |= GTIM_CR1_EDGE | GTIM_CR1_DIR; + break; + } + + case STM32L4_TIMMODE_CENTER1: + { + cr1 |= GTIM_CR1_CENTER1; + break; + } + + case STM32L4_TIMMODE_CENTER2: + { + cr1 |= GTIM_CR1_CENTER2; + break; + } + + case STM32L4_TIMMODE_CENTER3: + { + cr1 |= GTIM_CR1_CENTER3; + break; + } + + default: + { + pwmerr("ERROR: No such timer mode: %u\n", + (unsigned int)priv->mode); + ret = -EINVAL; + goto errout; + } + } + } + + /* Enable ARR Preload + * TODO: this should be configurable + */ + + cr1 |= GTIM_CR1_ARPE; + + /* Write CR1 */ + + pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1); + +errout: + return ret; +} + +/**************************************************************************** + * Name: pwm_mode_configure + * + * Description: + * Configure a PWM mode for given channel + * + ****************************************************************************/ + +static int pwm_mode_configure(FAR struct pwm_lowerhalf_s *dev, + uint8_t channel, uint32_t mode) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint32_t chanmode = 0; + uint32_t ocmode = 0; + uint32_t ccmr = 0; + uint32_t offset = 0; + int ret = OK; + bool ocmbit = false; + + /* Only advanced timers have channels 5-6 */ + + if (channel > 4 && priv->timtype != TIMTYPE_ADVANCED) + { + pwmerr("ERROR: No such channel: %u\n", channel); + ret = -EINVAL; + goto errout; + } + + /* Get channel mode + * TODO: configurable preload for CCxR + */ + + switch (mode) + { + case STM32L4_CHANMODE_FRZN: + { + chanmode = GTIM_CCMR_MODE_FRZN; + break; + } + + case STM32L4_CHANMODE_CHACT: + { + chanmode = GTIM_CCMR_MODE_CHACT; + break; + } + + case STM32L4_CHANMODE_CHINACT: + { + chanmode = GTIM_CCMR_MODE_CHINACT; + break; + } + + case STM32L4_CHANMODE_OCREFTOG: + { + chanmode = GTIM_CCMR_MODE_OCREFTOG; + break; + } + + case STM32L4_CHANMODE_OCREFLO: + { + chanmode = GTIM_CCMR_MODE_OCREFLO; + break; + } + + case STM32L4_CHANMODE_OCREFHI: + { + chanmode = GTIM_CCMR_MODE_OCREFHI; + break; + } + + case STM32L4_CHANMODE_PWM1: + { + chanmode = ATIM_CCMR_MODE_PWM1; + break; + } + + case STM32L4_CHANMODE_PWM2: + { + chanmode = ATIM_CCMR_MODE_PWM2; + break; + } + + case STM32L4_CHANMODE_COMBINED1: + { + chanmode = ATIM_CCMR_MODE_COMBINED1; + ocmbit = true; + break; + } + + case STM32L4_CHANMODE_COMBINED2: + { + chanmode = ATIM_CCMR_MODE_COMBINED2; + ocmbit = true; + break; + } + + case STM32L4_CHANMODE_ASYMMETRIC1: + { + chanmode = ATIM_CCMR_MODE_ASYMMETRIC1; + ocmbit = true; + break; + } + + case STM32L4_CHANMODE_ASYMMETRIC2: + { + chanmode = ATIM_CCMR_MODE_ASYMMETRIC2; + ocmbit = true; + break; + } + + default: + { + pwmerr("ERROR: No such mode: %u\n", (unsigned int)mode); + ret = -EINVAL; + goto errout; + } + } + + /* PWM mode configuration */ + + switch (channel) + { + /* Get CCMR offset */ + + case STM32L4_PWM_CHAN1: + case STM32L4_PWM_CHAN2: + { + offset = STM32L4_GTIM_CCMR1_OFFSET; + break; + } + + case STM32L4_PWM_CHAN3: + case STM32L4_PWM_CHAN4: + { + offset = STM32L4_GTIM_CCMR2_OFFSET; + break; + } + + case STM32L4_PWM_CHAN5: + case STM32L4_PWM_CHAN6: + { + offset = STM32L4_ATIM_CCMR3_OFFSET; + break; + } + + default: + { + pwmerr("ERROR: No such channel: %u\n", channel); + ret = -EINVAL; + goto errout; + } + } + + /* Get current registers */ + + ccmr = pwm_getreg(priv, offset); + + /* PWM mode configuration. + * NOTE: The CCMRx registers are identical if the channels are outputs. + */ + + switch (channel) + { + /* Configure channel 1/3/5 */ + + case STM32L4_PWM_CHAN1: + case STM32L4_PWM_CHAN3: + case STM32L4_PWM_CHAN5: + { + /* Reset current channel 1/3/5 mode configuration */ + + ccmr &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | + ATIM_CCMR1_OC1PE); + + /* Configure CC1/3/5 as output */ + + ocmode |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT); + + /* Configure Compare 1/3/5 mode */ + + ocmode |= (chanmode << ATIM_CCMR1_OC1M_SHIFT); + + /* Enable CCR1/3/5 preload */ + + ocmode |= ATIM_CCMR1_OC1PE; + + /* Reset current OC bit */ + + ccmr &= ~(ATIM_CCMR1_OC1M); + + /* Set an additional OC1/3/5M bit */ + + if (ocmbit) + { + ocmode |= ATIM_CCMR1_OC1M; + } + break; + } + + /* Configure channel 2/4/6 */ + + case STM32L4_PWM_CHAN2: + case STM32L4_PWM_CHAN4: + case STM32L4_PWM_CHAN6: + { + /* Reset current channel 2/4/6 mode configuration */ + + ccmr &= ~(ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | + ATIM_CCMR1_OC2PE); + + /* Configure CC2/4/6 as output */ + + ocmode |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT); + + /* Configure Compare 2/4/6 mode */ + + ocmode |= (chanmode << ATIM_CCMR1_OC2M_SHIFT); + + /* Enable CCR2/4/6 preload */ + + ocmode |= ATIM_CCMR1_OC2PE; + + /* Reset current OC bit */ + + ccmr &= ~(ATIM_CCMR1_OC2M); + + /* Set an additioneal OC2/4/6M bit */ + + if (ocmbit) + { + ocmode |= ATIM_CCMR1_OC2M; + } + break; + } + } + + /* Set the selected output compare mode */ + + ccmr |= ocmode; + + /* Write CCMRx registers */ + + pwm_putreg(priv, offset, ccmr); + +errout: + return ret; +} + +/**************************************************************************** + * Name: pwm_output_configure + * + * Description: + * Configure PWM output for given channel + * + ****************************************************************************/ + +static int pwm_output_configure(FAR struct stm32l4_pwmtimer_s *priv, + uint8_t channel) +{ + uint32_t cr2 = 0; + uint32_t ccer = 0; + + /* Get current registers state */ + + cr2 = pwm_getreg(priv, STM32L4_GTIM_CR2_OFFSET); + ccer = pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET); + + /* | OISx/OISxN | IDLE | for ADVANCED and COUNTUP16 | CR2 register + * | CCxP/CCxNP | POL | all PWM timers | CCER register + */ + + /* Configure output polarity (all PWM timers) */ + + if (priv->channels[channel - 1].out1.pol == STM32L4_POL_NEG) + { + ccer |= (GTIM_CCER_CC1P << ((channel - 1) * 4)); + } + else + { + ccer &= ~(GTIM_CCER_CC1P << ((channel - 1) * 4)); + } + +#ifdef HAVE_ADVTIM + if (priv->timtype == TIMTYPE_ADVANCED || + priv->timtype == TIMTYPE_COUNTUP16_N) + { + /* Configure output IDLE State */ + + if (priv->channels[channel - 1].out1.idle == STM32L4_IDLE_ACTIVE) + { + cr2 |= (ATIM_CR2_OIS1 << ((channel - 1) * 2)); + } + else + { + cr2 &= ~(ATIM_CR2_OIS1 << ((channel - 1) * 2)); + } + +#ifdef HAVE_PWM_COMPLEMENTARY + /* Configure complementary output IDLE state */ + + if (priv->channels[channel - 1].out2.idle == STM32L4_IDLE_ACTIVE) + { + cr2 |= (ATIM_CR2_OIS1N << ((channel - 1) * 2)); + } + else + { + cr2 &= ~(ATIM_CR2_OIS1N << ((channel - 1)* 2)); + } + + /* Configure complementary output polarity */ + + if (priv->channels[channel - 1].out2.pol == STM32L4_POL_NEG) + { + ccer |= (ATIM_CCER_CC1NP << ((channel - 1) * 4)); + } + else + { + ccer &= ~(ATIM_CCER_CC1NP << ((channel - 1) * 4)); + } +#endif /* HAVE_PWM_COMPLEMENTARY */ + + /* TODO: OIS5 and OIS6 */ + + cr2 &= ~(ATIM_CR2_OIS5 | ATIM_CR2_OIS6); + + /* TODO: CC5P and CC6P */ + + ccer &= ~(ATIM_CCER_CC5P | ATIM_CCER_CC6P); + } +#ifdef HAVE_GTIM_CCXNP + else +#endif /* HAVE_GTIM_CCXNP */ +#endif /* HAVE_ADVTIM */ +#ifdef HAVE_GTIM_CCXNP + { + /* CCxNP must be cleared if not ADVANCED timer. + * + * REVISIT: not all families have CCxNP bits for GTIM, + * which causes an ugly condition above + */ + + ccer &= ~(GTIM_CCER_CC1NP << ((channel - 1) * 4)); + } +#endif /* HAVE_GTIM_CCXNP */ + + /* Write registers */ + + pwm_modifyreg(priv, STM32L4_GTIM_CR2_OFFSET, 0, cr2); + pwm_modifyreg(priv, STM32L4_GTIM_CCER_OFFSET, 0, ccer); + + return OK; +} + +/**************************************************************************** + * Name: pwm_outputs_enable + * + * Description: + * Enable/disable given timer PWM outputs. + * + * NOTE: This is bulk operation - we can enable/disable many outputs + * at one time + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * outputs - outputs to set (look at enum stm32l4_chan_e in stm32l4_pwm.h) + * state - Enable/disable operation + * + ****************************************************************************/ + +static int pwm_outputs_enable(FAR struct pwm_lowerhalf_s *dev, + uint16_t outputs, bool state) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint32_t ccer = 0; + uint32_t regval = 0; + + /* Get curren register state */ + + ccer = pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET); + + /* Get outputs configuration */ + + regval |= ((outputs & STM32L4_PWM_OUT1) ? ATIM_CCER_CC1E : 0); + regval |= ((outputs & STM32L4_PWM_OUT1N) ? ATIM_CCER_CC1NE : 0); + regval |= ((outputs & STM32L4_PWM_OUT2) ? ATIM_CCER_CC2E : 0); + regval |= ((outputs & STM32L4_PWM_OUT2N) ? ATIM_CCER_CC2NE : 0); + regval |= ((outputs & STM32L4_PWM_OUT3) ? ATIM_CCER_CC3E : 0); + regval |= ((outputs & STM32L4_PWM_OUT3N) ? ATIM_CCER_CC3NE : 0); + regval |= ((outputs & STM32L4_PWM_OUT4) ? ATIM_CCER_CC4E : 0); + + /* NOTE: CC4N does not exist, but some docs show configuration bits for it */ + + regval |= ((outputs & STM32L4_PWM_OUT5) ? ATIM_CCER_CC5E : 0); + regval |= ((outputs & STM32L4_PWM_OUT6) ? ATIM_CCER_CC6E : 0); + + if (state == true) + { + /* Enable outpus - set bits */ + + ccer |= regval; + } + else + { + /* Disable outputs - reset bits */ + + ccer &= ~regval; + } + + /* Write register */ + + pwm_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer); + + return OK; +} + +#if defined(HAVE_PWM_COMPLEMENTARY) && defined(CONFIG_STM32L4_PWM_LL_OPS) + +/**************************************************************************** + * Name: pwm_deadtime_update + ****************************************************************************/ + +static int pwm_deadtime_update(FAR struct pwm_lowerhalf_s *dev, uint8_t dt) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint32_t bdtr = 0; + int ret = OK; + + /* Check if locked */ + + if (priv->lock > 0) + { + ret = -EACCES; + goto errout; + } + + /* Get current register state */ + + bdtr = pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET); + + /* TODO: check if BDTR not locked */ + + /* Update deadtime */ + + bdtr &= ~(ATIM_BDTR_DTG_MASK); + bdtr |= (dt << ATIM_BDTR_DTG_SHIFT); + + /* Write BDTR register */ + + pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, bdtr); + +errout: + return ret; +} +#endif + +/**************************************************************************** + * Name: pwm_soft_update + * + * Description: + * Generate an software update event + * + ****************************************************************************/ + +static int pwm_soft_update(FAR struct pwm_lowerhalf_s *dev) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + + pwm_putreg(priv, STM32L4_GTIM_EGR_OFFSET, ATIM_EGR_UG); + + return OK; +} + +/**************************************************************************** + * Name: pwm_soft_break + * + * Description: + * Generate an software break event + * + * Outputs are enabled if state is false. + * Outputs are disabled if state is true. + * + * NOTE: only timers with complementary outputs have BDTR register and + * support software break. + * + ****************************************************************************/ + +static int pwm_soft_break(FAR struct pwm_lowerhalf_s *dev, bool state) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + + if (state == true) + { + /* Reset MOE bit */ + + pwm_modifyreg(priv, STM32L4_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE, 0); + } + else + { + /* Set MOE bit */ + + pwm_modifyreg(priv, STM32L4_ATIM_BDTR_OFFSET, 0, ATIM_BDTR_MOE); + } + + return OK; +} + +/**************************************************************************** + * Name: pwm_outputs_from_channels + * + * Description: + * Get enabled outputs configuration from the PWM timer state + * + ****************************************************************************/ + +static uint16_t pwm_outputs_from_channels(FAR struct stm32l4_pwmtimer_s *priv) +{ + uint16_t outputs = 0; + uint8_t channel = 0; + uint8_t i = 0; + + for (i = 0; i < priv->chan_num; i += 1) + { + /* Get channel */ + + channel = priv->channels[i].channel; + + /* Set outputs if channel configured */ + + if (channel != 0) + { + /* Enable output if confiugred */ + + if (priv->channels[i].out1.in_use == 1) + { + outputs |= (STM32L4_PWM_OUT1 << ((channel - 1) * 2)); + } + +#ifdef HAVE_PWM_COMPLEMENTARY + /* Enable complementary output if configured */ + + if (priv->channels[i].out2.in_use == 1) + { + outputs |= (STM32L4_PWM_OUT1N << ((channel - 1) * 2)); + } +#endif + } + } + + return outputs; +} + +#ifdef HAVE_ADVTIM + +/**************************************************************************** + * Name: pwm_break_dt_configure + * + * Description: + * Configure break and deadtime + * + * NOTE: we have to configure all BDTR registers at once due to possible + * lock configuration + * + ****************************************************************************/ + +static int pwm_break_dt_configure(FAR struct stm32l4_pwmtimer_s *priv) +{ + uint32_t bdtr = 0; + + /* Set the clock division to zero for all (but the basic timers, but there + * should be no basic timers in this context + */ + + pwm_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, GTIM_CR1_CKD_MASK, + priv->t_dts << GTIM_CR1_CKD_SHIFT); + +#ifdef HAVE_PWM_COMPLEMENTARY + /* Initialize deadtime */ + + bdtr |= (priv->deadtime << ATIM_BDTR_DTG_SHIFT); +#endif + +#ifdef HAVE_BREAK + /* Configure Break 1 */ + + if (priv->brk.en1 == 1) + { + /* Enable Break 1 */ + + bdtr |= ATIM_BDTR_BKE; + + /* Set Break 1 polarity */ + + bdtr |= (priv->brk.pol1 == STM32L4_POL_NEG ? ATIM_BDTR_BKP : 0); + } + + /* Configure Break 1 */ + + if (priv->brk.en2 == 1) + { + /* Enable Break 2 */ + + bdtr |= ATIM_BDTR_BK2E; + + /* Set Break 2 polarity */ + + bdtr |= (priv->brk.pol2 == STM32L4_POL_NEG ? ATIM_BDTR_BK2P : 0); + + /* Configure BRK2 filter */ + + bdtr |= (priv->brk.flt2 << ATIM_BDTR_BK2F_SHIFT); + } + +#endif /* HAVE_BREAK */ + + /* Clear the OSSI and OSSR bits in the BDTR register. + * + * REVISIT: this should be configurable + */ + + bdtr &= ~(ATIM_BDTR_OSSI | ATIM_BDTR_OSSR); + + /* Configure lock */ + + bdtr |= priv->lock << ATIM_BDTR_LOCK_SHIFT; + + /* Write BDTR register at once */ + + pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, bdtr); + + return OK; +} + +#endif /* HAVE_ADVTIM */ + +/**************************************************************************** + * Name: pwm_configure + * + * Description: + * Configure PWM timer in normal mode (no PULSECOUNT) + * + ****************************************************************************/ + +static int pwm_configure(FAR struct pwm_lowerhalf_s *dev) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint16_t outputs = 0; + uint8_t j = 0; + int ret = OK; + + /* NOTE: leave timer counter disabled and all outputs disabled! */ + + /* Disable the timer until we get it configured */ + + pwm_timer_enable(dev, false); + + /* Get configured outputs */ + + outputs = pwm_outputs_from_channels(priv); + + /* Disable outputs */ + + ret = pwm_outputs_enable(dev, outputs, false); + if (ret < 0) + { + pwmerr("ERROR on pwm_outputs_enable()\n"); + goto errout; + } + + /* Initial timer configuration */ + + ret = pwm_timer_configure(priv); + if (ret < 0) + { + pwmerr("ERROR on pwm_timer_configure()\n"); + goto errout; + } + + /* Some special setup for advanced timers */ + +#ifdef HAVE_ADVTIM + if (priv->timtype == TIMTYPE_ADVANCED || + priv->timtype == TIMTYPE_COUNTUP16_N) + { + /* Configure break and deadtime register */ + + ret = pwm_break_dt_configure(priv); + if (ret < 0) + { + pwmerr("ERROR on pwm_break_dt_configure()\n"); + goto errout; + } + +#ifdef HAVE_TRGO + /* Configure TRGO/TRGO2 */ + + ret = pwm_sync_configure(priv, priv->trgo); + if (ret < 0) + { + pwmerr("ERROR on pwm_sync_configure()\n"); + goto errout; + } +#endif + } +#endif + + /* Configure timer channels */ + + for (j = 0; j < priv->chan_num; j++) + { + /* Skip channle if not in use */ + + if (priv->channels[j].channel != 0) + { + /* Update PWM mode */ + + ret = pwm_mode_configure(dev, priv->channels[j].channel, + priv->channels[j].mode); + if (ret < 0) + { + pwmerr("ERROR on pwm_mode_configure()\n"); + goto errout; + } + + /* PWM outputs configuration */ + + ret = pwm_output_configure(priv, priv->channels[j].channel); + if (ret < 0) + { + pwmerr("ERROR on pwm_output_configure()\n"); + goto errout; + } + } + } + + /* Disable software break at the end of the outputs configuration (enablei + * outputs). + * + * NOTE: Only timers with complementary outputs have BDTR register and + * support software break. + */ + + if (priv->timtype == TIMTYPE_ADVANCED || + priv->timtype == TIMTYPE_COUNTUP16_N) + { + pwminfo("pwm_soft_break(dev, false)\n"); + ret = pwm_soft_break(dev, false); + if (ret < 0) + { + pwmerr("ERROR on pwm_soft_break()\n"); + goto errout; + } + } + +errout: + return ret; +} + +#ifdef CONFIG_PWM_PULSECOUNT + +/**************************************************************************** + * Name: pwm_pulsecount_timer + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * TODO: PWM_PULSECOUNT should be configurable for each timer instance + * TODO: PULSECOUNT doesnt work with MULTICHAN at this moment + * + ****************************************************************************/ + +static int pwm_pulsecount_timer(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + ub16_t duty = 0; + uint8_t channel = 0; + uint16_t outputs = 0; + int ret = OK; + + /* If we got here it means that timer instance support pulsecount mode! */ + + DEBUGASSERT(priv != NULL && info != NULL); + + pwminfo("TIM%u channel: %u frequency: %u duty: %08x count: %u\n", + priv->timid, priv->channels[0].channel, info->frequency, + info->duty, info->count); + + DEBUGASSERT(info->frequency > 0); + + /* Channel specific setup */ + + duty = info->duty; + channel = priv->channels[0].channel; + + /* Disable all interrupts and DMA requests, clear all pending status */ + + pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, 0); + pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0); + + /* Set timer frequency */ + + ret = pwm_frequency_update(dev, info->frequency); + if (ret < 0) + { + goto errout; + } + + /* Update duty cycle */ + + ret = pwm_duty_update(dev, channel, duty); + if (ret < 0) + { + goto errout; + } + + /* If a non-zero repetition count has been selected, then set the + * repitition counter to the count-1 (pwm_pulsecount_start() has already + * assured us that the count value is within range). + */ + + if (info->count > 0) + { + /* Save the remaining count and the number of counts that will have + * elapsed on the first interrupt. + */ + + /* If the first interrupt occurs at the end end of the first + * repetition count, then the count will be the same as the RCR + * value. + */ + + priv->prev = stm32l4pwm_pulsecount(info->count); + pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->prev - 1); + + /* Generate an update event to reload the prescaler. This should + * preload the RCR into active repetition counter. + */ + + pwm_soft_update(dev); + + /* Now set the value of the RCR that will be loaded on the next + * update event. + */ + + priv->count = info->count; + priv->curr = stm32l4pwm_pulsecount(info->count - priv->prev); + pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1); + } + + /* Otherwise, just clear the repetition counter */ + + else + { + /* Set the repetition counter to zero */ + + pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, 0); + + /* Generate an update event to reload the prescaler */ + + pwm_soft_update(dev); + } + + /* Get configured outputs */ + + outputs = pwm_outputs_from_channels(priv); + + /* Enable output */ + + ret = pwm_outputs_enable(dev, outputs, true); + if (ret < 0) + { + goto errout; + } + + /* Setup update interrupt. If info->count is > 0, then we can be + * assured that pwm_pulsecount_start() has already verified: (1) that this + * is an advanced timer, and that (2) the repetition count is within range. + */ + + if (info->count > 0) + { + /* Clear all pending interrupts and enable the update interrupt. */ + + pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0); + pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, ATIM_DIER_UIE); + + /* Enable the timer */ + + pwm_timer_enable(dev, true); + + /* And enable timer interrupts at the NVIC */ + + up_enable_irq(priv->irq); + } + + pwm_dumpregs(dev, "After starting"); + +errout: + return ret; +} + +#else /* !CONFIG_PWM_PULSECOUNT */ + +/**************************************************************************** + * Name: pwm_duty_channels_update + * + * Description: + * Update duty cycle for given channels + * + ****************************************************************************/ + +static int pwm_duty_channels_update(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint8_t channel = 0; + ub16_t duty = 0; + int ret = OK; +#ifdef CONFIG_STM32L4_PWM_MULTICHAN + int i = 0; + int j = 0; +#endif + +#ifdef CONFIG_STM32L4_PWM_MULTICHAN + for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) +#endif + { +#ifdef CONFIG_STM32L4_PWM_MULTICHAN + duty = info->channels[i].duty; + channel = info->channels[i].channel; + + /* A value of zero means to skip this channel */ + + if (channel != 0) + { + /* Find the channel */ + + for (j = 0; j < priv->chan_num; j++) + { + if (priv->channels[j].channel == channel) + { + break; + } + } + + /* Check range */ + + if (j >= priv->chan_num) + { + pwmerr("ERROR: No such channel: %u\n", channel); + ret = -EINVAL; + goto errout; + } +#else + duty = info->duty; + channel = priv->channels[0].channel; +#endif + + /* Update duty cycle */ + + ret = pwm_duty_update(dev, channel, duty); + if (ret < 0) + { + goto errout; + } +#ifdef CONFIG_STM32L4_PWM_MULTICHAN + } +#endif + } + +errout: + return OK; +} + +/**************************************************************************** + * Name: pwm_timer + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_timer(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint16_t outputs = 0; + int ret = OK; + + DEBUGASSERT(priv != NULL && info != NULL); + +#if defined(CONFIG_STM32L4_PWM_MULTICHAN) + pwminfo("TIM%u frequency: %u\n", + priv->timid, info->frequency); +#else + pwminfo("TIM%u channel: %u frequency: %u duty: %08x\n", + priv->timid, priv->channels[0].channel, + info->frequency, info->duty); +#endif + + DEBUGASSERT(info->frequency > 0); +#ifndef CONFIG_STM32L4_PWM_MULTICHAN + DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100)); +#endif + + /* TODO: what if we have pwm running and we want disable some channels ? */ + + /* Set timer frequency */ + + ret = pwm_frequency_update(dev, info->frequency); + if (ret < 0) + { + goto errout; + } + + /* Channel specific configuration */ + + ret = pwm_duty_channels_update(dev, info); + if (ret < 0) + { + goto errout; + } + + /* Set the advanced timer's repetition counter */ + +#ifdef HAVE_ADVTIM + if (priv->timtype == TIMTYPE_ADVANCED || + priv->timtype == TIMTYPE_COUNTUP16_N) + { + /* If a non-zero repetition count has been selected, then set the + * repitition counter to the count-1 (pwm_start() has already + * assured us that the count value is within range). + */ + + /* Set the repetition counter to zero */ + + pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, 0); + + /* Generate an update event to reload the prescaler */ + + pwm_soft_update(dev); + } + else +#endif + { + /* Generate an update event to reload the prescaler (all timers) */ + + pwm_soft_update(dev); + } + + /* Get configured outputs */ + + outputs = pwm_outputs_from_channels(priv); + + /* Enable outputs */ + + ret = pwm_outputs_enable(dev, outputs, true); + if (ret < 0) + { + goto errout; + } + + /* Just enable the timer, leaving all interrupts disabled */ + + pwm_timer_enable(dev, true); + + pwm_dumpregs(dev, "After starting"); + +errout: + return ret; +} + +/**************************************************************************** + * Name: pwm_lptimer + * + * Description: + * (Re-)initialize the low-power timer resources and start the + * pulsed output + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +#ifdef HAVE_LPTIM +static int pwm_lptimer(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info) +{ + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; + uint16_t cr; + int ret = OK; + + DEBUGASSERT(priv != NULL && info != NULL); + +#if defined(CONFIG_STM32L4_PWM_MULTICHAN) + pwminfo("LPTIM%u frequency: %u\n", + priv->timid, info->frequency); +#else + pwminfo("LPTIM%u channel: %u frequency: %u duty: %08x\n", + priv->timid, priv->channels[0].channel, + info->frequency, info->duty); +#endif + + DEBUGASSERT(info->frequency > 0); +#ifndef CONFIG_STM32L4_PWM_MULTICHAN + DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100)); +#endif /* Enable again, ARR and CMP need to be written while enabled */ - cr |= LPTIM_CR_ENABLE; - stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr); + pwm_timer_enable(dev, true); - /* Compute reload value */ + /* Set timer frequency */ -#ifdef CONFIG_PWM_MULTICHAN + ret = pwm_lp_frequency_update(dev, info->frequency); + if (ret < 0) + { + goto errout; + } + +#ifdef CONFIG_STM32L4_PWM_MULTICHAN ub16_t duty = info->channels[0].duty; #else ub16_t duty = info->duty; #endif - /* Duty cycle: - * - * duty cycle = ccr / reload (fractional value) - */ + /* Update duty cycle */ - ccr = b16toi(duty * reload + b16HALF); - - pwminfo("ccr: %u\n", ccr); - - /* Set reload register */ - - stm32l4pwm_putreg(priv, STM32L4_LPTIM_ARR_OFFSET, (uint16_t)reload); - - /* Wait for write to complete */ - - while (!(getreg32(priv->base + STM32L4_LPTIM_ISR_OFFSET) & LPTIM_ISR_ARROK)); - - /* Set compare register */ - - stm32l4pwm_putreg(priv, STM32L4_LPTIM_CMP_OFFSET, (uint16_t)ccr); - - /* Wait for write to complete */ - - while (!(getreg32(priv->base + STM32L4_LPTIM_ISR_OFFSET) & LPTIM_ISR_CMPOK)); + ret = pwm_duty_update(dev, priv->channels[0].channel, duty); + if (ret < 0) + { + goto errout; + } /* Start counter */ - cr = stm32l4pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET); + cr = pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET); cr |= LPTIM_CR_CNTSTRT; - stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr); + pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr); - stm32l4pwm_dumpregs(priv, "After starting"); - return OK; + pwm_dumpregs(dev, "After starting"); + +errout: + return ret; } +#endif /* HAVE_LPTIM */ -#ifndef CONFIG_PWM_PULSECOUNT -/**************************************************************************** - * Name: stm32l4pwm_update_duty - * - * Description: - * Try to change only channel duty. - * - * Input Parameters: - * priv - A reference to the lower half PWM driver state structure - * channel - Channel to by updated - * duty - New duty. - * - * Returned Value: - * Zero on success; a negated errno value on failure - * - ****************************************************************************/ +#endif /* CONFIG_PWM_PULSECOUNT */ -static int stm32l4pwm_update_duty(FAR struct stm32l4_pwmtimer_s *priv, - uint8_t channel, ub16_t duty) -{ - /* Register offset */ - - int ccr_offset; - - /* Calculated values */ - - uint32_t reload; - uint32_t ccr; - - DEBUGASSERT(priv != NULL); - - pwminfo("%s%u channel: %u duty: %08x\n", - priv->timtype == TIMTYPE_LOWPOWER ? "LPTIM" : "TIM", - priv->timid, channel, duty); - -#ifndef CONFIG_PWM_MULTICHAN - DEBUGASSERT(channel == priv->channels[0].channel); - DEBUGASSERT(duty >= 0 && duty < uitoub16(100)); -#endif - - /* Get the reload values */ - - if (priv->timtype == TIMTYPE_LOWPOWER) - { - reload = stm32l4pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET); - } - else - { - reload = stm32l4pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET); - } - - /* Duty cycle: - * - * duty cycle = ccr / reload (fractional value) - */ - - ccr = b16toi(duty * reload + b16HALF); - - pwminfo("ccr: %u\n", ccr); - - if (priv->timtype == TIMTYPE_LOWPOWER) - { - /* Low-power timers only have a compare register */ - - ccr_offset = STM32L4_LPTIM_CMP_OFFSET; - } - else - { - switch (channel) - { - case 1: /* Register offset for Channel 1 */ - ccr_offset = STM32L4_GTIM_CCR1_OFFSET; - break; - - case 2: /* Register offset for Channel 2 */ - ccr_offset = STM32L4_GTIM_CCR2_OFFSET; - break; - - case 3: /* Register offset for Channel 3 */ - ccr_offset = STM32L4_GTIM_CCR3_OFFSET; - break; - - case 4: /* Register offset for Channel 4 */ - ccr_offset = STM32L4_GTIM_CCR4_OFFSET; - break; - - default: - pwmerr("ERROR: No such channel: %u\n", channel); - return -EINVAL; - } - } - - /* Set the duty cycle by writing to the CCR register for this channel */ - - stm32l4pwm_putreg(priv, ccr_offset, (uint16_t)ccr); - - return OK; -} -#endif +#ifdef HAVE_PWM_INTERRUPT /**************************************************************************** - * Name: stm32l4pwm_interrupt + * Name: pwm_interrupt * * Description: * Handle timer interrupts. * * Input Parameters: - * priv - A reference to the lower half PWM driver state structure + * dev - A reference to the lower half PWM driver state structure * * Returned Value: * Zero on success; a negated errno value on failure * ****************************************************************************/ -#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM)) -static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv) +static int pwm_interrupt(FAR struct pwm_lowerhalf_s *dev) { + FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; uint16_t regval; /* Verify that this is an update interrupt. Nothing else is expected. */ - regval = stm32l4pwm_getreg(priv, STM32L4_ATIM_SR_OFFSET); + regval = pwm_getreg(priv, STM32L4_ATIM_SR_OFFSET); DEBUGASSERT((regval & ATIM_SR_UIF) != 0); /* Clear the UIF interrupt bit */ - stm32l4pwm_putreg(priv, STM32L4_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF); + pwm_putreg(priv, STM32L4_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF); /* Calculate the new count by subtracting the number of pulses * since the last interrupt. @@ -1729,13 +3370,13 @@ static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv) * quickly as possible. */ - regval = stm32l4pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET); + regval = pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET); regval &= ~ATIM_BDTR_MOE; - stm32l4pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, regval); + pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, regval); /* Disable first interrtups, stop and reset the timer */ - stm32l4pwm_stop((FAR struct pwm_lowerhalf_s *)priv); + pwm_stop(dev); /* Then perform the callback into the upper half driver */ @@ -1762,17 +3403,18 @@ static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv) priv->prev = priv->curr; priv->curr = stm32l4pwm_pulsecount(priv->count - priv->prev); - stm32l4pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1); + pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1); } - /* Now all of the time critical stuff is done so we can do some debug output */ + /* Now all of the time critical stuff is done so we can do some debug + * output + */ pwminfo("Update interrupt SR: %04x prev: %u curr: %u count: %u\n", regval, priv->prev, priv->curr, priv->count); return OK; } -#endif /**************************************************************************** * Name: pwm_tim1/8interrupt @@ -1788,19 +3430,19 @@ static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv) * ****************************************************************************/ -#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32L4_TIM1_PWM) -static int stm32l4pwm_tim1interrupt(int irq, void *context, FAR void *arg) +#ifdef CONFIG_STM32L4_TIM1_PWM +static int pwm_tim1interrupt(int irq, void *context, FAR void *arg) { - return stm32l4pwm_interrupt(&g_pwm1dev); + return pwm_interrupt((FAR struct pwm_lowerhalf_s *)&g_pwm1dev); } -#endif +#endif /* CONFIG_STM32L4_TIM1_PWM */ -#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32L4_TIM8_PWM) -static int stm32l4pwm_tim8interrupt(int irq, void *context, FAR void *arg) +#ifdef CONFIG_STM32L4_TIM8_PWM +static int pwm_tim8interrupt(int irq, void *context, FAR void *arg) { - return stm32l4pwm_interrupt(&g_pwm8dev); + return pwm_interrupt((FAR struct pwm_lowerhalf_s *)&g_pwm8dev); } -#endif +#endif /* CONFIG_STM32L4_TIM8_PWM */ /**************************************************************************** * Name: stm32l4pwm_pulsecount @@ -1816,7 +3458,6 @@ static int stm32l4pwm_tim8interrupt(int irq, void *context, FAR void *arg) * ****************************************************************************/ -#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM)) static uint8_t stm32l4pwm_pulsecount(uint32_t count) { /* The the remaining pulse count is less than or equal to the maximum, the @@ -1825,7 +3466,7 @@ static uint8_t stm32l4pwm_pulsecount(uint32_t count) if (count <= ATIM_RCR_REP_MAX) { - return count; + return (uint8_t)count; } /* Otherwise, we have to be careful. We do not want a small number of @@ -1837,17 +3478,17 @@ static uint8_t stm32l4pwm_pulsecount(uint32_t count) else if (count < (3 * ATIM_RCR_REP_MAX / 2)) { - return (ATIM_RCR_REP_MAX + 1) >> 1; + return (uint8_t)((ATIM_RCR_REP_MAX + 1) >> 1); } /* Otherwise, return the maximum. The final count will be 64 or more */ else { - return ATIM_RCR_REP_MAX; + return (uint8_t)ATIM_RCR_REP_MAX; } } -#endif +#endif /* HAVE_PWM_INTERRUPT */ /**************************************************************************** * Name: stm32l4pwm_setapbclock @@ -1861,10 +3502,12 @@ static uint8_t stm32l4pwm_pulsecount(uint32_t count) * ****************************************************************************/ -static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on) +static int stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, + bool on) { uint32_t en_bit; uint32_t regaddr; + int ret = OK; /* Determine which timer to configure */ @@ -1874,60 +3517,91 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on) { #ifdef CONFIG_STM32L4_TIM1_PWM case 1: - regaddr = STM32L4_RCC_APB2ENR; - en_bit = RCC_APB2ENR_TIM1EN; - break; + { + regaddr = STM32L4_RCC_APB2ENR; + en_bit = RCC_APB2ENR_TIM1EN; + break; + } #endif + #ifdef CONFIG_STM32L4_TIM2_PWM case 2: - regaddr = STM32L4_RCC_APB1ENR1; - en_bit = RCC_APB1ENR1_TIM2EN; - break; + { + regaddr = STM32L4_RCC_APB1ENR1; + en_bit = RCC_APB1ENR1_TIM2EN; + break; + } #endif + #ifdef CONFIG_STM32L4_TIM3_PWM case 3: - regaddr = STM32L4_RCC_APB1ENR1; - en_bit = RCC_APB1ENR1_TIM3EN; - break; + { + regaddr = STM32L4_RCC_APB1ENR1; + en_bit = RCC_APB1ENR1_TIM3EN; + break; + } #endif + #ifdef CONFIG_STM32L4_TIM4_PWM case 4: - regaddr = STM32L4_RCC_APB1ENR1; - en_bit = RCC_APB1ENR1_TIM4EN; - break; + { + regaddr = STM32L4_RCC_APB1ENR1; + en_bit = RCC_APB1ENR1_TIM4EN; + break; + } #endif + #ifdef CONFIG_STM32L4_TIM5_PWM case 5: - regaddr = STM32L4_RCC_APB1ENR1; - en_bit = RCC_APB1ENR1_TIM5EN; - break; + { + regaddr = STM32L4_RCC_APB1ENR1; + en_bit = RCC_APB1ENR1_TIM5EN; + break; + } #endif + #ifdef CONFIG_STM32L4_TIM8_PWM case 8: - regaddr = STM32L4_RCC_APB2ENR; - en_bit = RCC_APB2ENR_TIM8EN; - break; + { + regaddr = STM32L4_RCC_APB2ENR; + en_bit = RCC_APB2ENR_TIM8EN; + break; + } #endif + #ifdef CONFIG_STM32L4_TIM15_PWM case 15: - regaddr = STM32L4_RCC_APB2ENR; - en_bit = RCC_APB2ENR_TIM15EN; - break; + { + regaddr = STM32L4_RCC_APB2ENR; + en_bit = RCC_APB2ENR_TIM15EN; + break; + } #endif + #ifdef CONFIG_STM32L4_TIM16_PWM case 16: - regaddr = STM32L4_RCC_APB2ENR; - en_bit = RCC_APB2ENR_TIM16EN; - break; + { + regaddr = STM32L4_RCC_APB2ENR; + en_bit = RCC_APB2ENR_TIM16EN; + break; + } #endif + #ifdef CONFIG_STM32L4_TIM17_PWM case 17: - regaddr = STM32L4_RCC_APB2ENR; - en_bit = RCC_APB2ENR_TIM17EN; - break; + { + regaddr = STM32L4_RCC_APB2ENR; + en_bit = RCC_APB2ENR_TIM17EN; + break; + } #endif + default: - return; + { + pwmerr("ERROR: No such timer configured %d\n", priv->timid); + ret = -EINVAL; + goto errout; + } } /* Enable/disable APB 1/2 clock for timer */ @@ -1941,6 +3615,7 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on) modifyreg32(regaddr, en_bit, 0); } } +#ifdef HAVE_LPTIM else { uint32_t clock_bits; @@ -1949,67 +3624,86 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on) { #ifdef CONFIG_STM32L4_LPTIM1_PWM case 1: + { #if defined(CONFIG_STM32L4_LPTIM1_CLK_APB1) - /* Enable APB clock for LPTIM1 */ + /* Enable APB clock for LPTIM1 */ - if (on) - { - modifyreg32(STM32L4_RCC_APB1ENR1, 0, RCC_APB1ENR1_LPTIM1EN); - } - else - { - modifyreg32(STM32L4_RCC_APB1ENR1, RCC_APB1ENR1_LPTIM1EN, 0); - } + if (on) + { + modifyreg32(STM32L4_RCC_APB1ENR1, + 0, RCC_APB1ENR1_LPTIM1EN); + } + else + { + modifyreg32(STM32L4_RCC_APB1ENR1, + RCC_APB1ENR1_LPTIM1EN, 0); + } - clock_bits = RCC_CCIPR_LPTIM1SEL_PCLK; + clock_bits = RCC_CCIPR_LPTIM1SEL_PCLK; #elif defined(CONFIG_STM32L4_LPTIM1_CLK_LSI) - clock_bits = RCC_CCIPR_LPTIM1SEL_LSI; + clock_bits = RCC_CCIPR_LPTIM1SEL_LSI; #elif defined(CONFIG_STM32L4_LPTIM1_CLK_LSE) - clock_bits = RCC_CCIPR_LPTIM1SEL_LSE; + clock_bits = RCC_CCIPR_LPTIM1SEL_LSE; #elif defined(CONFIG_STM32L4_LPTIM1_CLK_HSI) - clock_bits = RCC_CCIPR_LPTIM1SEL_HSI; + clock_bits = RCC_CCIPR_LPTIM1SEL_HSI; #endif - /* Choose which clock will be used for LPTIM1 */ + /* Choose which clock will be used for LPTIM1 */ - modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM1SEL_MASK, clock_bits); - break; + modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM1SEL_MASK, + clock_bits); + break; + } #endif #ifdef CONFIG_STM32L4_LPTIM2_PWM case 2: + { #if defined(CONFIG_STM32L4_LPTIM2_CLK_APB1) - /* Enable APB clock for LPTIM2 */ + /* Enable APB clock for LPTIM2 */ - if (on) - { - modifyreg32(STM32L4_RCC_APB1ENR2, 0, RCC_APB1ENR2_LPTIM2EN); - } - else - { - modifyreg32(STM32L4_RCC_APB1ENR2, RCC_APB1ENR2_LPTIM2EN, 0); - } + if (on) + { + modifyreg32(STM32L4_RCC_APB1ENR2, + 0, RCC_APB1ENR2_LPTIM2EN); + } + else + { + modifyreg32(STM32L4_RCC_APB1ENR2, + RCC_APB1ENR2_LPTIM2EN, 0); + } - clock_bits = RCC_CCIPR_LPTIM2SEL_PCLK; + clock_bits = RCC_CCIPR_LPTIM2SEL_PCLK; #elif defined(CONFIG_STM32L4_LPTIM2_CLK_LSI) - clock_bits = RCC_CCIPR_LPTIM2SEL_LSI; + clock_bits = RCC_CCIPR_LPTIM2SEL_LSI; #elif defined(CONFIG_STM32L4_LPTIM2_CLK_LSE) - clock_bits = RCC_CCIPR_LPTIM2SEL_LSE; + clock_bits = RCC_CCIPR_LPTIM2SEL_LSE; #elif defined(CONFIG_STM32L4_LPTIM2_CLK_HSI) - clock_bits = RCC_CCIPR_LPTIM2SEL_HSI; + clock_bits = RCC_CCIPR_LPTIM2SEL_HSI; #endif - /* Choose which clock will be used for LPTIM2 */ + /* Choose which clock will be used for LPTIM2 */ + + modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM2SEL_MASK, + clock_bits); + break; + } - modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM2SEL_MASK, clock_bits); - break; #endif default: - return; + { + pwmerr("ERROR: No such timer configured %d\n", priv->timid); + ret = -EINVAL; + goto errout; + } } } + +#endif /* HAVE_LPTIM */ +errout: + return ret; } /**************************************************************************** - * Name: stm32l4pwm_setup + * Name: pwm_setup * * Description: * This method is called when the driver is opened. The lower half driver @@ -2028,10 +3722,11 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on) * ****************************************************************************/ -static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev) +static int pwm_setup(FAR struct pwm_lowerhalf_s *dev) { FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; uint32_t pincfg; + int ret; int i; if (priv->timtype == TIMTYPE_LOWPOWER) @@ -2043,42 +3738,55 @@ static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev) pwminfo("TIM%u\n", priv->timid); } - stm32l4pwm_dumpregs(priv, "Initially"); - /* Enable APB1/2 clocking for timer. */ stm32l4pwm_setapbclock(priv, true); + pwm_dumpregs(dev, "Initially"); + /* Configure the PWM output pins, but do not start the timer yet */ - for (i = 0; i < PWM_NCHANNELS; i++) + for (i = 0; i < priv->chan_num; i++) { - pincfg = priv->channels[i].pincfg; - if (pincfg != 0) + if (priv->channels[i].out1.in_use == 1) { + pincfg = priv->channels[i].out1.pincfg; pwminfo("pincfg: %08x\n", pincfg); stm32l4_configgpio(pincfg); + pwm_dumpgpio(pincfg, "PWM setup"); } - /* Enable complementary channel if available */ - - pincfg = priv->channels[i].npincfg; - if (pincfg != 0) +#ifdef HAVE_PWM_COMPLEMENTARY + if (priv->channels[i].out2.in_use == 1) { - pwminfo("npincfg: %08x\n", pincfg); + pincfg = priv->channels[i].out2.pincfg; + pwminfo("pincfg: %08x\n", pincfg); stm32l4_configgpio(pincfg); + pwm_dumpgpio(pincfg, "PWM setup"); } +#endif + } - pwm_dumpgpio(pincfg, "PWM setup"); + /* Configure PWM timer with the selected configuration. + * + * NOTE: We configure PWM here during setup, but leave timer with disabled + * counter, disabled outputs, not configured frequency and duty cycle + */ + + ret = pwm_configure(dev); + if (ret < 0) + { + pwmerr("failed to configure PWM %d\n", priv->timid); + return ERROR; } return OK; } /**************************************************************************** - * Name: stm32l4pwm_shutdown + * Name: pwm_shutdown * * Description: * This method is called when the driver is closed. The lower half driver @@ -2093,27 +3801,39 @@ static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev) * ****************************************************************************/ -static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) +static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) { FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; - uint32_t pincfg; - int i; + uint32_t pincfg = 0; + int i = 0; + int ret = OK; - pwminfo("TIM%u\n", priv->timid); + if (priv->timtype == TIMTYPE_LOWPOWER) + { + pwminfo("LPTIM%u\n", priv->timid); + } + else + { + pwminfo("TIM%u\n", priv->timid); + } /* Make sure that the output has been stopped */ - stm32l4pwm_stop(dev); + pwm_stop(dev); /* Disable APB1/2 clocking for timer. */ - stm32l4pwm_setapbclock(priv, false); + ret = stm32l4pwm_setapbclock(priv, false); + if (ret < 0) + { + goto errout; + } /* Then put the GPIO pins back to the default state */ - for (i = 0; i < PWM_NCHANNELS; i++) + for (i = 0; i < priv->chan_num; i++) { - pincfg = priv->channels[i].pincfg; + pincfg = priv->channels[i].out1.pincfg; if (pincfg != 0) { pwminfo("pincfg: %08x\n", pincfg); @@ -2124,23 +3844,26 @@ static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) stm32l4_configgpio(pincfg); } - pincfg = priv->channels[i].npincfg; +#ifdef HAVE_PWM_COMPLEMENTARY + pincfg = priv->channels[i].out2.pincfg; if (pincfg != 0) { - pwminfo("npincfg: %08x\n", pincfg); + pwminfo("pincfg: %08x\n", pincfg); pincfg &= (GPIO_PORT_MASK | GPIO_PIN_MASK); pincfg |= GPIO_INPUT | GPIO_FLOAT; stm32l4_configgpio(pincfg); } +#endif } - return OK; +errout: + return ret; } /**************************************************************************** - * Name: stm32l4pwm_start + * Name: pwm_start * * Description: * (Re-)initialize the timer resources and start the pulsed output @@ -2155,7 +3878,7 @@ static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) ****************************************************************************/ #ifdef CONFIG_PWM_PULSECOUNT -static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info, FAR void *handle) { @@ -2181,17 +3904,11 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, /* Start the time */ - if (priv->timtype == TIMTYPE_LOWPOWER) - { - return stm32l4pwm_lptimer(priv, info); - } - else - { - return stm32l4pwm_timer(priv, info); - } + return pwm_pulsecount_timer(dev, info); } -#else -static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, +#else /* !CONFIG_PWM_PULSECOUNT */ + +static int pwm_start(FAR struct pwm_lowerhalf_s *dev, FAR const struct pwm_info_s *info) { int ret = OK; @@ -2201,7 +3918,7 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, if (info->frequency == priv->frequency) { -#ifdef CONFIG_PWM_MULTICHAN +#ifdef CONFIG_STM32L4_PWM_MULTICHAN int i; for (i = 0; ret == OK && i < CONFIG_PWM_NCHANNELS; i++) @@ -2210,25 +3927,26 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, if (info->channels[i].channel != 0) { - ret = stm32l4pwm_update_duty(priv, info->channels[i].channel, - info->channels[i].duty); + ret = pwm_duty_update(dev, info->channels[i].channel, + info->channels[i].duty); } } - #else - ret = stm32l4pwm_update_duty(priv, priv->channels[0].channel, info->duty); -#endif + ret = pwm_duty_update(dev, priv->channels[0].channel, info->duty); +#endif /* CONFIG_STM32L4_PWM_MULTICHAN */ } else { - if (priv->timtype == TIMTYPE_LOWPOWER) + if (priv->timtype != TIMTYPE_LOWPOWER) { - ret = stm32l4pwm_lptimer(priv, info); + ret = pwm_timer(dev, info); } +#ifdef HAVE_LPTIM else { - ret = stm32l4pwm_timer(priv, info); + ret = pwm_lptimer(dev, info); } +#endif /* Save current frequency */ @@ -2240,10 +3958,10 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, return ret; } -#endif +#endif /* CONFIG_PWM_PULSECOUNT */ /**************************************************************************** - * Name: stm32l4pwm_stop + * Name: pwm_stop * * Description: * Stop the pulsed output and reset the timer resources @@ -2261,7 +3979,7 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev, * ****************************************************************************/ -static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev) +static int pwm_stop(FAR struct pwm_lowerhalf_s *dev) { FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; uint32_t resetbit = 0; @@ -2278,21 +3996,6 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev) pwminfo("TIM%u\n", priv->timid); } - /* Disable interrupts momentary to stop any ongoing timer processing and - * to prevent any concurrent access to the reset register. - */ - - flags = enter_critical_section(); - - /* Stopped so frequency is zero */ - - priv->frequency = 0; - - /* Disable further interrupts and stop the timer */ - - stm32l4pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, 0); - stm32l4pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0); - /* Determine which timer to reset */ if (priv->timtype != TIMTYPE_LOWPOWER) @@ -2367,11 +4070,30 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev) resetbit = RCC_APB1RSTR2_LPTIM2RST; break; #endif + default: + return -EINVAL; } } + /* Disable interrupts momentary to stop any ongoing timer processing and + * to prevent any concurrent access to the reset register. + */ + + flags = enter_critical_section(); + +#ifndef CONFIG_PWM_PULSECOUNT + /* Stopped so frequency is zero */ + + priv->frequency = 0; +#endif + + /* Disable further interrupts and stop the timer */ + + pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, 0); + pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0); + /* Reset the timer - stopping the output and putting the timer back - * into a state where stm32l4pwm_start() can be called. + * into a state where pwm_start() can be called. */ regval = getreg32(regaddr); @@ -2383,12 +4105,12 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev) leave_critical_section(flags); pwminfo("regaddr: %08x resetbit: %08x\n", regaddr, resetbit); - stm32l4pwm_dumpregs(priv, "After stop"); + pwm_dumpregs(dev, "After stop"); return OK; } /**************************************************************************** - * Name: stm32l4pwm_ioctl + * Name: pwm_ioctl * * Description: * Lower-half logic may support platform-specific ioctl commands @@ -2403,8 +4125,8 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev) * ****************************************************************************/ -static int stm32l4pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, - unsigned long arg) +static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, + unsigned long arg) { #ifdef CONFIG_DEBUG_PWM_INFO FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev; @@ -2538,6 +4260,7 @@ FAR struct pwm_lowerhalf_s *stm32l4_pwminitialize(int timer) * ****************************************************************************/ +#ifdef HAVE_LPTIM FAR struct pwm_lowerhalf_s *stm32l4_lp_pwminitialize(int timer) { FAR struct stm32l4_pwmtimer_s *lower; @@ -2565,5 +4288,6 @@ FAR struct pwm_lowerhalf_s *stm32l4_lp_pwminitialize(int timer) return (FAR struct pwm_lowerhalf_s *)lower; } +#endif /* HAVE_LPTIM */ #endif /* CONFIG_STM32L4_TIMn_PWM, n = 1,...,17 */ diff --git a/arch/arm/src/stm32l4/stm32l4_pwm.h b/arch/arm/src/stm32l4/stm32l4_pwm.h index c7a639de2b1..01832e22798 100644 --- a/arch/arm/src/stm32l4/stm32l4_pwm.h +++ b/arch/arm/src/stm32l4/stm32l4_pwm.h @@ -1,4 +1,4 @@ -/************************************************************************************ +/**************************************************************************** * arch/arm/src/stm32l4/stm32l4_pwm.h * * Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved. @@ -33,36 +33,38 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - ************************************************************************************/ + ****************************************************************************/ #ifndef __ARCH_ARM_SRC_STM32L4_STM32L4_PWM_H #define __ARCH_ARM_SRC_STM32L4_STM32L4_PWM_H -/* The STM32L4 does not have dedicated PWM hardware. Rather, pulsed output control - * is a capability of the STM32L4 timers. The logic in this file implements the - * lower half of the standard, NuttX PWM interface using the STM32L4 timers. That - * interface is described in include/nuttx/timers/pwm.h. +/* The STM32L4 does not have dedicated PWM hardware. Rather, pulsed output + * control is a capability of the STM32L4 timers. The logic in this file + * implements the lower half of the standard, NuttX PWM interface using the + * STM32L4 timers. That interface is described in include/nuttx/timers/pwm.h. */ -/************************************************************************************ +/**************************************************************************** * Included Files - ************************************************************************************/ + ****************************************************************************/ #include +#include + #include "chip.h" -/************************************************************************************ +/**************************************************************************** * Pre-processor Definitions - ************************************************************************************/ + ****************************************************************************/ -/* Configuration ********************************************************************/ +/* Configuration ************************************************************/ /* Timer devices may be used for different purposes. One special purpose is * to generate modulated outputs for such things as motor control. If - * CONFIG_STM32L4_TIMn is defined then the CONFIG_STM32L4_TIMn_PWM must also be - * defined to indicate that timer "n" is intended to be used for pulsed output - * signal generation. + * CONFIG_STM32L4_TIMn is defined then the CONFIG_STM32L4_TIMn_PWM must also + * be defined to indicate that timer "n" is intended to be used for pulsed + * output signal generation. */ #ifndef CONFIG_STM32L4_TIM1 @@ -99,7 +101,9 @@ # undef CONFIG_STM32L4_LPTIM2_PWM #endif -/* The basic timers (timer 6 and 7) are not capable of generating output pulses */ +/* The basic timers (timer 6 and 7) are not capable of generating output + * pulses. + */ #undef CONFIG_STM32L4_TIM6_PWM #undef CONFIG_STM32L4_TIM7_PWM @@ -117,7 +121,9 @@ #include "hardware/stm32l4_tim.h" #include "hardware/stm32l4_lptim.h" -#ifdef CONFIG_PWM_MULTICHAN +/* PWM driver channels configuration */ + +#ifdef CONFIG_STM32L4_PWM_MULTICHAN #ifdef CONFIG_STM32L4_TIM1_CHANNEL1 # ifdef CONFIG_STM32L4_TIM1_CH1OUT @@ -502,33 +508,19 @@ #endif #define PWM_LPTIM2_NCHANNELS PWM_LPTIM2_CHANNEL1 -#define PWM_MAX(a, b) ((a) > (b) ? (a) : (b)) +#else /* !CONFIG_STM32L4_PWM_MULTICHAN */ -#define PWM_NCHANNELS PWM_MAX(PWM_TIM1_NCHANNELS, \ - PWM_MAX(PWM_TIM2_NCHANNELS, \ - PWM_MAX(PWM_TIM3_NCHANNELS, \ - PWM_MAX(PWM_TIM4_NCHANNELS, \ - PWM_MAX(PWM_TIM5_NCHANNELS, \ - PWM_MAX(PWM_TIM8_NCHANNELS, \ - PWM_MAX(PWM_TIM15_NCHANNELS, \ - PWM_MAX(PWM_TIM16_NCHANNELS, \ - PWM_MAX(PWM_TIM17_NCHANNELS, \ - PWM_MAX(PWM_LPTIM1_NCHANNELS, \ - PWM_LPTIM2_NCHANNELS)))))))))) - -#else - -/* For each timer that is enabled for PWM usage, we need the following additional - * configuration settings: +/* For each timer that is enabled for PWM usage, we need the following + * additional configuration settings: * * CONFIG_STM32L4_TIMx_CHANNEL - Specifies the timer output channel {1,..,4} - * PWM_TIMx_CHn - One of the values defined in chip/stm32*_pinmap.h. In the case - * where there are multiple pin selections, the correct setting must be provided - * in the arch/board/board.h file. + * PWM_TIMx_CHn - One of the values defined in chip/stm32*_pinmap.h. In the + * case where there are multiple pin selections, the correct setting must be + * provided in the arch/board/board.h file. * - * NOTE: The STM32L4 timers are each capable of generating different signals on - * each of the four channels with different duty cycles. That capability is - * not supported by this driver: Only one output channel per timer. + * NOTE: The STM32L4 timers are each capable of generating different signals + * on each of the four channels with different duty cycles. That capability + * is not supported by this driver: Only one output channel per timer. */ #ifdef CONFIG_STM32L4_TIM1_PWM @@ -537,25 +529,46 @@ # elif CONFIG_STM32L4_TIM1_CHANNEL == 1 # define CONFIG_STM32L4_TIM1_CHANNEL1 1 # define CONFIG_STM32L4_TIM1_CH1MODE CONFIG_STM32L4_TIM1_CHMODE -# define PWM_TIM1_CH1CFG GPIO_TIM1_CH1OUT -# define PWM_TIM1_CH1NCFG 0 +# ifdef CONFIG_STM32L4_TIM1_CH1OUT +# define PWM_TIM1_CH1CFG GPIO_TIM1_CH1OUT +# endif +# ifdef CONFIG_STM32L4_TIM1_CH1NOUT +# define PWM_TIM1_CH1NCFG GPIO_TIM1_CH1NOUT +# else +# define PWM_TIM1_CH1NCFG 0 +# endif # elif CONFIG_STM32L4_TIM1_CHANNEL == 2 # define CONFIG_STM32L4_TIM1_CHANNEL2 1 # define CONFIG_STM32L4_TIM1_CH2MODE CONFIG_STM32L4_TIM1_CHMODE -# define PWM_TIM1_CH2CFG GPIO_TIM1_CH2OUT -# define PWM_TIM1_CH2NCFG 0 +# ifdef CONFIG_STM32L4_TIM1_CH2OUT +# define PWM_TIM1_CH2CFG GPIO_TIM1_CH2OUT +# endif +# ifdef CONFIG_STM32L4_TIM1_CH2NOUT +# define PWM_TIM1_CH2NCFG GPIO_TIM1_CH2NOUT +# else +# define PWM_TIM1_CH2NCFG 0 +# endif # elif CONFIG_STM32L4_TIM1_CHANNEL == 3 # define CONFIG_STM32L4_TIM1_CHANNEL3 1 # define CONFIG_STM32L4_TIM1_CH3MODE CONFIG_STM32L4_TIM1_CHMODE -# define PWM_TIM1_CH3CFG GPIO_TIM1_CH3OUT -# define PWM_TIM1_CH3NCFG 0 +# ifdef CONFIG_STM32L4_TIM1_CH3OUT +# define PWM_TIM1_CH3CFG GPIO_TIM1_CH3OUT +# endif +# ifdef CONFIG_STM32L4_TIM1_CH3NOUT +# define PWM_TIM1_CH3NCFG GPIO_TIM1_CH3NOUT +# else +# define PWM_TIM1_CH3NCFG 0 +# endif # elif CONFIG_STM32L4_TIM1_CHANNEL == 4 # define CONFIG_STM32L4_TIM1_CHANNEL4 1 # define CONFIG_STM32L4_TIM1_CH4MODE CONFIG_STM32L4_TIM1_CHMODE -# define PWM_TIM1_CH4CFG GPIO_TIM1_CH4OUT +# ifdef CONFIG_STM32L4_TIM1_CH4OUT +# define PWM_TIM1_CH4CFG GPIO_TIM1_CH4OUT +# endif # else # error "Unsupported value of CONFIG_STM32L4_TIM1_CHANNEL" # endif +# define PWM_TIM1_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_TIM2_PWM @@ -580,6 +593,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_TIM2_CHANNEL" # endif +# define PWM_TIM2_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_TIM3_PWM @@ -604,6 +618,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_TIM3_CHANNEL" # endif +# define PWM_TIM3_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_TIM4_PWM @@ -628,6 +643,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_TIM4_CHANNEL" # endif +# define PWM_TIM4_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_TIM5_PWM @@ -652,6 +668,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_TIM5_CHANNEL" # endif +# define PWM_TIM5_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_TIM8_PWM @@ -679,6 +696,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_TIM8_CHANNEL" # endif +# define PWM_TIM8_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_TIM15_PWM @@ -696,6 +714,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_TIM15_CHANNEL" # endif +# define PWM_TIM15_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_TIM16_PWM @@ -709,6 +728,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_TIM16_CHANNEL" # endif +# define PWM_TIM16_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_TIM17_PWM @@ -722,6 +742,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_TIM17_CHANNEL" # endif +# define PWM_TIM17_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_LPTIM1_PWM @@ -734,6 +755,7 @@ # else # error "Unsupported value of CONFIG_STM32L4_LPTIM1_CHANNEL" # endif +# define PWM_LPTIM1_NCHANNELS 1 #endif #ifdef CONFIG_STM32L4_LPTIM2_PWM @@ -746,19 +768,258 @@ # else # error "Unsupported value of CONFIG_STM32L4_LPTIM2_CHANNEL" # endif +# define PWM_LPTIM2_NCHANNELS 1 #endif -#define PWM_NCHANNELS 1 - #endif -/************************************************************************************ +/* Complementary outputs support */ + +#if defined(CONFIG_STM32L4_TIM1_CH1NOUT) || defined(CONFIG_STM32L4_TIM1_CH2NOUT) || \ + defined(CONFIG_STM32L4_TIM1_CH3NOUT) +# define HAVE_TIM1_COMPLEMENTARY +#endif +#if defined(CONFIG_STM32L4_TIM8_CH1NOUT) || defined(CONFIG_STM32L4_TIM8_CH2NOUT) || \ + defined(CONFIG_STM32L4_TIM8_CH3NOUT) +# define HAVE_TIM8_COMPLEMENTARY +#endif +#if defined(CONFIG_STM32L4_TIM15_CH1NOUT) +# define HAVE_TIM15_COMPLEMENTARY +#endif +#if defined(CONFIG_STM32L4_TIM16_CH1NOUT) +# define HAVE_TIM16_COMPLEMENTARY +#endif +#if defined(CONFIG_STM32L4_TIM17_CH1NOUT) +# define HAVE_TIM17_COMPLEMENTARY +#endif +#if defined(CONFIG_STM32L4_LPTIM1_CH1NOUT) +# define HAVE_LPTIM1_COMPLEMENTARY +#endif +#if defined(CONFIG_STM32L4_LPTIM2_CH1NOUT) +# define HAVE_LPTIM2_COMPLEMENTARY +#endif +#if defined(HAVE_TIM1_COMPLEMENTARY) || defined(HAVE_TIM8_COMPLEMENTARY) || \ + defined(HAVE_TIM15_COMPLEMENTARY) || defined(HAVE_TIM16_COMPLEMENTARY) || \ + defined(HAVE_TIM17_COMPLEMENTARY) || defined(HAVE_LPTIM1_COMPLEMENTARY) || \ + defined(HAVE_LPTIM2_COMPLEMENTARY) +# define HAVE_PWM_COMPLEMENTARY +#endif + +/* Low-level ops helpers ************************************************************/ + +#ifdef CONFIG_STM32L4_PWM_LL_OPS + +/* NOTE: low-level ops accept pwm_lowerhalf_s as first argument, but llops + * access can be found in stm32l4_pwm_dev_s + */ + +#define PWM_SETUP(dev) \ + (dev)->ops->setup((FAR struct pwm_lowerhalf_s *)dev) +#define PWM_SHUTDOWN(dev) \ + (dev)->ops->shutdown((FAR struct pwm_lowerhalf_s *)dev) +#define PWM_CCR_UPDATE(dev, index, ccr) \ + (dev)->llops->ccr_update((FAR struct pwm_lowerhalf_s *)dev, index, ccr) +#define PWM_MODE_UPDATE(dev, index, mode) \ + (dev)->llops->mode_update((FAR struct pwm_lowerhalf_s *)dev, index, mode) +#define PWM_CCR_GET(dev, index) \ + (dev)->llops->ccr_get((FAR struct pwm_lowerhalf_s *)dev, index) +#define PWM_ARR_UPDATE(dev, arr) \ + (dev)->llops->arr_update((FAR struct pwm_lowerhalf_s *)dev, arr) +#define PWM_ARR_GET(dev) \ + (dev)->llops->arr_get((FAR struct pwm_lowerhalf_s *)dev) +#define PWM_OUTPUTS_ENABLE(dev, out, state) \ + (dev)->llops->outputs_enable((FAR struct pwm_lowerhalf_s *)dev, out, state) +#define PWM_SOFT_UPDATE(dev) \ + (dev)->llops->soft_update((FAR struct pwm_lowerhalf_s *)dev) +#define PWM_CONFIGURE(dev) \ + (dev)->llops->configure((FAR struct pwm_lowerhalf_s *)dev) +#define PWM_SOFT_BREAK(dev, state) \ + (dev)->llops->soft_break((FAR struct pwm_lowerhalf_s *)dev, state) +#define PWM_FREQ_UPDATE(dev, freq) \ + (dev)->llops->freq_update((FAR struct pwm_lowerhalf_s *)dev, freq) +#define PWM_TIM_ENABLE(dev, state) \ + (dev)->llops->tim_enable((FAR struct pwm_lowerhalf_s *)dev, state) +#ifdef CONFIG_DEBUG_STM32L4_PWM_INFO +# define PWM_DUMP_REGS(dev, msg) \ + (dev)->llops->dump_regs((FAR struct pwm_lowerhalf_s *)dev, msg) +#else +# define PWM_DUMP_REGS(dev, msg) +#endif +#define PWM_DT_UPDATE(dev, dt) \ + (dev)->llops->dt_update((FAR struct pwm_lowerhalf_s *)dev, dt) +#endif + +/**************************************************************************** * Public Types - ************************************************************************************/ + ****************************************************************************/ -/************************************************************************************ +/* Timer mode */ + +enum stm32l4_timmode_e +{ + STM32L4_TIMMODE_COUNTUP = 0, + STM32L4_TIMMODE_COUNTDOWN = 1, + STM32L4_TIMMODE_CENTER1 = 2, + STM32L4_TIMMODE_CENTER2 = 3, + STM32L4_TIMMODE_CENTER3 = 4, +}; + +/* Timer output polarity */ + +enum stm32l4_pwm_pol_e +{ + STM32L4_POL_POS = 0, + STM32L4_POL_NEG = 1, +}; + +/* Timer output IDLE state */ + +enum stm32l4_pwm_idle_e +{ + STM32L4_IDLE_INACTIVE = 0, + STM32L4_IDLE_ACTIVE = 1 +}; + +/* PWM channel mode */ + +enum stm32l4_chanmode_e +{ + STM32L4_CHANMODE_FRZN = 0, /* CCRx matches has no effects on outputs */ + STM32L4_CHANMODE_CHACT = 1, /* OCxREF active on match */ + STM32L4_CHANMODE_CHINACT = 2, /* OCxREF inactive on match */ + STM32L4_CHANMODE_OCREFTOG = 3, /* OCxREF toggles when TIMy_CNT=TIMyCCRx */ + STM32L4_CHANMODE_OCREFLO = 4, /* OCxREF is forced low */ + STM32L4_CHANMODE_OCREFHI = 5, /* OCxREF is forced high */ + STM32L4_CHANMODE_PWM1 = 6, /* PWM mode 1 */ + STM32L4_CHANMODE_PWM2 = 7, /* PWM mode 2 */ + STM32L4_CHANMODE_COMBINED1 = 8, /* Combined PWM mode 1 */ + STM32L4_CHANMODE_COMBINED2 = 9, /* Combined PWM mode 2 */ + STM32L4_CHANMODE_ASYMMETRIC1 = 10, /* Asymmetric PWM mode 1 */ + STM32L4_CHANMODE_ASYMMETRIC2 = 11, /* Asymmetric PWM mode 2 */ +}; + +/* PWM timer channel */ + +enum stm32l4_pwm_chan_e +{ + STM32L4_PWM_CHAN1 = 1, + STM32L4_PWM_CHAN2 = 2, + STM32L4_PWM_CHAN3 = 3, + STM32L4_PWM_CHAN4 = 4, + STM32L4_PWM_CHAN5 = 5, + STM32L4_PWM_CHAN6 = 6, +}; + +/* PWM timer channel output */ + +enum stm32l4_pwm_output_e +{ + STM32L4_PWM_OUT1 = (1 << 0), + STM32L4_PWM_OUT1N = (1 << 1), + STM32L4_PWM_OUT2 = (1 << 2), + STM32L4_PWM_OUT2N = (1 << 3), + STM32L4_PWM_OUT3 = (1 << 4), + STM32L4_PWM_OUT3N = (1 << 5), + STM32L4_PWM_OUT4 = (1 << 6), + /* 1 << 7 reserved - no complementary output for CH4 */ + /* Only available inside micro */ + STM32L4_PWM_OUT5 = (1 << 8), + /* 1 << 9 reserved - no complementary output for CH5 */ + STM32L4_PWM_OUT6 = (1 << 10), + /* 1 << 11 reserved - no complementary output for CH6 */ +}; + +#ifdef CONFIG_STM32L4_PWM_LL_OPS + +/* This structure provides the publicly visable representation of the + * "lower-half" PWM driver structure. + */ + +struct stm32l4_pwm_dev_s +{ + /* The first field of this state structure must be a pointer to the PWM + * callback structure to be consistent with upper-half PWM driver. + */ + + FAR const struct pwm_ops_s *ops; + + /* Publicly visible portion of the "lower-half" PWM driver structure */ + + FAR const struct stm32l4_pwm_ops_s *llops; + + /* Require cast-compatibility with private "lower-half" PWM strucutre */ +}; + +/* Low-level operations for PWM */ + +struct pwm_lowerhalf_s; +struct stm32l4_pwm_ops_s +{ + /* Update CCR register */ + + int (*ccr_update)(FAR struct pwm_lowerhalf_s *dev, + uint8_t index, uint32_t ccr); + + /* Update PWM mode */ + + int (*mode_update)(FAR struct pwm_lowerhalf_s *dev, + uint8_t index, uint32_t mode); + + /* Get CCR register */ + + uint32_t (*ccr_get)(FAR struct pwm_lowerhalf_s *dev, uint8_t index); + + /* Update ARR register */ + + int (*arr_update)(FAR struct pwm_lowerhalf_s *dev, uint32_t arr); + + /* Get ARR register */ + + uint32_t (*arr_get)(FAR struct pwm_lowerhalf_s *dev); + + /* Enable outputs */ + + int (*outputs_enable)(FAR struct pwm_lowerhalf_s *dev, + uint16_t outputs, bool state); + + /* Software update */ + + int (*soft_update)(FAR struct pwm_lowerhalf_s *dev); + + /* PWM configure */ + + int (*configure)(FAR struct pwm_lowerhalf_s *dev); + + /* Software break */ + + int (*soft_break)(FAR struct pwm_lowerhalf_s *dev, bool state); + + /* Update frequency */ + + int (*freq_update)(FAR struct pwm_lowerhalf_s *dev, uint32_t frequency); + + /* Enable timer counter */ + + int (*tim_enable)(FAR struct pwm_lowerhalf_s *dev, bool state); + +#ifdef CONFIG_DEBUG_PWM_INFO + /* Dump timer registers */ + + void (*dump_regs)(FAR struct pwm_lowerhalf_s *dev, FAR const char *msg); +#endif + +#ifdef HAVE_PWM_COMPLEMENTARY + /* Deadtime update */ + + int (*dt_update)(FAR struct pwm_lowerhalf_s *dev, uint8_t dt); +#endif +}; + +#endif /* CONFIG_STM32L4_PWM_LL_OPS */ + +/**************************************************************************** * Public Data - ************************************************************************************/ + ****************************************************************************/ #ifndef __ASSEMBLY__ @@ -771,11 +1032,11 @@ extern "C" #define EXTERN extern #endif -/************************************************************************************ +/**************************************************************************** * Public Functions - ************************************************************************************/ + ****************************************************************************/ -/************************************************************************************ +/**************************************************************************** * Name: stm32l4_pwminitialize * * Description: @@ -790,7 +1051,7 @@ extern "C" * On success, a pointer to the STM32 lower half PWM driver is returned. * NULL is returned on any failure. * - ************************************************************************************/ + ****************************************************************************/ FAR struct pwm_lowerhalf_s *stm32l4_pwminitialize(int timer); diff --git a/boards/arm/stm32l4/nucleo-l432kc/Kconfig b/boards/arm/stm32l4/nucleo-l432kc/Kconfig index f913f96d1bb..353f988d0fa 100644 --- a/boards/arm/stm32l4/nucleo-l432kc/Kconfig +++ b/boards/arm/stm32l4/nucleo-l432kc/Kconfig @@ -107,4 +107,38 @@ endchoice endmenu +menuconfig NUCLEOL432KC_SPWM + bool "Sinusoidal PWM generator example" + default n + +if NUCLEOL432KC_SPWM + +choice + prompt "Sinusoidal PWM source" + default NUCLEOL432KC_SPWM_USE_TIM1 + +config NUCLEOL432KC_SPWM_USE_TIM1 + bool "Use TIM1 as PWM source" + +endchoice + +config NUCLEOL432KC_SPWM_PWM_FREQ + int "PWM frequency in Hz" + default 100000 + +config NUCLEOL432KC_SPWM_SAMPLES + int "Sine samples" + default 100 + +config NUCLEOL432KC_SPWM_FREQ + int "Waveform frequency in Hz" + default 60 + +config NUCLEOL432KC_SPWM_PHASE_NUM + int "Number of phases" + default 1 + range 1 4 if NUCLEOL432KC_SPWM_USE_TIM1 + +endif + endif # ARCH_BOARD_NUCLEO_L432KC diff --git a/boards/arm/stm32l4/nucleo-l432kc/README.txt b/boards/arm/stm32l4/nucleo-l432kc/README.txt index 5f19b4e166a..aac5e140819 100644 --- a/boards/arm/stm32l4/nucleo-l432kc/README.txt +++ b/boards/arm/stm32l4/nucleo-l432kc/README.txt @@ -535,3 +535,14 @@ Configurations Pin 33 PA10 USART1_TX some RS-232 converters Pin 20 GND Pin 8 U5V + + spwm + ---- + + Configures the sinusoidal PWM (SPWM) example which presents a simple use case + of the STM32L4 PWM lower-half driver without generic upper-half PWM logic. + + It uses TIM1 to generate PWM and TIM6 to change waveform samples + + At the moment, the waveform parameters are hardcoded, but it should be easy to + modify this example and make it more functional. \ No newline at end of file diff --git a/boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig b/boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig new file mode 100755 index 00000000000..6c2ce2b48f7 --- /dev/null +++ b/boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig @@ -0,0 +1,1360 @@ +# +# Automatically generated file; DO NOT EDIT. +# Nuttx/ Configuration +# + +# +# Build Setup +# +# CONFIG_EXPERIMENTAL is not set +# CONFIG_DEFAULT_SMALL is not set +CONFIG_HOST_LINUX=y +# CONFIG_HOST_MACOS is not set +# CONFIG_HOST_WINDOWS is not set +# CONFIG_HOST_OTHER is not set + +# +# Build Configuration +# +CONFIG_APPS_DIR="../apps" +CONFIG_BUILD_FLAT=y +# CONFIG_BUILD_2PASS is not set + +# +# Binary Output Formats +# +# CONFIG_CXD56_BINARY is not set +CONFIG_INTELHEX_BINARY=y +# CONFIG_MOTOROLA_SREC is not set +CONFIG_RAW_BINARY=y +# CONFIG_UBOOT_UIMAGE is not set +# CONFIG_DFU_BINARY is not set + +# +# Customize Header Files +# +# CONFIG_ARCH_HAVE_STDINT_H is not set +# CONFIG_ARCH_HAVE_STDBOOL_H is not set +# CONFIG_ARCH_HAVE_MATH_H is not set +CONFIG_ARCH_FLOAT_H=y +CONFIG_ARCH_HAVE_STDARG_H=y +# CONFIG_ARCH_STDARG_H is not set +CONFIG_ARCH_HAVE_SETJMP=y +# CONFIG_ARCH_SETJMP_H is not set +# CONFIG_ARCH_DEBUG_H is not set + +# +# Debug Options +# +CONFIG_DEBUG_ALERT=y +# CONFIG_DEBUG_FEATURES is not set +CONFIG_ARCH_HAVE_STACKCHECK=y +# CONFIG_STACK_COLORATION is not set +CONFIG_ARCH_HAVE_HEAPCHECK=y +# CONFIG_HEAP_COLORATION is not set +# CONFIG_DEBUG_SYMBOLS is not set +CONFIG_ARCH_HAVE_CUSTOMOPT=y +CONFIG_DEBUG_NOOPT=y +# CONFIG_DEBUG_CUSTOMOPT is not set +# CONFIG_DEBUG_FULLOPT is not set + +# +# System Type +# +CONFIG_ARCH_ARM=y +# CONFIG_ARCH_AVR is not set +# CONFIG_ARCH_HC is not set +# CONFIG_ARCH_MIPS is not set +# CONFIG_ARCH_MISOC is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_RISCV is not set +# CONFIG_ARCH_SIM is not set +# CONFIG_ARCH_X86 is not set +# CONFIG_ARCH_XTENSA is not set +# CONFIG_ARCH_Z16 is not set +# CONFIG_ARCH_Z80 is not set +# CONFIG_ARCH_OR1K is not set +CONFIG_ARCH="arm" + +# +# ARM Options +# +# CONFIG_ARCH_CHIP_A1X is not set +# CONFIG_ARCH_CHIP_AM335X is not set +# CONFIG_ARCH_CHIP_C5471 is not set +# CONFIG_ARCH_CHIP_DM320 is not set +# CONFIG_ARCH_CHIP_EFM32 is not set +# CONFIG_ARCH_CHIP_IMX1 is not set +# CONFIG_ARCH_CHIP_IMX6 is not set +# CONFIG_ARCH_CHIP_IMXRT is not set +# CONFIG_ARCH_CHIP_KINETIS is not set +# CONFIG_ARCH_CHIP_KL is not set +# CONFIG_ARCH_CHIP_LC823450 is not set +# CONFIG_ARCH_CHIP_LM is not set +# CONFIG_ARCH_CHIP_LPC17XX_40XX is not set +# CONFIG_ARCH_CHIP_LPC214X is not set +# CONFIG_ARCH_CHIP_LPC2378 is not set +# CONFIG_ARCH_CHIP_LPC31XX is not set +# CONFIG_ARCH_CHIP_LPC43XX is not set +# CONFIG_ARCH_CHIP_LPC54XX is not set +# CONFIG_ARCH_CHIP_MAX326XX is not set +# CONFIG_ARCH_CHIP_MOXART is not set +# CONFIG_ARCH_CHIP_NRF52 is not set +# CONFIG_ARCH_CHIP_NUC1XX is not set +# CONFIG_ARCH_CHIP_S32K1XX is not set +# CONFIG_ARCH_CHIP_SAMA5 is not set +# CONFIG_ARCH_CHIP_SAMD2X is not set +# CONFIG_ARCH_CHIP_SAML2X is not set +# CONFIG_ARCH_CHIP_SAMD5X is not set +# CONFIG_ARCH_CHIP_SAME5X is not set +# CONFIG_ARCH_CHIP_SAM34 is not set +# CONFIG_ARCH_CHIP_SAMV7 is not set +# CONFIG_ARCH_CHIP_STM32 is not set +# CONFIG_ARCH_CHIP_STM32F0 is not set +# CONFIG_ARCH_CHIP_STM32L0 is not set +# CONFIG_ARCH_CHIP_STM32G0 is not set +# CONFIG_ARCH_CHIP_STM32F7 is not set +# CONFIG_ARCH_CHIP_STM32H7 is not set +CONFIG_ARCH_CHIP_STM32L4=y +# CONFIG_ARCH_CHIP_STR71X is not set +# CONFIG_ARCH_CHIP_TMS570 is not set +# CONFIG_ARCH_CHIP_TIVA is not set +# CONFIG_ARCH_CHIP_XMC4 is not set +# CONFIG_ARCH_CHIP_CXD56XX is not set +# CONFIG_ARCH_ARM7TDMI is not set +# CONFIG_ARCH_ARM920T is not set +# CONFIG_ARCH_ARM926EJS is not set +# CONFIG_ARCH_ARM1136J is not set +# CONFIG_ARCH_ARM1156T2 is not set +# CONFIG_ARCH_ARM1176JZ is not set +# CONFIG_ARCH_CORTEXM0 is not set +# CONFIG_ARCH_CORTEXM23 is not set +CONFIG_ARCH_ARMV7M=y +# CONFIG_ARCH_CORTEXM3 is not set +# CONFIG_ARCH_CORTEXM33 is not set +CONFIG_ARCH_CORTEXM4=y +# CONFIG_ARCH_CORTEXM7 is not set +# CONFIG_ARCH_ARMV7A is not set +# CONFIG_ARCH_CORTEXA5 is not set +# CONFIG_ARCH_CORTEXA7 is not set +# CONFIG_ARCH_CORTEXA8 is not set +# CONFIG_ARCH_CORTEXA9 is not set +# CONFIG_ARCH_ARMV7R is not set +# CONFIG_ARCH_CORTEXR4 is not set +# CONFIG_ARCH_CORTEXR5 is not set +# CONFIG_ARCH_CORTEXR7 is not set +CONFIG_ARCH_FAMILY="armv7-m" +CONFIG_ARCH_CHIP="stm32l4" +# CONFIG_ARCH_HAVE_TRUSTZONE is not set +CONFIG_ARM_HAVE_MPU_UNIFIED=y +# CONFIG_ARM_MPU is not set +CONFIG_ARCH_HAVE_HARDFAULT_DEBUG=y +# CONFIG_DEBUG_HARDFAULT_ALERT is not set +CONFIG_ARCH_HAVE_MEMFAULT_DEBUG=y +# CONFIG_ARM_SEMIHOSTING_SYSLOG is not set + +# +# ARMV7M Configuration Options +# +# CONFIG_ARMV7M_HAVE_ICACHE is not set +# CONFIG_ARMV7M_HAVE_DCACHE is not set +# CONFIG_ARMV7M_LAZYFPU is not set +CONFIG_ARMV7M_USEBASEPRI=y +# CONFIG_ARMV7M_HAVE_ITCM is not set +# CONFIG_ARMV7M_HAVE_DTCM is not set +# CONFIG_ARMV7M_TOOLCHAIN_IARL is not set +# CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT is not set +# CONFIG_ARMV7M_TOOLCHAIN_CODEREDL is not set +CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYL=y +# CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIL is not set +# CONFIG_ARMV7M_TOOLCHAIN_CLANGL is not set +CONFIG_ARMV7M_HAVE_STACKCHECK=y +# CONFIG_ARMV7M_STACKCHECK is not set +# CONFIG_ARMV7M_ITMSYSLOG is not set +# CONFIG_USART2_RS485 is not set +# CONFIG_USART2_RXDMA is not set +# CONFIG_USART2_TXDMA is not set + +# +# STM32L4 Configuration Options +# +# CONFIG_ARCH_CHIP_STM32L412KB is not set +# CONFIG_ARCH_CHIP_STM32L432KB is not set +CONFIG_ARCH_CHIP_STM32L432KC=y +# CONFIG_ARCH_CHIP_STM32L433CB is not set +# CONFIG_ARCH_CHIP_STM32L433CC is not set +# CONFIG_ARCH_CHIP_STM32L433RB is not set +# CONFIG_ARCH_CHIP_STM32L433RC is not set +# CONFIG_ARCH_CHIP_STM32L433VC is not set +# CONFIG_ARCH_CHIP_STM32L442KC is not set +# CONFIG_ARCH_CHIP_STM32L443CC is not set +# CONFIG_ARCH_CHIP_STM32L443RC is not set +# CONFIG_ARCH_CHIP_STM32L443VC is not set +# CONFIG_ARCH_CHIP_STM32L451CC is not set +# CONFIG_ARCH_CHIP_STM32L451CE is not set +# CONFIG_ARCH_CHIP_STM32L451RC is not set +# CONFIG_ARCH_CHIP_STM32L451RE is not set +# CONFIG_ARCH_CHIP_STM32L451VC is not set +# CONFIG_ARCH_CHIP_STM32L451VE is not set +# CONFIG_ARCH_CHIP_STM32L452CC is not set +# CONFIG_ARCH_CHIP_STM32L452CE is not set +# CONFIG_ARCH_CHIP_STM32L452RC is not set +# CONFIG_ARCH_CHIP_STM32L452RE is not set +# CONFIG_ARCH_CHIP_STM32L452VC is not set +# CONFIG_ARCH_CHIP_STM32L452VE is not set +# CONFIG_ARCH_CHIP_STM32L462CE is not set +# CONFIG_ARCH_CHIP_STM32L462RE is not set +# CONFIG_ARCH_CHIP_STM32L462VE is not set +# CONFIG_ARCH_CHIP_STM32L475RG is not set +# CONFIG_ARCH_CHIP_STM32L475RE is not set +# CONFIG_ARCH_CHIP_STM32L475RC is not set +# CONFIG_ARCH_CHIP_STM32L475VG is not set +# CONFIG_ARCH_CHIP_STM32L475VE is not set +# CONFIG_ARCH_CHIP_STM32L475VC is not set +# CONFIG_ARCH_CHIP_STM32L476RG is not set +# CONFIG_ARCH_CHIP_STM32L476RE is not set +# CONFIG_ARCH_CHIP_STM32L486RG is not set +# CONFIG_ARCH_CHIP_STM32L486JG is not set +# CONFIG_ARCH_CHIP_STM32L486VG is not set +# CONFIG_ARCH_CHIP_STM32L486QG is not set +# CONFIG_ARCH_CHIP_STM32L486ZG is not set +# CONFIG_ARCH_CHIP_STM32L496RE is not set +# CONFIG_ARCH_CHIP_STM32L496RG is not set +# CONFIG_ARCH_CHIP_STM32L496VE is not set +# CONFIG_ARCH_CHIP_STM32L496VG is not set +# CONFIG_ARCH_CHIP_STM32L496ZE is not set +# CONFIG_ARCH_CHIP_STM32L496ZG is not set +# CONFIG_ARCH_CHIP_STM32L496AG is not set +# CONFIG_ARCH_CHIP_STM32L4A6RG is not set +# CONFIG_ARCH_CHIP_STM32L4A6VG is not set +# CONFIG_ARCH_CHIP_STM32L4A6QG is not set +# CONFIG_ARCH_CHIP_STM32L4A6ZG is not set +# CONFIG_ARCH_CHIP_STM32L4A6AG is not set +# CONFIG_ARCH_CHIP_STM32L4R5ZI is not set +# CONFIG_ARCH_CHIP_STM32L4R9AI is not set +# CONFIG_STM32L4_STM32L4X1 is not set +CONFIG_STM32L4_STM32L4X2=y +CONFIG_STM32L4_STM32L4X3=y +# CONFIG_STM32L4_STM32L4X5 is not set +# CONFIG_STM32L4_STM32L4X6 is not set +# CONFIG_STM32L4_STM32L4XR is not set +# CONFIG_STM32L4_STM32L412XX is not set +# CONFIG_STM32L4_STM32L422XX is not set +# CONFIG_STM32L4_STM32L431XX is not set +CONFIG_STM32L4_STM32L432XX=y +# CONFIG_STM32L4_STM32L433XX is not set +# CONFIG_STM32L4_STM32L442XX is not set +# CONFIG_STM32L4_STM32L443XX is not set +# CONFIG_STM32L4_STM32L451XX is not set +# CONFIG_STM32L4_STM32L452XX is not set +# CONFIG_STM32L4_STM32L462XX is not set +# CONFIG_STM32L4_STM32L471XX is not set +# CONFIG_STM32L4_STM32L475XX is not set +# CONFIG_STM32L4_STM32L476XX is not set +# CONFIG_STM32L4_STM32L486XX is not set +# CONFIG_STM32L4_STM32L496XX is not set +# CONFIG_STM32L4_STM32L4A6XX is not set +# CONFIG_STM32L4_STM32L4R5XX is not set +# CONFIG_STM32L4_STM32L4S5XX is not set +# CONFIG_STM32L4_STM32L4R7XX is not set +# CONFIG_STM32L4_STM32L4S7XX is not set +# CONFIG_STM32L4_STM32L4R9XX is not set +# CONFIG_STM32L4_STM32L4S9XX is not set +CONFIG_STM32L4_FLASH_OVERRIDE_DEFAULT=y +# CONFIG_STM32L4_FLASH_OVERRIDE_8 is not set +# CONFIG_STM32L4_FLASH_OVERRIDE_B is not set +# CONFIG_STM32L4_FLASH_OVERRIDE_C is not set +# CONFIG_STM32L4_FLASH_OVERRIDE_E is not set +# CONFIG_STM32L4_FLASH_OVERRIDE_G is not set +# CONFIG_STM32L4_FLASH_OVERRIDE_I is not set +# CONFIG_STM32L4_FLASH_CONFIG_B is not set +CONFIG_STM32L4_FLASH_CONFIG_C=y +# CONFIG_STM32L4_FLASH_CONFIG_E is not set +CONFIG_STM32L4_IO_CONFIG_K=y +# CONFIG_STM32L4_IO_CONFIG_T is not set +# CONFIG_STM32L4_IO_CONFIG_C is not set +# CONFIG_STM32L4_IO_CONFIG_R is not set +# CONFIG_STM32L4_IO_CONFIG_J is not set +# CONFIG_STM32L4_IO_CONFIG_M is not set +# CONFIG_STM32L4_IO_CONFIG_V is not set +# CONFIG_STM32L4_IO_CONFIG_Q is not set +# CONFIG_STM32L4_IO_CONFIG_Z is not set +# CONFIG_STM32L4_IO_CONFIG_A is not set + +# +# STM32L4 SRAM2 and SRAM3 Options +# +CONFIG_STM32L4_SRAM2_HEAP=y +CONFIG_STM32L4_SRAM2_INIT=y + +# +# STM32L4 Peripherals +# + +# +# STM32L4 Peripheral Support +# +# CONFIG_STM32L4_HAVE_ADC2 is not set +# CONFIG_STM32L4_HAVE_ADC3 is not set +# CONFIG_STM32L4_HAVE_AES is not set +# CONFIG_STM32L4_HAVE_CAN2 is not set +CONFIG_STM32L4_HAVE_COMP=y +CONFIG_STM32L4_HAVE_DAC2=y +# CONFIG_STM32L4_HAVE_DCMI is not set +# CONFIG_STM32L4_HAVE_DFSDM1 is not set +# CONFIG_STM32L4_HAVE_DMA2D is not set +# CONFIG_STM32L4_HAVE_DMAMUX is not set +# CONFIG_STM32L4_HAVE_FSMC is not set +# CONFIG_STM32L4_HAVE_HASH is not set +CONFIG_STM32L4_HAVE_HSI48=y +# CONFIG_STM32L4_HAVE_I2C4 is not set +# CONFIG_STM32L4_HAVE_LCD is not set +# CONFIG_STM32L4_HAVE_LTDC is not set +CONFIG_STM32L4_HAVE_LPTIM1=y +CONFIG_STM32L4_HAVE_LPTIM2=y +# CONFIG_STM32L4_HAVE_OTGFS is not set +CONFIG_STM32L4_HAVE_USBFS=y +CONFIG_STM32L4_HAVE_SAI1=y +# CONFIG_STM32L4_HAVE_SAI2 is not set +# CONFIG_STM32L4_RTC is not set +# CONFIG_STM32L4_HAVE_SDMMC1 is not set +# CONFIG_STM32L4_HAVE_TIM3 is not set +# CONFIG_STM32L4_HAVE_TIM4 is not set +# CONFIG_STM32L4_HAVE_TIM5 is not set +CONFIG_STM32L4_HAVE_TIM7=y +# CONFIG_STM32L4_HAVE_TIM8 is not set +# CONFIG_STM32L4_HAVE_TIM17 is not set +CONFIG_STM32L4_HAVE_USART1=y +CONFIG_STM32L4_HAVE_USART2=y +# CONFIG_STM32L4_HAVE_USART3 is not set +# CONFIG_STM32L4_HAVE_UART4 is not set +# CONFIG_STM32L4_HAVE_UART5 is not set +# CONFIG_STM32L4_HAVE_QSPI is not set +# CONFIG_STM32L4_ADC is not set +# CONFIG_STM32L4_CAN is not set +# CONFIG_STM32L4_DAC is not set +# CONFIG_STM32L4_DFSDM is not set +CONFIG_STM32L4_DMA=y +# CONFIG_STM32L4_I2C is not set +# CONFIG_STM32L4_SAI is not set +# CONFIG_STM32L4_SPI is not set +CONFIG_STM32L4_USART=y +# CONFIG_STM32L4_LPTIM is not set +# CONFIG_STM32L4_SDMMC is not set + +# +# AHB1 Peripherals +# +CONFIG_STM32L4_DMA1=y +CONFIG_STM32L4_DMA2=y +# CONFIG_STM32L4_CRC is not set +# CONFIG_STM32L4_TSC is not set + +# +# AHB2 Peripherals +# +# CONFIG_STM32L4_ADC1 is not set +# CONFIG_STM32L4_RNG is not set + +# +# AHB3 Peripherals +# + +# +# APB1 Peripherals +# +# CONFIG_STM32L4_PWR is not set +# CONFIG_STM32L4_TIM2 is not set +CONFIG_STM32L4_TIM6=y +# CONFIG_STM32L4_TIM7 is not set +# CONFIG_STM32L4_SPI3 is not set +CONFIG_STM32L4_USART2=y +# CONFIG_STM32L4_I2C1 is not set +# CONFIG_STM32L4_I2C3 is not set +# CONFIG_STM32L4_CAN1 is not set +# CONFIG_STM32L4_DAC1 is not set +# CONFIG_STM32L4_DAC2 is not set +# CONFIG_STM32L4_OPAMP is not set +# CONFIG_STM32L4_LPTIM1 is not set +# CONFIG_STM32L4_LPUART1 is not set +# CONFIG_STM32L4_SWPMI is not set +# CONFIG_STM32L4_LPTIM2 is not set +# CONFIG_STM32L4_USBFS is not set + +# +# APB2 Peripherals +# +# CONFIG_STM32L4_SYSCFG is not set +CONFIG_STM32L4_TIM1=y +# CONFIG_STM32L4_SPI1 is not set +# CONFIG_STM32L4_USART1 is not set +# CONFIG_STM32L4_TIM15 is not set +# CONFIG_STM32L4_TIM16 is not set +# CONFIG_STM32L4_COMP is not set +# CONFIG_STM32L4_SAI1 is not set + +# +# Other Peripherals +# +# CONFIG_STM32L4_BKPSRAM is not set +# CONFIG_STM32L4_IWDG is not set +# CONFIG_STM32L4_WWDG is not set +# CONFIG_STM32L4_SAI1PLL is not set +CONFIG_STM32L4_FLASH_PREFETCH=y +CONFIG_STM32L4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y +# CONFIG_ARCH_BOARD_STM32L4_CUSTOM_CLOCKCONFIG is not set +CONFIG_STM32L4_HAVE_RTC_SUBSECONDS=y + +# +# Timer Configuration +# +# CONFIG_STM32L4_ONESHOT is not set +# CONFIG_STM32L4_FREERUN is not set +CONFIG_STM32L4_PWM_LL_OPS=y +CONFIG_STM32L4_TIM1_PWM=y +CONFIG_STM32L4_TIM1_MODE=0 +CONFIG_STM32L4_TIM1_LOCK=0 +CONFIG_STM32L4_TIM1_TDTS=0 +CONFIG_STM32L4_TIM1_DEADTIME=0 +CONFIG_STM32L4_TIM1_CH1OUT=y +CONFIG_STM32L4_TIM1_CH1NOUT=y +CONFIG_STM32L4_TIM1_CHANNEL=1 +CONFIG_STM32L4_TIM1_CHMODE=6 +# CONFIG_STM32L4_PWM_MULTICHAN is not set + +# +# STM32L4 TIMx Outputs Configuration +# +CONFIG_STM32L4_TIM1_CH1POL=0 +CONFIG_STM32L4_TIM1_CH1IDLE=0 +CONFIG_STM32L4_TIM1_CH1NPOL=0 +CONFIG_STM32L4_TIM1_CH1NIDLE=0 +CONFIG_STM32L4_SERIALDRIVER=y + +# +# U[S]ART Configuration +# +CONFIG_STM32L4_USART2_SERIALDRIVER=y +# CONFIG_STM32L4_USART2_1WIREDRIVER is not set + +# +# Serial Driver Configuration +# +# CONFIG_STM32L4_SERIAL_DISABLE_REORDERING is not set +# CONFIG_STM32L4_FLOWCONTROL_BROKEN is not set +# CONFIG_STM32L4_USART_BREAKS is not set +# CONFIG_STM32L4_USART_SINGLEWIRE is not set +# CONFIG_STM32L4_USART_INVERT is not set +# CONFIG_STM32L4_USART_SWAP is not set +# CONFIG_ARCH_TOOLCHAIN_IAR is not set +CONFIG_ARCH_TOOLCHAIN_GNU=y +# CONFIG_ARCH_GNU_NO_WEAKFUNCTIONS is not set + +# +# Architecture Options +# +# CONFIG_ARCH_NOINTC is not set +# CONFIG_ARCH_VECNOTIRQ is not set +CONFIG_ARCH_HAVE_IRQTRIGGER=y +CONFIG_ARCH_DMA=y +CONFIG_ARCH_HAVE_IRQPRIO=y +# CONFIG_ARCH_ICACHE is not set +# CONFIG_ARCH_DCACHE is not set +# CONFIG_ARCH_L2CACHE is not set +# CONFIG_ARCH_HAVE_ADDRENV is not set +# CONFIG_ARCH_NEED_ADDRENV_MAPPING is not set +# CONFIG_ARCH_HAVE_MULTICPU is not set +CONFIG_ARCH_HAVE_VFORK=y +CONFIG_ARCH_HAVE_FPU=y +# CONFIG_ARCH_HAVE_DPFPU is not set +CONFIG_ARCH_HAVE_LAZYFPU=y +# CONFIG_ARCH_HAVE_MMU is not set +CONFIG_ARCH_HAVE_MPU=y +# CONFIG_ARCH_NAND_HWECC is not set +# CONFIG_ARCH_HAVE_EXTCLK is not set +# CONFIG_ARCH_HAVE_POWEROFF is not set +CONFIG_ARCH_HAVE_PROGMEM=y +CONFIG_ARCH_HAVE_RESET=y +CONFIG_ARCH_HAVE_TESTSET=y +CONFIG_ARCH_HAVE_FETCHADD=y +CONFIG_ARCH_HAVE_RTC_SUBSECONDS=y +# CONFIG_ARCH_HAVE_GARBAGE is not set +# CONFIG_ARCH_GLOBAL_IRQDISABLE is not set +CONFIG_ARCH_FPU=y +# CONFIG_ARCH_USE_MPU is not set +CONFIG_ARCH_IRQPRIO=y +CONFIG_ARCH_STACKDUMP=y +# CONFIG_ENDIAN_BIG is not set +# CONFIG_ARCH_IDLE_CUSTOM is not set +# CONFIG_ARCH_HAVE_RAMFUNCS is not set +CONFIG_ARCH_HAVE_RAMVECTORS=y +CONFIG_ARCH_RAMVECTORS=y +# CONFIG_ARCH_MINIMAL_VECTORTABLE is not set + +# +# Board Settings +# +CONFIG_BOARD_LOOPSPERMSEC=8499 + +# +# Interrupt options +# +CONFIG_ARCH_HAVE_INTERRUPTSTACK=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_HAVE_HIPRI_INTERRUPT=y +CONFIG_ARCH_HIPRI_INTERRUPT=y + +# +# Boot options +# +# CONFIG_BOOT_RUNFROMEXTSRAM is not set +CONFIG_BOOT_RUNFROMFLASH=y +# CONFIG_BOOT_RUNFROMISRAM is not set +# CONFIG_BOOT_RUNFROMSDRAM is not set +# CONFIG_BOOT_COPYTORAM is not set + +# +# Boot Memory Configuration +# +CONFIG_RAM_START=0x20000000 +CONFIG_RAM_SIZE=65536 +# CONFIG_ARCH_HAVE_SDRAM is not set + +# +# Board Selection +# +CONFIG_ARCH_BOARD_NUCLEO_L432KC=y +# CONFIG_ARCH_BOARD_CUSTOM is not set +CONFIG_ARCH_BOARD="nucleo-l432kc" + +# +# Common Board Options +# +CONFIG_ARCH_HAVE_LEDS=y +CONFIG_ARCH_LEDS=y +CONFIG_ARCH_HAVE_BUTTONS=y +# CONFIG_ARCH_BUTTONS is not set +CONFIG_ARCH_HAVE_IRQBUTTONS=y + +# +# Board-Specific Options +# + +# +# U[S]ART Pin Layouts +# + +# +# USART1 is disabled. (Enable it under: System Type -> STM32L4 Peripheral Support) +# +# CONFIG_ARCH_BOARD_USART2_RX_PA3 is not set +CONFIG_ARCH_BOARD_USART2_RX_PA15=y +CONFIG_ARCH_BOARD_USART2_TX_PA2=y + +# +# LPUART1 is disabled. (Enable it under: System Type -> STM32L4 Peripheral Support) +# +CONFIG_NUCLEOL432KC_SPWM=y +CONFIG_NUCLEOL432KC_SPWM_USE_TIM1=y +CONFIG_NUCLEOL432KC_SPWM_PWM_FREQ=200000 +CONFIG_NUCLEOL432KC_SPWM_SAMPLES=100 +CONFIG_NUCLEOL432KC_SPWM_FREQ=60 +CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM=1 +# CONFIG_BOARD_CRASHDUMP is not set +CONFIG_LIB_BOARDCTL=y +# CONFIG_BOARDCTL_FINALINIT is not set +# CONFIG_BOARDCTL_RESET is not set +# CONFIG_BOARDCTL_UNIQUEID is not set +CONFIG_BOARDCTL_MKRD=y +# CONFIG_BOARDCTL_ROMDISK is not set +# CONFIG_BOARDCTL_APP_SYMTAB is not set +# CONFIG_BOARDCTL_TESTSET is not set +# CONFIG_BOARDCTL_IOCTL is not set + +# +# RTOS Features +# +CONFIG_DISABLE_OS_API=y +# CONFIG_DISABLE_POSIX_TIMERS is not set +# CONFIG_DISABLE_PTHREAD is not set +# CONFIG_DISABLE_MQUEUE is not set +# CONFIG_DISABLE_ENVIRON is not set + +# +# Clocks and Timers +# +CONFIG_ARCH_HAVE_TICKLESS=y +# CONFIG_SCHED_TICKLESS is not set +CONFIG_USEC_PER_TICK=10000 +# CONFIG_SYSTEMTICK_HOOK is not set +# CONFIG_SYSTEM_TIME64 is not set +# CONFIG_CLOCK_MONOTONIC is not set +# CONFIG_ARCH_HAVE_TIMEKEEPING is not set +# CONFIG_JULIAN_TIME is not set +CONFIG_START_YEAR=2018 +CONFIG_START_MONTH=1 +CONFIG_START_DAY=1 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_PREALLOC_WDOGS=8 +CONFIG_WDOG_INTRESERVE=1 +CONFIG_PREALLOC_TIMERS=4 + +# +# Tasks and Scheduling +# +# CONFIG_SPINLOCK is not set +# CONFIG_IRQCHAIN is not set +# CONFIG_IRQCOUNT is not set +# CONFIG_INIT_NONE is not set +CONFIG_INIT_ENTRYPOINT=y +# CONFIG_INIT_FILEPATH is not set +CONFIG_USER_ENTRYPOINT="spwm_main" +CONFIG_USERMAIN_PRIORITY=100 +CONFIG_RR_INTERVAL=200 +# CONFIG_SCHED_SPORADIC is not set +CONFIG_TASK_NAME_SIZE=0 +CONFIG_MAX_TASKS=16 +# CONFIG_SCHED_HAVE_PARENT is not set +CONFIG_SCHED_WAITPID=y +# CONFIG_SCHED_USER_IDENTITY is not set + +# +# Pthread Options +# +CONFIG_NPTHREAD_KEYS=4 +# CONFIG_PTHREAD_MUTEX_TYPES is not set +CONFIG_PTHREAD_MUTEX_ROBUST=y +# CONFIG_PTHREAD_MUTEX_UNSAFE is not set +# CONFIG_PTHREAD_MUTEX_BOTH is not set +# CONFIG_PTHREAD_CLEANUP is not set +# CONFIG_CANCELLATION_POINTS is not set + +# +# Performance Monitoring +# +# CONFIG_SCHED_SUSPENDSCHEDULER is not set +# CONFIG_SCHED_RESUMESCHEDULER is not set +# CONFIG_SCHED_CPULOAD is not set +# CONFIG_SCHED_INSTRUMENTATION is not set + +# +# Files and I/O +# +CONFIG_DEV_CONSOLE=y +# CONFIG_FDCLONE_DISABLE is not set +# CONFIG_FDCLONE_STDIO is not set +CONFIG_SDCLONE_DISABLE=y +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NAME_MAX=32 +# CONFIG_PRIORITY_INHERITANCE is not set + +# +# RTOS hooks +# +# CONFIG_BOARD_EARLY_INITIALIZE is not set +# CONFIG_BOARD_LATE_INITIALIZE is not set +# CONFIG_SCHED_STARTHOOK is not set +# CONFIG_SCHED_ATEXIT is not set +# CONFIG_SCHED_ONEXIT is not set + +# +# Signal Configuration +# +# CONFIG_SIG_DEFAULT is not set + +# +# Signal Numbers +# + +# +# Standard Signal Numbers +# +CONFIG_SIG_SIGUSR1=1 +CONFIG_SIG_SIGUSR2=2 +CONFIG_SIG_SIGALRM=3 +CONFIG_SIG_PIPE=11 + +# +# Non-standard Signal Numbers +# +CONFIG_SIG_SIGCONDTIMEDOUT=16 + +# +# POSIX Message Queue Options +# +CONFIG_PREALLOC_MQ_MSGS=4 +CONFIG_MQ_MAXMSGSIZE=32 +# CONFIG_MODULE is not set + +# +# Work queue support +# +# CONFIG_SCHED_WORKQUEUE is not set +# CONFIG_SCHED_HPWORK is not set +# CONFIG_SCHED_LPWORK is not set + +# +# Stack and heap information +# +CONFIG_IDLETHREAD_STACKSIZE=1024 +CONFIG_USERMAIN_STACKSIZE=2048 +CONFIG_PTHREAD_STACK_MIN=256 +CONFIG_PTHREAD_STACK_DEFAULT=2048 +# CONFIG_LIB_SYSCALL is not set + +# +# Device Drivers +# +# CONFIG_DEV_SIMPLE_ADDRENV is not set +CONFIG_DEV_NULL=y +# CONFIG_DEV_ZERO is not set +# CONFIG_DEV_URANDOM is not set +# CONFIG_DEV_LOOP is not set +CONFIG_DRVR_MKRD=y + +# +# Buffering +# +# CONFIG_DRVR_WRITEBUFFER is not set +# CONFIG_DRVR_READAHEAD is not set +# CONFIG_RAMDISK is not set +# CONFIG_CAN is not set +CONFIG_ARCH_HAVE_PWM_PULSECOUNT=y +# CONFIG_ARCH_HAVE_PWM_MULTICHAN is not set +CONFIG_ARCH_HAVE_I2CRESET=y +# CONFIG_I2C is not set +# CONFIG_ARCH_HAVE_SPI_CRCGENERATION is not set +# CONFIG_ARCH_HAVE_SPI_CS_CONTROL is not set +CONFIG_ARCH_HAVE_SPI_BITORDER=y +CONFIG_SPI=y +# CONFIG_SPI_SLAVE is not set +CONFIG_SPI_EXCHANGE=y +# CONFIG_SPI_CMDDATA is not set +# CONFIG_SPI_CALLBACK is not set +# CONFIG_SPI_HWFEATURES is not set +# CONFIG_SPI_BITORDER is not set +# CONFIG_SPI_CS_DELAY_CONTROL is not set +# CONFIG_SPI_TRIGGER is not set +# CONFIG_SPI_DRIVER is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_I2S is not set + +# +# Timer Driver Support +# +CONFIG_PWM=y +# CONFIG_PWM_PULSECOUNT is not set +# CONFIG_TIMER is not set +# CONFIG_ONESHOT is not set +# CONFIG_RTC is not set +# CONFIG_WATCHDOG is not set +# CONFIG_ANALOG is not set +# CONFIG_DRIVERS_AUDIO is not set +# CONFIG_FB_CMAP is not set +# CONFIG_FB_TRANSPARENCY is not set +# CONFIG_DRIVERS_VIDEO is not set +# CONFIG_BCH is not set +# CONFIG_INPUT is not set + +# +# IO Expander/GPIO Support +# +# CONFIG_IOEXPANDER is not set +# CONFIG_DEV_GPIO is not set + +# +# LCD Driver Support +# +# CONFIG_LCD is not set + +# +# Character/Segment LCD Devices +# +# CONFIG_SLCD is not set + +# +# Other LCD-related Devices +# +# CONFIG_LCD_OTHER is not set + +# +# LED Support +# +# CONFIG_USERLED is not set +# CONFIG_LEDS_APA102 is not set +# CONFIG_LEDS_MAX7219 is not set +# CONFIG_RGBLED is not set +# CONFIG_PCA9635PW is not set +# CONFIG_NCP5623C is not set +# CONFIG_ARCH_HAVE_SDIO is not set +# CONFIG_ARCH_HAVE_SDIOWAIT_WRCOMPLETE is not set +# CONFIG_ARCH_HAVE_SDIO_PREFLIGHT is not set +# CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT is not set +# CONFIG_MMCSD is not set +# CONFIG_MODEM is not set +# CONFIG_MTD is not set +# CONFIG_EEPROM is not set +# CONFIG_PIPES is not set +# CONFIG_PM is not set +# CONFIG_DRIVERS_POWERLED is not set +# CONFIG_DRIVERS_SMPS is not set +# CONFIG_DRIVERS_MOTOR is not set +# CONFIG_POWER is not set +# CONFIG_SENSORS is not set +CONFIG_SERIAL=y +# CONFIG_DEV_LOWCONSOLE is not set +# CONFIG_SERIAL_REMOVABLE is not set +CONFIG_SERIAL_CONSOLE=y +# CONFIG_16550_UART is not set +# CONFIG_OTHER_UART_SERIALDRIVER is not set +CONFIG_MCU_SERIAL=y +CONFIG_STANDARD_SERIAL=y +CONFIG_SERIAL_NPOLLWAITERS=2 +# CONFIG_SERIAL_IFLOWCONTROL is not set +# CONFIG_SERIAL_RS485CONTROL is not set +# CONFIG_SERIAL_OFLOWCONTROL is not set +# CONFIG_SERIAL_TXDMA is not set +# CONFIG_SERIAL_RXDMA is not set +CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y +# CONFIG_SERIAL_TERMIOS is not set +CONFIG_USART2_SERIAL_CONSOLE=y +# CONFIG_OTHER_SERIAL_CONSOLE is not set +# CONFIG_NO_SERIAL_CONSOLE is not set +# CONFIG_UART_SERIALDRIVER is not set +# CONFIG_UART0_SERIALDRIVER is not set +# CONFIG_UART1_SERIALDRIVER is not set +# CONFIG_UART2_SERIALDRIVER is not set +# CONFIG_UART3_SERIALDRIVER is not set +# CONFIG_UART4_SERIALDRIVER is not set +# CONFIG_UART5_SERIALDRIVER is not set +# CONFIG_UART6_SERIALDRIVER is not set +# CONFIG_UART7_SERIALDRIVER is not set +# CONFIG_UART8_SERIALDRIVER is not set +# CONFIG_LPUART_SERIALDRIVER is not set +# CONFIG_LPUART0_SERIALDRIVER is not set +# CONFIG_LPUART1_SERIALDRIVER is not set +# CONFIG_LPUART2_SERIALDRIVER is not set +# CONFIG_LPUART3_SERIALDRIVER is not set +# CONFIG_LPUART4_SERIALDRIVER is not set +# CONFIG_LPUART5_SERIALDRIVER is not set +# CONFIG_LPUART6_SERIALDRIVER is not set +# CONFIG_LPUART7_SERIALDRIVER is not set +# CONFIG_LPUART8_SERIALDRIVER is not set +# CONFIG_USART0_SERIALDRIVER is not set +# CONFIG_USART1_SERIALDRIVER is not set +CONFIG_USART2_SERIALDRIVER=y +# CONFIG_USART3_SERIALDRIVER is not set +# CONFIG_USART4_SERIALDRIVER is not set +# CONFIG_USART5_SERIALDRIVER is not set +# CONFIG_USART6_SERIALDRIVER is not set +# CONFIG_USART7_SERIALDRIVER is not set +# CONFIG_USART8_SERIALDRIVER is not set +# CONFIG_USART9_SERIALDRIVER is not set + +# +# USART2 Configuration +# +CONFIG_USART2_RXBUFSIZE=256 +CONFIG_USART2_TXBUFSIZE=256 +CONFIG_USART2_BAUD=115200 +CONFIG_USART2_BITS=8 +CONFIG_USART2_PARITY=0 +CONFIG_USART2_2STOP=0 +# CONFIG_USART2_IFLOWCONTROL is not set +# CONFIG_USART2_OFLOWCONTROL is not set +# CONFIG_SCI0_SERIALDRIVER is not set +# CONFIG_SCI1_SERIALDRIVER is not set +# CONFIG_SCI2_SERIALDRIVER is not set +# CONFIG_SCI3_SERIALDRIVER is not set +# CONFIG_SCI4_SERIALDRIVER is not set +# CONFIG_SCI5_SERIALDRIVER is not set +# CONFIG_SCI6_SERIALDRIVER is not set +# CONFIG_SCI7_SERIALDRIVER is not set +# CONFIG_SCI8_SERIALDRIVER is not set +# CONFIG_SCI9_SERIALDRIVER is not set +# CONFIG_SCI10_SERIALDRIVER is not set +# CONFIG_SCI11_SERIALDRIVER is not set +# CONFIG_SCI12_SERIALDRIVER is not set +# CONFIG_PSEUDOTERM is not set +# CONFIG_USBDEV is not set +# CONFIG_USBHOST is not set +# CONFIG_USBMISC is not set +# CONFIG_HAVE_USBTRACE is not set +# CONFIG_DRIVERS_WIRELESS is not set +# CONFIG_DRIVERS_CONTACTLESS is not set +# CONFIG_1WIRE is not set + +# +# System Logging +# +# CONFIG_ARCH_SYSLOG is not set +CONFIG_SYSLOG_WRITE=y +# CONFIG_RAMLOG is not set +# CONFIG_SYSLOG_BUFFER is not set +# CONFIG_SYSLOG_INTBUFFER is not set +# CONFIG_SYSLOG_TIMESTAMP is not set +# CONFIG_SYSLOG_PREFIX is not set +CONFIG_SYSLOG_SERIAL_CONSOLE=y +# CONFIG_SYSLOG_CHAR is not set +CONFIG_SYSLOG_CONSOLE=y +# CONFIG_SYSLOG_NONE is not set +# CONFIG_SYSLOG_FILE is not set +# CONFIG_SYSLOG_CHARDEV is not set +# CONFIG_SPECIFIC_DRIVERS is not set +# CONFIG_DRIVERS_RF is not set + +# +# Networking Support +# +# CONFIG_ARCH_HAVE_NET is not set +# CONFIG_ARCH_HAVE_PHY is not set +# CONFIG_NET_WRITE_BUFFERS is not set +# CONFIG_NET_READAHEAD is not set +# CONFIG_NET_MCASTGROUP is not set +# CONFIG_NET is not set + +# +# Crypto API +# +# CONFIG_CRYPTO is not set + +# +# File Systems +# + +# +# File system configuration +# +# CONFIG_DISABLE_MOUNTPOINT is not set +# CONFIG_FS_AUTOMOUNTER is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_PSEUDOFS_SOFTLINKS is not set +CONFIG_FS_READABLE=y +CONFIG_FS_WRITABLE=y +# CONFIG_FS_NAMED_SEMAPHORES is not set +CONFIG_FS_MQUEUE_MPATH="/var/mqueue" +# CONFIG_FS_RAMMAP is not set + +# +# Partition Table +# +# CONFIG_PTABLE_PARTITION is not set +# CONFIG_FS_FAT is not set +# CONFIG_FS_NXFFS is not set +# CONFIG_FS_ROMFS is not set +# CONFIG_FS_CROMFS is not set +# CONFIG_FS_TMPFS is not set +# CONFIG_FS_SMARTFS is not set +# CONFIG_FS_BINFS is not set +# CONFIG_FS_PROCFS is not set +# CONFIG_FS_SPIFFS is not set +# CONFIG_FS_LITTLEFS is not set +# CONFIG_FS_UNIONFS is not set +# CONFIG_FS_HOSTFS is not set + +# +# Graphics Support +# +# CONFIG_NX is not set +# CONFIG_NXFONTS is not set + +# +# Font Cache Pixel Depths +# +# CONFIG_NXFONTS_DISABLE_1BPP is not set +# CONFIG_NXFONTS_DISABLE_2BPP is not set +# CONFIG_NXFONTS_DISABLE_4BPP is not set +# CONFIG_NXFONTS_DISABLE_8BPP is not set +# CONFIG_NXFONTS_DISABLE_16BPP is not set +# CONFIG_NXFONTS_DISABLE_24BPP is not set +# CONFIG_NXFONTS_DISABLE_32BPP is not set +CONFIG_NXFONTS_PACKEDMSFIRST=y +# CONFIG_NXGLIB is not set + +# +# Memory Management +# +# CONFIG_MM_SMALL is not set +CONFIG_MM_REGIONS=2 +# CONFIG_ARCH_HAVE_HEAP2 is not set +# CONFIG_GRAN is not set +# CONFIG_MM_FILL_ALLOCATIONS is not set + +# +# Common I/O Buffer Support +# +# CONFIG_MM_IOB is not set + +# +# Audio Support +# +# CONFIG_AUDIO is not set + +# +# Video Support +# + +# +# Video subsystem +# +# CONFIG_VIDEO is not set + +# +# Wireless Support +# +# CONFIG_WIRELESS is not set + +# +# Binary Loader +# +# CONFIG_BINFMT_DISABLE is not set +# CONFIG_BINFMT_LOADABLE is not set +# CONFIG_PIC is not set +# CONFIG_NXFLAT is not set +# CONFIG_ELF is not set +# CONFIG_SYMTAB_ORDEREDBYNAME is not set + +# +# Library Routines +# + +# +# Standard C Library Options +# + +# +# Standard C I/O +# +# CONFIG_STDIO_DISABLE_BUFFERING is not set +CONFIG_STDIO_BUFFER_SIZE=64 +CONFIG_STDIO_LINEBUFFER=y +CONFIG_NUNGET_CHARS=2 +# CONFIG_LIBC_PRINT_LEGACY is not set +# CONFIG_LIBC_FLOATINGPOINT is not set +CONFIG_LIBC_LONG_LONG=y +# CONFIG_LIBC_NUMBERED_ARGS is not set +# CONFIG_LIBC_SCANSET is not set +# CONFIG_EOL_IS_CR is not set +# CONFIG_EOL_IS_LF is not set +# CONFIG_EOL_IS_BOTH_CRLF is not set +CONFIG_EOL_IS_EITHER_CRLF=y +# CONFIG_MEMCPY_VIK is not set +CONFIG_LIBM=y + +# +# Architecture-Specific Support +# +CONFIG_ARCH_LOWPUTC=y +# CONFIG_ARCH_ROMGETC is not set +# CONFIG_LIBC_ARCH_MEMCPY is not set +# CONFIG_LIBC_ARCH_MEMCMP is not set +# CONFIG_LIBC_ARCH_MEMMOVE is not set +# CONFIG_LIBC_ARCH_MEMSET is not set +# CONFIG_LIBC_ARCH_STRCHR is not set +# CONFIG_LIBC_ARCH_STRCMP is not set +# CONFIG_LIBC_ARCH_STRCPY is not set +# CONFIG_LIBC_ARCH_STRNCPY is not set +# CONFIG_LIBC_ARCH_STRLEN is not set +# CONFIG_LIBC_ARCH_STRNLEN is not set +# CONFIG_LIBC_ARCH_ELF is not set +# CONFIG_ARMV7M_MEMCPY is not set +# CONFIG_ARMV7M_LIBM is not set +# CONFIG_MACHINE_OPTS_ARMV7M is not set +# CONFIG_LIBM_ARCH_FABSF is not set +# CONFIG_LIBM_ARCH_SQRTF is not set + +# +# stdlib Options +# +CONFIG_LIB_RAND_ORDER=1 +CONFIG_LIB_HOMEDIR="/" +CONFIG_LIBC_TMPDIR="/tmp" +CONFIG_LIBC_MAX_TMPFILE=32 + +# +# Program Execution Options +# +# CONFIG_LIBC_EXECFUNCS is not set +CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=1024 +CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048 +CONFIG_LIB_HOSTNAME="" + +# +# errno Decode Support +# +# CONFIG_LIBC_STRERROR is not set +# CONFIG_LIBC_PERROR_STDOUT is not set + +# +# memcpy/memset Options +# +# CONFIG_MEMSET_OPTSPEED is not set + +# +# pthread support +# +# CONFIG_LIBC_DLFCN is not set +# CONFIG_LIBC_MODLIB is not set +# CONFIG_LIBC_GROUP_FILE is not set +# CONFIG_LIBC_PASSWD_FILE is not set +# CONFIG_LIBC_WCHAR is not set +# CONFIG_LIBC_LOCALE is not set +# CONFIG_LIBC_LZF is not set + +# +# Time/Time Zone Support +# +# CONFIG_LIBC_LOCALTIME is not set +# CONFIG_TIME_EXTENDED is not set +CONFIG_ARCH_HAVE_TLS=y + +# +# Thread Local Storage (TLS) +# +# CONFIG_TLS is not set + +# +# Network-Related Options +# +# CONFIG_LIBC_IPv4_ADDRCONV is not set +# CONFIG_LIBC_IPv6_ADDRCONV is not set +# CONFIG_LIBC_NETDB is not set + +# +# NETDB Support +# +# CONFIG_LIBC_GAISTRERROR is not set +# CONFIG_NETDB_HOSTFILE is not set +# CONFIG_LIBC_IOCTL_VARIADIC is not set +CONFIG_LIB_SENDFILE_BUFSIZE=512 + +# +# Non-standard Library Support +# +# CONFIG_LIB_CRC64_FAST is not set +# CONFIG_LIB_KBDCODEC is not set +# CONFIG_LIB_SLCDCODEC is not set +# CONFIG_LIB_ENVPATH is not set +# CONFIG_LIB_HEX2BIN is not set +CONFIG_BUILTIN=y + +# +# Basic CXX Support +# +# CONFIG_C99_BOOL8 is not set +CONFIG_HAVE_CXX=y +# CONFIG_CXX_NEWLONG is not set + +# +# LLVM C++ Library (libcxx) +# +# CONFIG_LIBCXX is not set + +# +# uClibc++ Standard C++ Library +# +# CONFIG_UCLIBCXX is not set +# CONFIG_LIBDSP is not set + +# +# Open Asymmetric Multi Processing +# +# CONFIG_OPENAMP is not set + +# +# Application Configuration +# + +# +# Built-In Applications +# +CONFIG_BUILTIN_PROXY_STACKSIZE=1024 + +# +# CAN Utilities +# + +# +# Examples +# +# CONFIG_EXAMPLES_ABNTCODI is not set +# CONFIG_EXAMPLES_ADXL372_TEST is not set +# CONFIG_EXAMPLES_APA102 is not set +# CONFIG_EXAMPLES_AUDIO_SOUND is not set +# CONFIG_EXAMPLES_BATTERY is not set +# CONFIG_EXAMPLES_SIXAXIS is not set +# CONFIG_EXAMPLES_BUTTONS is not set +# CONFIG_EXAMPLES_CALIB_UDELAY is not set +# CONFIG_EXAMPLES_CCTYPE is not set +# CONFIG_EXAMPLES_CHARGER is not set +# CONFIG_EXAMPLES_CHAT is not set +# CONFIG_EXAMPLES_CHRONO is not set +# CONFIG_EXAMPLES_CONFIGDATA is not set +# CONFIG_EXAMPLES_DHCPD is not set +# CONFIG_EXAMPLES_DHTXX is not set +# CONFIG_EXAMPLES_DSPTEST is not set +# CONFIG_EXAMPLES_FTPC is not set +# CONFIG_EXAMPLES_FTPD is not set +# CONFIG_EXAMPLES_GPS is not set +# CONFIG_EXAMPLES_HELLO is not set +# CONFIG_EXAMPLES_HELLOXX is not set +# CONFIG_EXAMPLES_HIDKBD is not set +# CONFIG_EXAMPLES_IGMP is not set +# CONFIG_EXAMPLES_INA219 is not set +# CONFIG_EXAMPLES_INA226 is not set +# CONFIG_EXAMPLES_LSM330SPI_TEST is not set +# CONFIG_EXAMPLES_LVGLDEMO is not set +# CONFIG_EXAMPLES_MAX31855 is not set +# CONFIG_EXAMPLES_MEDIA is not set +# CONFIG_EXAMPLES_MLX90614 is not set +# CONFIG_EXAMPLES_MM is not set +# CONFIG_EXAMPLES_MODBUS is not set +# CONFIG_EXAMPLES_MODBUSMASTER is not set +# CONFIG_EXAMPLES_MOUNT is not set +# CONFIG_EXAMPLES_NULL is not set +# CONFIG_EXAMPLES_NXDEMO is not set +# CONFIG_EXAMPLES_OBD2 is not set +# CONFIG_EXAMPLES_PCA9635 is not set +# CONFIG_EXAMPLES_PDCURSES is not set +# CONFIG_EXAMPLES_POSIXSPAWN is not set +# CONFIG_EXAMPLES_POWERLED is not set +# CONFIG_EXAMPLES_POWERMONITOR is not set +# CONFIG_EXAMPLES_PPPD is not set +# CONFIG_EXAMPLES_PWM is not set +# CONFIG_EXAMPLES_RFID_READUID is not set +# CONFIG_EXAMPLES_RGBLED is not set +# CONFIG_EXAMPLES_SENDMAIL is not set +# CONFIG_EXAMPLES_SERIALBLASTER is not set +# CONFIG_EXAMPLES_SERIALRX is not set +# CONFIG_EXAMPLES_SERLOOP is not set +# CONFIG_EXAMPLES_SLCD is not set +# CONFIG_EXAMPLES_SMPS is not set +# CONFIG_EXAMPLES_STAT is not set +# CONFIG_EXAMPLES_TCPECHO is not set +# CONFIG_EXAMPLES_TIFF is not set +# CONFIG_EXAMPLES_TOUCHSCREEN is not set +# CONFIG_EXAMPLES_UID is not set +# CONFIG_EXAMPLES_USBSERIAL is not set +# CONFIG_EXAMPLES_USERFS is not set +# CONFIG_EXAMPLES_WATCHDOG is not set +# CONFIG_EXAMPLES_WEBSERVER is not set +# CONFIG_EXAMPLES_XBC_TEST is not set + +# +# File System Utilities +# +# CONFIG_FSUTILS_INIFILE is not set +# CONFIG_FSUTILS_INIH is not set +# CONFIG_FSUTILS_PASSWD is not set + +# +# GPS Utilities +# +# CONFIG_GPSUTILS_MINMEA_LIB is not set + +# +# Graphics Support +# +# CONFIG_GRAPHICS_FT80X is not set +# CONFIG_GRAPHICS_LVGL is not set + +# +# NxWidgets +# + +# +# NxWM +# +# CONFIG_GRAPHICS_PDCURSES is not set +# CONFIG_TIFF is not set + +# +# Industrial Applications +# +# CONFIG_INDUSTRY_ABNT_CODI_LIB is not set + +# +# Interpreters +# +# CONFIG_INTERPRETERS_BAS is not set +# CONFIG_INTERPRETERS_FICL is not set +# CONFIG_INTERPRETERS_MINIBASIC is not set + +# +# FreeModBus +# +# CONFIG_MODBUS is not set + +# +# Network Utilities +# +# CONFIG_NETUTILS_CHAT is not set +# CONFIG_NETUTILS_CJSON is not set +# CONFIG_NETUTILS_CODECS is not set +# CONFIG_NETUTILS_ESP8266 is not set +# CONFIG_NETUTILS_FTPC is not set +# CONFIG_NETUTILS_SMTP is not set + +# +# NSH Library +# +# CONFIG_NSH_LIBRARY is not set + +# +# Platform-specific Support +# +# CONFIG_PLATFORM_CONFIGDATA is not set +CONFIG_HAVE_CXXINITIALIZE=y + +# +# System Libraries and NSH Add-Ons +# +# CONFIG_SYSTEM_CLE is not set +# CONFIG_SYSTEM_CUTERM is not set +# CONFIG_SYSTEM_EMBEDLOG is not set +# CONFIG_SYSTEM_HEX2BIN is not set +# CONFIG_SYSTEM_HEXED is not set +# CONFIG_SYSTEM_NSH is not set +# CONFIG_SYSTEM_RAMTEST is not set +# CONFIG_READLINE_HAVE_EXTMATCH is not set +CONFIG_SYSTEM_READLINE=y +CONFIG_READLINE_ECHO=y +# CONFIG_READLINE_TABCOMPLETION is not set +# CONFIG_READLINE_CMD_HISTORY is not set +# CONFIG_SYSTEM_SETLOGMASK is not set +# CONFIG_SYSTEM_SPITOOL is not set +# CONFIG_SYSTEM_TEE is not set +# CONFIG_SYSTEM_TERMCURSES is not set +# CONFIG_SYSTEM_UBLOXMODEM is not set +# CONFIG_SYSTEM_VI is not set +# CONFIG_SYSTEM_ZMODEM is not set + +# +# Testing +# +# CONFIG_TESTING_CXXTEST is not set +# CONFIG_TESTING_FSTEST is not set +# CONFIG_TESTING_GETPRIME is not set +# CONFIG_TESTING_NXFFS is not set +# CONFIG_TESTING_OSTEST is not set +# CONFIG_TESTING_SCANFTEST is not set +# CONFIG_TESTING_SMART is not set +# CONFIG_TESTING_SMART_TEST is not set +# CONFIG_TESTING_UNITY is not set + +# +# Wireless Libraries and NSH Add-Ons +# + +# +# Bluetooth applications +# +# CONFIG_BTSAK is not set + +# +# IEEE 802.15.4 applications +# +# CONFIG_IEEE802154_I8SAK is not set +# CONFIG_IEEE802154_LIBMAC is not set +# CONFIG_IEEE802154_LIBUTILS is not set diff --git a/boards/arm/stm32l4/nucleo-l432kc/include/nucleo-l432kc.h b/boards/arm/stm32l4/nucleo-l432kc/include/nucleo-l432kc.h index a9819b8508e..964fffed220 100644 --- a/boards/arm/stm32l4/nucleo-l432kc/include/nucleo-l432kc.h +++ b/boards/arm/stm32l4/nucleo-l432kc/include/nucleo-l432kc.h @@ -68,7 +68,8 @@ * synced MSI. * * System Clock source : PLL (HSI) - * SYSCLK(Hz) : 80000000 Determined by PLL configuration + * SYSCLK(Hz) : 80000000 Determined by PLL + * configuration * HCLK(Hz) : 80000000 (STM32L4_RCC_CFGR_HPRE) * (Max 80 MHz) * AHB Prescaler : 1 (STM32L4_RCC_CFGR_HPRE) @@ -233,9 +234,9 @@ /* 'main' PLL config; we use this to generate our system clock via the R * output. We set it up as 16 MHz / 1 * 10 / 2 = 80 MHz * - * XXX NOTE: currently the main PLL is implicitly turned on and is implicitly - * the system clock; this should be configurable since not all applications may - * want things done this way. + * XXX NOTE: currently the main PLL is implicitly turned on and is + * implicitly the system clock; this should be configurable since not all + * applications may want things done this way. */ #define STM32L4_PLLCFG_PLLN RCC_PLLCFG_PLLN(10) @@ -495,6 +496,8 @@ #define STM32L4_APB1_TIM2_CLKIN (STM32L4_PCLK1_FREQUENCY) #define STM32L4_APB1_TIM6_CLKIN (STM32L4_PCLK1_FREQUENCY) #define STM32L4_APB1_TIM7_CLKIN (STM32L4_PCLK1_FREQUENCY) +#define STM32L4_APB1_LPTIM1_CLKIN (STM32L4_PCLK1_FREQUENCY) +#define STM32L4_APB1_LPTIM2_CLKIN (STM32L4_PCLK1_FREQUENCY) /* Configure the APB2 prescaler */ @@ -507,8 +510,8 @@ #endif -/* The timer clock frequencies are automatically defined by hardware. - * If the APB prescaler equals 1, the timer clock frequencies are set to the same +/* The timer clock frequencies are automatically defined by hardware. If the + * APB prescaler equals 1, the timer clock frequencies are set to the same * frequency as that of the APB domain. Otherwise they are set to twice. * Note: TIM1,15,16 are on APB2, others on APB1 */ diff --git a/boards/arm/stm32l4/nucleo-l432kc/src/Makefile b/boards/arm/stm32l4/nucleo-l432kc/src/Makefile index 9c0c71b4d14..899191db7a0 100644 --- a/boards/arm/stm32l4/nucleo-l432kc/src/Makefile +++ b/boards/arm/stm32l4/nucleo-l432kc/src/Makefile @@ -92,4 +92,8 @@ ifeq ($(CONFIG_LIB_BOARDCTL),y) CSRCS += stm32_appinit.c endif +ifeq ($(CONFIG_NUCLEOL432KC_SPWM),y) +CSRCS += stm32_spwm.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c b/boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c new file mode 100644 index 00000000000..9f10e7168c3 --- /dev/null +++ b/boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c @@ -0,0 +1,664 @@ +/**************************************************************************** + * boards/arm/stm32/nucleo-l432kc/src/stm32_spwm.c + * + * Copyright (C) 2018, 2019 Gregory Nutt. All rights reserved. + * Author: Mateusz Szafoni + * + * 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 +#include + +#include "up_internal.h" +#include "ram_vectors.h" + +#include "stm32l4_pwm.h" +#include "stm32l4_tim.h" + +#ifdef CONFIG_NUCLEOL432KC_SPWM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Assertions ***************************************************************/ + +#ifndef CONFIG_ARCH_CHIP_STM32L432KC +# warning "This only have been verified with CONFIG_ARCH_CHIP_STM32L432KC" +#endif + +#ifndef CONFIG_ARCH_HIPRI_INTERRUPT +# error "CONFIG_ARCH_HIPRI_INTERRUPT is required" +#endif + +#ifndef CONFIG_ARCH_RAMVECTORS +# error "CONFIG_ARCH_RAMVECTORS is required" +#endif + +#ifndef CONFIG_ARCH_IRQPRIO +# error "CONFIG_ARCH_IRQPRIO is required" +#endif + +#ifndef CONFIG_ARCH_FPU +# warning "Set CONFIG_ARCH_FPU for hardware FPU support" +#endif + +/* Check the configuration for TIM1 */ + +#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 + +/* Phase 1 is TIM1 CH1 */ + +# if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM > 0 +# ifndef CONFIG_STM32L4_TIM1_CH1OUT +# error +# endif +# ifndef CONFIG_STM32L4_TIM6 +# error +# endif +# endif + +/* Phase 2 is TIM1 CH2 */ + +# if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM > 1 +# ifndef CONFIG_STM32L4_TIM1_CH2OUT +# error +# endif +# endif + +/* Phase 3 is TIM1 CH3 */ + +# if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM > 2 +# ifndef CONFIG_STM32L4_TIM1_CH3OUT +# error +# endif +# endif + +/* Phase 4 is TIM1 CH4 */ + +# if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM > 3 +# ifndef CONFIG_STM32L4_TIM1_CH4OUT +# error +# endif +# endif + +# if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM != PWM_TIM1_NCHANNELS +# error +# endif + +#endif /* CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 */ + +/* Configuration ************************************************************/ + +#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 +# define PWM_TIMERS_IN_USE 1 +#endif + +#define SPWM_PHASE_SHIFT ((360.0f/CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM)) + +#define SAMPLES_NUM CONFIG_NUCLEOL432KC_SPWM_SAMPLES +#define PHASES_NUM CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* SPWM private data */ + +struct spwm_s +{ + FAR struct stm32l4_pwm_dev_s *pwm; +#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 + FAR struct stm32l4_tim_dev_s *tim; +#endif + float waveform[SAMPLES_NUM]; /* Waveform samples */ + float phase_step; /* Waveform phase step */ + float waveform_freq; /* Waveform frequency */ + uint16_t cmp[SAMPLES_NUM]; /* PWM TIM compare table */ + uint16_t per; /* PWM TIM period */ + uint16_t samples; /* Modulation waveform samples num */ + uint16_t phase_shift[PHASES_NUM]; /* Phase offset */ + volatile uint16_t sample_now[PHASES_NUM]; /* Current sample number for + * phase */ + uint8_t phases; /* Number of PWM phases */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct spwm_s g_spwm = +{ + .waveform_freq = ((float)CONFIG_NUCLEOL432KC_SPWM_FREQ), + .phases = PHASES_NUM, + .samples = SAMPLES_NUM, +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static float waveform_func(float x); +static int waveform_init(FAR struct spwm_s *spwm, float (*f)(float)); +static int spwm_start(FAR struct spwm_s *spwm); +static int spwm_start(FAR struct spwm_s *spwm); +static int spwm_stop(FAR struct spwm_s *spwm); +#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 +static int spwm_tim1_setup(FAR struct spwm_s *spwm); +static int spwm_tim6_setup(FAR struct spwm_s *spwm); +static int spwm_tim1_start(FAR struct spwm_s *spwm); +static int spwm_tim6_start(FAR struct spwm_s *spwm); +static int spwm_tim1_stop(FAR struct spwm_s *spwm); +static int spwm_tim6_stop(FAR struct spwm_s *spwm); +#endif /* CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 */ +static int spwm_setup(FAR struct spwm_s *spwm); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: waveform_func + * + * Description: + * Modulation function. This function must return values from <0.0, 1.0>! + * + ****************************************************************************/ + +static float waveform_func(float x) +{ + DEBUGASSERT(x >= 0 && x <= 2 * M_PI); + + /* Sine modulation */ + + return (sinf(x) + 1.0f) / 2.0f; +} + +/**************************************************************************** + * Name: waveform_init + * + * Description: + * Initialize modulation waveform + * + ****************************************************************************/ + +static int waveform_init(FAR struct spwm_s *spwm, float (*f)(float)) +{ + uint16_t i = 0; + int ret = 0; + + printf("Initialize waveform\n"); + + /* Get phase step to achieve one sine waveform period */ + + spwm->phase_step = (float)(2 * M_PI / spwm->samples); + + /* Initialize sine and PWM compare tables */ + + for (i = 0; i < spwm->samples; i += 1) + { + /* We need sine in range from 0 to 1.0 */ + + spwm->waveform[i] = f(spwm->phase_step * i); + + DEBUGASSERT(spwm->waveform[i] >= 0.0 && spwm->waveform[i] <= 2 * M_PI); + + spwm->cmp[i] = (uint16_t)(spwm->waveform[i] * spwm->per); + } + + /* Configure phase shift TODO: this should be configurable */ + + for (i = 0; i < spwm->phases; i += 1) + { + spwm->phase_shift[i] = + (spwm->samples / CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM) * i; + } + + /* Initialize offstes */ + + for (i = 0; i < spwm->phases; i += 1) + { + spwm->sample_now[i] = spwm->phase_shift[i]; + } + + printf("\tsamples = %d\n", spwm->samples); + printf("\tper = %d\n", spwm->per); + printf("\tphase = %d\n", spwm->phases); + for (i = 0; i < spwm->phases; i += 1) + { + printf("\tsnow%d = %d\n", i, spwm->sample_now[i]); + } + + return ret; +} + +/**************************************************************************** + * Name: spwm_start + * + * Description: + * Start SPWM + * + ****************************************************************************/ + +static int spwm_start(FAR struct spwm_s *spwm) +{ + /* Start TIM1 */ + + spwm_tim1_start(spwm); + + /* Start TIM6 */ + + spwm_tim6_start(spwm); + + return OK; +} + +/**************************************************************************** + * Name: spwm_stop + * + * Description: + * Stop SPWM + * + ****************************************************************************/ + +static int spwm_stop(FAR struct spwm_s *spwm) +{ + /* Stop TIM1 */ + + spwm_tim1_stop(spwm); + + /* Stop TIM6 */ + + spwm_tim6_stop(spwm); + + return OK; +} + +#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 + +/**************************************************************************** + * Name: tim6_handler + ****************************************************************************/ + +static void tim6_handler(void) +{ + FAR struct spwm_s *spwm = &g_spwm; + FAR struct stm32l4_pwm_dev_s *pwm = spwm->pwm; + FAR struct stm32l4_tim_dev_s *tim = spwm->tim; + uint8_t i = 0; + + for (i = 0; i < spwm->phases; i += 1) + { + /* Set new CMP for timers */ + + PWM_CCR_UPDATE(pwm, i + 1, spwm->cmp[spwm->sample_now[i]]); + + /* Increase sample pointer */ + + spwm->sample_now[i] += 1; + + if (spwm->sample_now[i] > spwm->samples) + { + spwm->sample_now[i] = 0; + } + } + + /* TODO: Software update */ + + STM32L4_TIM_ACKINT(tim, ATIM_SR_UIF); +} + +/**************************************************************************** + * Name: spwm_tim6_setup + ****************************************************************************/ + +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 */ + + tim = stm32l4_tim_init(6); + if (tim == NULL) + { + printf("ERROR: Failed to get TIM6 interface\n"); + ret = -1; + goto errout; + } + + spwm->tim = tim; + + /* Frequency with which we will change samples. + * + * tim6_freq = samples_num * waveform_freq. + */ + + freq = spwm->samples * spwm->waveform_freq; + per = BOARD_TIM6_FREQUENCY / freq; + if (per > 0xffff) + { + printf("ERROR: can not achieve TIM6 frequency\n"); + ret = -1; + goto errout; + } + + /* TODO: TIM_SETFREQ */ + + STM32L4_TIM_SETCLOCK(tim, BOARD_TIM6_FREQUENCY); + STM32L4_TIM_SETPERIOD(tim, per); + + /* Attach TIM6 ram vector */ + + ret = up_ramvec_attach(STM32L4_IRQ_TIM6, tim6_handler); + if (ret < 0) + { + printf("ERROR: up_ramvec_attach failed: %d\n", ret); + ret = -1; + goto errout; + } + + /* Set the priority of the TIM6 interrupt vector */ + + ret = up_prioritize_irq(STM32L4_IRQ_TIM6, NVIC_SYSH_HIGH_PRIORITY); + if (ret < 0) + { + printf("ERROR: up_prioritize_irq failed: %d\n", ret); + ret = -1; + goto errout; + } + + spwm_tim6_stop(spwm); + +errout: + return ret; +} + +/**************************************************************************** + * Name: spwm_tim6_start + ****************************************************************************/ + +static int spwm_tim6_start(FAR struct spwm_s *spwm) +{ + FAR struct stm32l4_tim_dev_s *tim = spwm->tim; + + /* Enable the timer interrupt at the NVIC and at TIM6 */ + + up_enable_irq(STM32L4_IRQ_TIM6); + STM32L4_TIM_ENABLEINT(tim, BTIM_DIER_UIE); + + return OK; +} + +/**************************************************************************** + * Name: spwm_tim6_stop + ****************************************************************************/ + +static int spwm_tim6_stop(FAR struct spwm_s *spwm) +{ + FAR struct stm32l4_tim_dev_s *tim = spwm->tim; + + /* Disable the timer interrupt at the NVIC and at TIM6 */ + + up_disable_irq(STM32L4_IRQ_TIM6); + STM32L4_TIM_DISABLEINT(tim, BTIM_DIER_UIE); + + return OK; +} + +/**************************************************************************** + * Name: spwm_tim1_setup + ****************************************************************************/ + +static int spwm_tim1_setup(FAR struct spwm_s *spwm) +{ + FAR struct stm32l4_pwm_dev_s *pwm = NULL; + int ret = OK; + + /* Get TIM1 PWM interface */ + + pwm = (FAR struct stm32l4_pwm_dev_s *)stm32l4_pwminitialize(1); + if (pwm == NULL) + { + printf("ERROR: Failed to get TIM1 PWM interface\n"); + ret = -1; + goto errout; + } + + spwm->pwm = pwm; + + /* Initial PWM1 setup */ + + ret = PWM_SETUP(pwm); + if (ret < 0) + { + printf("ERROR: Failed to get setup TIM1 PWM\n"); + ret = -1; + goto errout; + } + + /* Configure TIM1 PWM frequency */ + + ret = PWM_FREQ_UPDATE(pwm, CONFIG_NUCLEOL432KC_SPWM_PWM_FREQ); + if (ret < 0) + { + printf("ERROR: Failed to set TIM1 PWM frequency\n"); + ret = -1; + goto errout; + } + + /* Get TIM1 period (ARR) */ + + spwm->per = PWM_ARR_GET(pwm); + + spwm_tim1_stop(spwm); + +errout: + return ret; +} + +/**************************************************************************** + * Name: spwm_tim1_start + ****************************************************************************/ + +static int spwm_tim1_start(FAR struct spwm_s *spwm) +{ + FAR struct stm32l4_pwm_dev_s *pwm = spwm->pwm; + uint16_t outputs = 0; + int i = 0; + + /* Get outputs */ + + for (i = 0; i < spwm->phases; i += 1) + { + outputs |= (1 << (i * 2)); + } + + /* Enable PWM outputs */ + + PWM_OUTPUTS_ENABLE(pwm, outputs, true); + + /* Enable TIM1 */ + + PWM_TIM_ENABLE(pwm, true); + + return OK; +} + +/**************************************************************************** + * Name: spwm_tim1_stop + ****************************************************************************/ + +static int spwm_tim1_stop(FAR struct spwm_s *spwm) +{ + FAR struct stm32l4_pwm_dev_s *pwm = spwm->pwm; + uint16_t outputs = 0; + int i = 0; + + /* Get outputs */ + + for (i = 0; i < spwm->phases; i += 1) + { + outputs |= (1 << (i * 2)); + } + + /* Disable PWM outputs */ + + PWM_OUTPUTS_ENABLE(pwm, outputs, false); + + /* Disable TIM1 */ + + PWM_TIM_ENABLE(pwm, false); + + return OK; +} + +#endif /* CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 */ + +/**************************************************************************** + * Name: spwm_setup + ****************************************************************************/ + +static int spwm_setup(FAR struct spwm_s *spwm) +{ + int ret = OK; + + /* TIM1 setup - PWM */ + + printf("Setup TIM1 and TIM6\n"); + ret = spwm_tim1_setup(spwm); + if (ret < 0) + { + goto errout; + } + + /* TIM6 setup - IRQ */ + + ret = spwm_tim6_setup(spwm); + if (ret < 0) + { + goto errout; + } + +errout: + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spwm_main + * + * Description: + * Entrypoint for SPWM example. + * + ****************************************************************************/ + +int spwm_main(int argc, char *argv[]) +{ + FAR struct spwm_s *spwm = NULL; + int ret = OK; + int i = 0; + + spwm = &g_spwm; + + printf("\nspwm_main: Started\n"); + + /* Setup SPWM example */ + + ret = spwm_setup(spwm); + if (ret < 0) + { + printf("ERROR: failed to setup SPWM %d!\n", ret); + goto errout; + } + + /* Initialize modulation waveform */ + + ret = waveform_init(spwm, waveform_func); + if (ret < 0) + { + printf("ERROR: failed initialize modulation wavefrom %d!\n", ret); + goto errout; + } + + /* Start SPWM */ + + ret = spwm_start(spwm); + if (ret < 0) + { + printf("ERROR: failed start SPWM %d!\n", ret); + goto errout; + } + + /* Main loop */ + + while (1) + { + /* Print counter */ + + printf("%d\n", i); + + /* Increase counter */ + + i += 1; + + /* Sleep */ + + nxsig_sleep(1); + } + +errout: + spwm_stop(spwm); + + return 0; +} + +#endif /* CONFIG_NUCLEOL432KC_SPWM */