arch/arm/src/stm32l4 and boards/arm/stm32l4/nucleo-l476rg: Add support for LPTIM timers on the STM32L4 as PWM outputs.
This commit is contained in:
parent
637004e70c
commit
fd625eaa89
@ -1810,6 +1810,74 @@ config STM32L4_ONESHOT_MAXTIMERS
|
||||
of the timers and places an upper limit on the number of oneshot
|
||||
timers that you can use.
|
||||
|
||||
config STM32L4_LPTIM1_PWM
|
||||
bool "LPTIM1 PWM"
|
||||
default n
|
||||
depends on STM32L4_LPTIM1
|
||||
select PWM
|
||||
---help---
|
||||
Reserve low-power timer 1 for use by PWM
|
||||
|
||||
Timer devices may be used for different purposes. One special purpose is
|
||||
to generate modulated outputs for such things as motor control. If STM32L4_LPTIM1
|
||||
is defined then THIS following may also be defined to indicate that
|
||||
the timer is intended to be used for pulsed output modulation.
|
||||
|
||||
if STM32L4_LPTIM1_PWM
|
||||
|
||||
choice
|
||||
prompt "LPTIM1 clock source"
|
||||
default STM32L4_LPTIM1_CLK_APB1
|
||||
|
||||
config STM32L4_LPTIM1_CLK_APB1
|
||||
bool "Clock LPTIM1 from APB1"
|
||||
|
||||
config STM32L4_LPTIM1_CLK_LSE
|
||||
bool "Clock LPTIM1 from LSE"
|
||||
|
||||
config STM32L4_LPTIM1_CLK_LSI
|
||||
bool "Clock LPTIM1 from LSI"
|
||||
|
||||
config STM32L4_LPTIM1_CLK_HSI
|
||||
bool "Clock LPTIM1 from HSI"
|
||||
endchoice
|
||||
|
||||
endif # STM32L4_LPTIM1_PWM
|
||||
|
||||
config STM32L4_LPTIM2_PWM
|
||||
bool "LPTIM2 PWM"
|
||||
default n
|
||||
depends on STM32L4_LPTIM2
|
||||
select PWM
|
||||
---help---
|
||||
Reserve low-power timer 2 for use by PWM
|
||||
|
||||
Timer devices may be used for different purposes. One special purpose is
|
||||
to generate modulated outputs for such things as motor control. If STM32L4_LPTIM2
|
||||
is defined then THIS following may also be defined to indicate that
|
||||
the timer is intended to be used for pulsed output modulation.
|
||||
|
||||
if STM32L4_LPTIM2_PWM
|
||||
|
||||
choice
|
||||
prompt "LPTIM2 clock source"
|
||||
default STM32L4_LPTIM2_CLK_APB1
|
||||
|
||||
config STM32L4_LPTIM2_CLK_APB1
|
||||
bool "Clock LPTIM2 from APB1"
|
||||
|
||||
config STM32L4_LPTIM2_CLK_LSE
|
||||
bool "Clock LPTIM2 from LSE"
|
||||
|
||||
config STM32L4_LPTIM2_CLK_LSI
|
||||
bool "Clock LPTIM2 from LSI"
|
||||
|
||||
config STM32L4_LPTIM2_CLK_HSI
|
||||
bool "Clock LPTIM2 from HSI"
|
||||
endchoice
|
||||
|
||||
endif # STM32L4_LPTIM2_PWM
|
||||
|
||||
config STM32L4_TIM1_PWM
|
||||
bool "TIM1 PWM"
|
||||
default n
|
||||
|
@ -114,4 +114,12 @@
|
||||
#define LPTIM_CR_SNGSTRT (1 << 1) /* Bit 1: Single Mode */
|
||||
#define LPTIM_CR_CNTSTRT (1 << 2) /* Bit 2: Continuous Mode */
|
||||
|
||||
#define LPTIM_ISR_CMPM (1 << 0) /* Bit 0: Compare match */
|
||||
#define LPTIM_ISR_ARRM (1 << 1) /* Bit 1: Autoreload match */
|
||||
#define LPTIM_ISR_EXTTRIG (1 << 2) /* Bit 2: External trigger edge event */
|
||||
#define LPTIM_ISR_CMPOK (1 << 3) /* Bit 3: Compare register update OK */
|
||||
#define LPTIM_ISR_ARROK (1 << 4) /* Bit 4: Autoreload register update OK */
|
||||
#define LPTIM_ISR_UP (1 << 5) /* Bit 5: Counter direction change down to up */
|
||||
#define LPTIM_ISR_DOWN (1 << 6) /* Bit 6: Counter direction change up to down */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_STM32L4_HARDWARE_STM32L4_LPTIM_H */
|
||||
|
@ -116,18 +116,6 @@
|
||||
#define STM32L4_ATIM_OR2_OFFSET 0x0050 /* Timer option register 2 */
|
||||
#define STM32L4_ATIM_OR3_OFFSET 0x0050 /* Timer option register 3 */
|
||||
|
||||
/* Low-Power Timers - LPTIM1 and LPTIM2 */
|
||||
|
||||
#define STM32L4_LPTIM_ISR_OFFSET 0x0000 /* Interrupt and Status register */
|
||||
#define STM32L4_LPTIM_ICR_OFFSET 0x0004 /* Interrupt clear register */
|
||||
#define STM32L4_LPTIM_IER_OFFSET 0x0008 /* Interrupt enable register */
|
||||
#define STM32L4_LPTIM_CFGR_OFFSET 0x000c /* Configuration register */
|
||||
#define STM32L4_LPTIM_CR_OFFSET 0x0010 /* Control register */
|
||||
#define STM32L4_LPTIM_CMP_OFFSET 0x0014 /* Compare register */
|
||||
#define STM32L4_LPTIM_ARR_OFFSET 0x0018 /* Auto-reloud register (16-bit) */
|
||||
#define STM32L4_LPTIM_CNT_OFFSET 0x001c /* Counter (16-bit) */
|
||||
#define STM32L4_LPTIM_OR_OFFSET 0x001c /* Options Register */
|
||||
|
||||
/* Register Addresses ***************************************************************/
|
||||
|
||||
/* Advanced Timers - TIM1 and TIM8 */
|
||||
@ -715,40 +703,40 @@
|
||||
#define ATIM_BDTR_MOE (1 << 15) /* Bit 15: Main Output enable */
|
||||
#define ATIM_BDTR_BKF_SHIFT (16) /* Bits 16-19: Break filter */
|
||||
#define ATIM_BDTR_BKF_MASK (15 << ATIM_BDTR_BKF_SHIFT)
|
||||
# define ATIM_BDTR_BKF_NOFILT (0 << ATIM_BDTR_BKF_SHIFT) /* 0000: No filter, BRK acts asynchronously */
|
||||
# define ATIM_BDTR_BKF_FCKINT2 (1 << ATIM_BDTR_BKF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */
|
||||
# define ATIM_BDTR_BKF_FCKINT4 (2 << ATIM_BDTR_BKF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */
|
||||
# define ATIM_BDTR_BKF_FCKINT8 (3 << ATIM_BDTR_BKF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd26 (4 << ATIM_BDTR_BKF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd28 (5 << ATIM_BDTR_BKF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd36 (6 << ATIM_BDTR_BKF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd38 (7 << ATIM_BDTR_BKF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd86 (8 << ATIM_BDTR_BKF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd88 (9 << ATIM_BDTR_BKF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd165 (10 << ATIM_BDTR_BKF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */
|
||||
# define ATIM_BDTR_BKF_FDTSd166 (11 << ATIM_BDTR_BKF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd168 (12 << ATIM_BDTR_BKF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd325 (13 << ATIM_BDTR_BKF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */
|
||||
# define ATIM_BDTR_BKF_FDTSd326 (14 << ATIM_BDTR_BKF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd328 (15 << ATIM_BDTR_BKF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */
|
||||
# define ATIM_BDTR_BKF_NOFILT (0 << ATIM_BDTR_BKF_SHIFT) /* 0000: No filter, BRK acts asynchronously */
|
||||
# define ATIM_BDTR_BKF_FCKINT2 (1 << ATIM_BDTR_BKF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */
|
||||
# define ATIM_BDTR_BKF_FCKINT4 (2 << ATIM_BDTR_BKF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */
|
||||
# define ATIM_BDTR_BKF_FCKINT8 (3 << ATIM_BDTR_BKF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd26 (4 << ATIM_BDTR_BKF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd28 (5 << ATIM_BDTR_BKF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd36 (6 << ATIM_BDTR_BKF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd38 (7 << ATIM_BDTR_BKF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd86 (8 << ATIM_BDTR_BKF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd88 (9 << ATIM_BDTR_BKF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd165 (10 << ATIM_BDTR_BKF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */
|
||||
# define ATIM_BDTR_BKF_FDTSd166 (11 << ATIM_BDTR_BKF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd168 (12 << ATIM_BDTR_BKF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */
|
||||
# define ATIM_BDTR_BKF_FDTSd325 (13 << ATIM_BDTR_BKF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */
|
||||
# define ATIM_BDTR_BKF_FDTSd326 (14 << ATIM_BDTR_BKF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */
|
||||
# define ATIM_BDTR_BKF_FDTSd328 (15 << ATIM_BDTR_BKF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */
|
||||
#define ATIM_BDTR_BK2F_SHIFT (20) /* Bits 20-23: Break 2 filter */
|
||||
#define ATIM_BDTR_BK2F_MASK (15 << ATIM_BDTR_BK2F_SHIFT)
|
||||
# define ATIM_BDTR_BK2F_NOFILT (0 << ATIM_BDTR_BK2F_SHIFT) /* 0000: No filter, BRK 2 acts asynchronously */
|
||||
# define ATIM_BDTR_BK2F_FCKINT2 (1 << ATIM_BDTR_BK2F_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */
|
||||
# define ATIM_BDTR_BK2F_FCKINT4 (2 << ATIM_BDTR_BK2F_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */
|
||||
# define ATIM_BDTR_BK2F_FCKINT8 (3 << ATIM_BDTR_BK2F_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd26 (4 << ATIM_BDTR_BK2F_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd28 (5 << ATIM_BDTR_BK2F_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd36 (6 << ATIM_BDTR_BK2F_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd38 (7 << ATIM_BDTR_BK2F_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd86 (8 << ATIM_BDTR_BK2F_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd88 (9 << ATIM_BDTR_BK2F_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd165 (10 << ATIM_BDTR_BK2F_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd166 (11 << ATIM_BDTR_BK2F_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd168 (12 << ATIM_BDTR_BK2F_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd325 (13 << ATIM_BDTR_BK2F_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd326 (14 << ATIM_BDTR_BK2F_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd328 (15 << ATIM_BDTR_BK2F_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */
|
||||
# define ATIM_BDTR_BK2F_NOFILT (0 << ATIM_BDTR_BK2F_SHIFT) /* 0000: No filter, BRK 2 acts asynchronously */
|
||||
# define ATIM_BDTR_BK2F_FCKINT2 (1 << ATIM_BDTR_BK2F_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */
|
||||
# define ATIM_BDTR_BK2F_FCKINT4 (2 << ATIM_BDTR_BK2F_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */
|
||||
# define ATIM_BDTR_BK2F_FCKINT8 (3 << ATIM_BDTR_BK2F_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd26 (4 << ATIM_BDTR_BK2F_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd28 (5 << ATIM_BDTR_BK2F_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd36 (6 << ATIM_BDTR_BK2F_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd38 (7 << ATIM_BDTR_BK2F_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd86 (8 << ATIM_BDTR_BK2F_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd88 (9 << ATIM_BDTR_BK2F_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd165 (10 << ATIM_BDTR_BK2F_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd166 (11 << ATIM_BDTR_BK2F_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd168 (12 << ATIM_BDTR_BK2F_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd325 (13 << ATIM_BDTR_BK2F_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd326 (14 << ATIM_BDTR_BK2F_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */
|
||||
# define ATIM_BDTR_BK2F_FDTSd328 (15 << ATIM_BDTR_BK2F_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */
|
||||
#define ATIM_BDTR_BK2E (1 << 24) /* Bit 24: Break 2 enable */
|
||||
#define ATIM_BDTR_BK2P (1 << 1525 /* Bit 25:Break 2 polarity */
|
||||
|
||||
|
@ -62,16 +62,19 @@
|
||||
* intended for use with the PWM upper half driver.
|
||||
*/
|
||||
|
||||
#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) || \
|
||||
defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \
|
||||
defined(CONFIG_STM32L4_TIM17_PWM)
|
||||
#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) || \
|
||||
defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \
|
||||
defined(CONFIG_STM32L4_TIM17_PWM) || defined(CONFIG_STM32L4_LPTIM1_PWM) || \
|
||||
defined(CONFIG_STM32L4_LPTIM2_PWM)
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* PWM/Timer Definitions ****************************************************/
|
||||
|
||||
/* The following definitions are used to identify the various time types */
|
||||
|
||||
#define TIMTYPE_BASIC 0 /* Basic timers: TIM6,7 */
|
||||
@ -79,6 +82,7 @@
|
||||
#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_TIM1 TIMTYPE_ADVANCED
|
||||
#define TIMTYPE_TIM2 TIMTYPE_GENERAL32
|
||||
@ -91,6 +95,8 @@
|
||||
#define TIMTYPE_TIM15 TIMTYPE_COUNTUP16
|
||||
#define TIMTYPE_TIM16 TIMTYPE_COUNTUP16
|
||||
#define TIMTYPE_TIM17 TIMTYPE_COUNTUP16
|
||||
#define TIMTYPE_LPTIM1 TIMTYPE_LOWPOWER
|
||||
#define TIMTYPE_LPTIM2 TIMTYPE_LOWPOWER
|
||||
|
||||
/* Debug ********************************************************************/
|
||||
|
||||
@ -161,13 +167,17 @@ struct stm32l4_pwmtimer_s
|
||||
/****************************************************************************
|
||||
* Static Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* 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 stm32l4pwm_getreg(struct stm32l4_pwmtimer_s *priv,
|
||||
int offset);
|
||||
static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset,
|
||||
uint16_t value);
|
||||
|
||||
#ifdef CONFIG_DEBUG_PWM_INFO
|
||||
static void stm32l4pwm_dumpregs(struct stm32l4_pwmtimer_s *priv, FAR const char *msg);
|
||||
static void stm32l4pwm_dumpregs(struct stm32l4_pwmtimer_s *priv,
|
||||
const char *msg);
|
||||
#else
|
||||
# define stm32l4pwm_dumpregs(priv,msg)
|
||||
#endif
|
||||
@ -177,7 +187,11 @@ static void stm32l4pwm_dumpregs(struct stm32l4_pwmtimer_s *priv, FAR const char
|
||||
static int stm32l4pwm_timer(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_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);
|
||||
@ -209,7 +223,10 @@ static int stm32l4pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
/* This is the list of lower half PWM driver methods used by the upper half driver */
|
||||
|
||||
/* This is the list of lower half PWM driver methods used by the upper half
|
||||
* driver.
|
||||
*/
|
||||
|
||||
static const struct pwm_ops_s g_pwmops =
|
||||
{
|
||||
@ -606,6 +623,66 @@ static struct stm32l4_pwmtimer_s g_pwm17dev =
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_LPTIM1_PWM
|
||||
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,
|
||||
},
|
||||
#endif
|
||||
},
|
||||
.timtype = TIMTYPE_LPTIM1,
|
||||
.mode = STM32L4_TIMMODE_COUNTUP,
|
||||
.base = STM32L4_LPTIM1_BASE,
|
||||
#if defined(CONFIG_STM32L4_LPTIM1_CLK_APB1)
|
||||
.pclk = STM32L4_PCLK1_FREQUENCY,
|
||||
#elif defined(CONFIG_STM32L4_LPTIM1_CLK_LSE)
|
||||
.pclk = STM32L4_LSE_FREQUENCY,
|
||||
#elif defined(CONFIG_STM32L4_LPTIM1_CLK_LSI)
|
||||
.pclk = STM32L4_LSI_FREQUENCY,
|
||||
#elif defined(CONFIG_STM32L4_LPTIM1_CLK_HSI)
|
||||
.pclk = STM32L4_HSI_FREQUENCY,
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_LPTIM2_PWM
|
||||
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,
|
||||
},
|
||||
#endif
|
||||
},
|
||||
.timtype = TIMTYPE_LPTIM2,
|
||||
.mode = STM32L4_TIMMODE_COUNTUP,
|
||||
.base = STM32L4_LPTIM2_BASE,
|
||||
#if defined(CONFIG_STM32L4_LPTIM2_CLK_APB1)
|
||||
.pclk = STM32L4_PCLK1_FREQUENCY,
|
||||
#elif defined(CONFIG_STM32L4_LPTIM2_CLK_LSE)
|
||||
.pclk = STM32L4_LSE_FREQUENCY,
|
||||
#elif defined(CONFIG_STM32L4_LPTIM2_CLK_LSI)
|
||||
.pclk = STM32L4_LSI_FREQUENCY,
|
||||
#elif defined(CONFIG_STM32L4_LPTIM2_CLK_HSI)
|
||||
.pclk = STM32L4_HSI_FREQUENCY,
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -688,42 +765,57 @@ static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset,
|
||||
static void stm32l4pwm_dumpregs(struct stm32l4_pwmtimer_s *priv,
|
||||
FAR const char *msg)
|
||||
{
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM)
|
||||
if (priv->timtype == TIMTYPE_ADVANCED)
|
||||
if (priv->timtype == TIMTYPE_LOWPOWER)
|
||||
{
|
||||
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));
|
||||
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));
|
||||
pwminfo(" ISR: %04x CNT: %04x\n",
|
||||
stm32l4pwm_getreg(priv, STM32L4_LPTIM_ISR_OFFSET),
|
||||
stm32l4pwm_getreg(priv, STM32L4_LPTIM_CNT_OFFSET));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pwminfo(" DCR: %04x DMAR: %04x\n",
|
||||
stm32l4pwm_getreg(priv, STM32L4_GTIM_DCR_OFFSET),
|
||||
stm32l4pwm_getreg(priv, STM32L4_GTIM_DMAR_OFFSET));
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
#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));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pwminfo(" DCR: %04x DMAR: %04x\n",
|
||||
stm32l4pwm_getreg(priv, STM32L4_GTIM_DCR_OFFSET),
|
||||
stm32l4pwm_getreg(priv, STM32L4_GTIM_DMAR_OFFSET));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1266,8 +1358,8 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
|
||||
* 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 &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE |
|
||||
ATIM_CCER_CC2NP | ATIM_CCER_CC3NE | ATIM_CCER_CC3NP);
|
||||
|
||||
ccer |= ccnenable;
|
||||
|
||||
@ -1290,7 +1382,6 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
|
||||
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.
|
||||
*/
|
||||
@ -1353,6 +1444,145 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32l4pwm_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
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32l4pwm_lptimer(FAR struct stm32l4_pwmtimer_s *priv,
|
||||
FAR const struct pwm_info_s *info)
|
||||
{
|
||||
/* 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",
|
||||
priv->timid, info->frequency, info->duty);
|
||||
|
||||
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.
|
||||
* For certain desired frequencies it is possible that the clock
|
||||
* is too high and other one needs to be selected.
|
||||
*/
|
||||
|
||||
for (prescaler = 0; prescaler < 8; prescaler++)
|
||||
{
|
||||
timclk = priv->pclk / (1 << prescaler);
|
||||
reload = timclk / info->frequency;
|
||||
|
||||
if (reload <= 65535)
|
||||
{
|
||||
/* The reload counter is feasible, go with it */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reload < 2)
|
||||
{
|
||||
reload = 1;
|
||||
}
|
||||
else if (reload > 65535)
|
||||
{
|
||||
reload = 65535;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Disable the timer to set the prescaler */
|
||||
|
||||
cr = stm32l4pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET);
|
||||
|
||||
cr &= ~LPTIM_CR_ENABLE;
|
||||
stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr);
|
||||
|
||||
/* 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 &= ~LPTIM_CFGR_PRESC_MASK;
|
||||
cfgr |= (prescaler << LPTIM_CFGR_PRESC_SHIFT) | LPTIM_CFGR_WAVPOL;
|
||||
|
||||
putreg32(cfgr, priv->base + STM32L4_LPTIM_CFGR_OFFSET);
|
||||
|
||||
/* Enable again, ARR and CMP need to be written while enabled */
|
||||
|
||||
cr |= LPTIM_CR_ENABLE;
|
||||
stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr);
|
||||
|
||||
/* Compute reload value */
|
||||
|
||||
ub16_t duty = info->duty;
|
||||
|
||||
/* Duty cycle:
|
||||
*
|
||||
* duty cycle = ccr / reload (fractional value)
|
||||
*/
|
||||
|
||||
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));
|
||||
|
||||
/* Start counter */
|
||||
|
||||
cr = stm32l4pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET);
|
||||
cr |= LPTIM_CR_CNTSTRT;
|
||||
stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr);
|
||||
|
||||
stm32l4pwm_dumpregs(priv, "After starting");
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PWM_PULSECOUNT
|
||||
/****************************************************************************
|
||||
* Name: stm32l4pwm_update_duty
|
||||
@ -1384,7 +1614,8 @@ static int stm32l4pwm_update_duty(FAR struct stm32l4_pwmtimer_s *priv,
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
pwminfo("TIM%u channel: %u duty: %08x\n",
|
||||
pwminfo("%s%u channel: %u duty: %08x\n",
|
||||
priv->timtype == TIMTYPE_LOWPOWER ? "LPTIM" : "TIM",
|
||||
priv->timid, channel, duty);
|
||||
|
||||
#ifndef CONFIG_PWM_MULTICHAN
|
||||
@ -1394,7 +1625,14 @@ static int stm32l4pwm_update_duty(FAR struct stm32l4_pwmtimer_s *priv,
|
||||
|
||||
/* Get the reload values */
|
||||
|
||||
reload = stm32l4pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET);
|
||||
if (priv->timtype == TIMTYPE_LOWPOWER)
|
||||
{
|
||||
reload = stm32l4pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
reload = stm32l4pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET);
|
||||
}
|
||||
|
||||
/* Duty cycle:
|
||||
*
|
||||
@ -1405,27 +1643,36 @@ static int stm32l4pwm_update_duty(FAR struct stm32l4_pwmtimer_s *priv,
|
||||
|
||||
pwminfo("ccr: %u\n", ccr);
|
||||
|
||||
switch (channel)
|
||||
if (priv->timtype == TIMTYPE_LOWPOWER)
|
||||
{
|
||||
case 1: /* Register offset for Channel 1 */
|
||||
ccr_offset = STM32L4_GTIM_CCR1_OFFSET;
|
||||
break;
|
||||
/* Low-power timers only have a compare register */
|
||||
|
||||
case 2: /* Register offset for Channel 2 */
|
||||
ccr_offset = STM32L4_GTIM_CCR2_OFFSET;
|
||||
break;
|
||||
ccr_offset = STM32L4_LPTIM_CMP_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 1: /* Register offset for Channel 1 */
|
||||
ccr_offset = STM32L4_GTIM_CCR1_OFFSET;
|
||||
break;
|
||||
|
||||
case 3: /* Register offset for Channel 3 */
|
||||
ccr_offset = STM32L4_GTIM_CCR3_OFFSET;
|
||||
break;
|
||||
case 2: /* Register offset for Channel 2 */
|
||||
ccr_offset = STM32L4_GTIM_CCR2_OFFSET;
|
||||
break;
|
||||
|
||||
case 4: /* Register offset for Channel 4 */
|
||||
ccr_offset = STM32L4_GTIM_CCR4_OFFSET;
|
||||
break;
|
||||
case 3: /* Register offset for Channel 3 */
|
||||
ccr_offset = STM32L4_GTIM_CCR3_OFFSET;
|
||||
break;
|
||||
|
||||
default:
|
||||
pwmerr("ERROR: No such channel: %u\n", channel);
|
||||
return -EINVAL;
|
||||
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 */
|
||||
@ -1613,75 +1860,143 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on)
|
||||
|
||||
/* Determine which timer to configure */
|
||||
|
||||
switch (priv->timid)
|
||||
if (priv->timtype != TIMTYPE_LOWPOWER)
|
||||
{
|
||||
switch (priv->timid)
|
||||
{
|
||||
#ifdef CONFIG_STM32L4_TIM1_PWM
|
||||
case 1:
|
||||
regaddr = STM32L4_RCC_APB2ENR;
|
||||
en_bit = RCC_APB2ENR_TIM1EN;
|
||||
break;
|
||||
case 1:
|
||||
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;
|
||||
case 2:
|
||||
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_APB1ENR_TIM3EN;
|
||||
break;
|
||||
case 3:
|
||||
regaddr = STM32L4_RCC_APB1ENR1;
|
||||
en_bit = RCC_APB1ENR_TIM3EN;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM4_PWM
|
||||
case 4:
|
||||
regaddr = STM32L4_RCC_APB1ENR1;
|
||||
en_bit = RCC_APB1ENR1_TIM4EN;
|
||||
break;
|
||||
case 4:
|
||||
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_APB1ENR_TIM5EN;
|
||||
break;
|
||||
case 5:
|
||||
regaddr = STM32L4_RCC_APB1ENR1;
|
||||
en_bit = RCC_APB1ENR_TIM5EN;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM8_PWM
|
||||
case 8:
|
||||
regaddr = STM32L4_RCC_APB2ENR;
|
||||
en_bit = RCC_APB2ENR_TIM8EN;
|
||||
break;
|
||||
case 8:
|
||||
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;
|
||||
case 15:
|
||||
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;
|
||||
case 16:
|
||||
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;
|
||||
case 17:
|
||||
regaddr = STM32L4_RCC_APB2ENR;
|
||||
en_bit = RCC_APB2ENR_TIM17EN;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable/disable APB 1/2 clock for timer */
|
||||
/* Enable/disable APB 1/2 clock for timer */
|
||||
|
||||
if (on)
|
||||
{
|
||||
modifyreg32(regaddr, 0, en_bit);
|
||||
if (on)
|
||||
{
|
||||
modifyreg32(regaddr, 0, en_bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
modifyreg32(regaddr, en_bit, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
modifyreg32(regaddr, en_bit, 0);
|
||||
uint32_t clock_bits;
|
||||
|
||||
switch (priv->timid)
|
||||
{
|
||||
#ifdef CONFIG_STM32L4_LPTIM1_PWM
|
||||
case 1:
|
||||
#if defined(CONFIG_STM32L4_LPTIM1_CLK_APB1)
|
||||
/* Enable APB clock for LPTIM1 */
|
||||
|
||||
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;
|
||||
#elif defined(CONFIG_STM32L4_LPTIM1_CLK_LSI)
|
||||
clock_bits = RCC_CCIPR_LPTIM1SEL_LSI;
|
||||
#elif defined(CONFIG_STM32L4_LPTIM1_CLK_LSE)
|
||||
clock_bits = RCC_CCIPR_LPTIM1SEL_LSE;
|
||||
#elif defined(CONFIG_STM32L4_LPTIM1_CLK_HSI)
|
||||
clock_bits = RCC_CCIPR_LPTIM1SEL_HSI;
|
||||
#endif
|
||||
/* Choose which clock will be used for LPTIM1 */
|
||||
|
||||
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 */
|
||||
|
||||
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;
|
||||
#elif defined(CONFIG_STM32L4_LPTIM2_CLK_LSI)
|
||||
clock_bits = RCC_CCIPR_LPTIM2SEL_LSI;
|
||||
#elif defined(CONFIG_STM32L4_LPTIM2_CLK_LSE)
|
||||
clock_bits = RCC_CCIPR_LPTIM2SEL_LSE;
|
||||
#elif defined(CONFIG_STM32L4_LPTIM2_CLK_HSI)
|
||||
clock_bits = RCC_CCIPR_LPTIM2SEL_HSI;
|
||||
#endif
|
||||
/* Choose which clock will be used for LPTIM2 */
|
||||
|
||||
modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM2SEL_MASK, clock_bits);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1711,7 +2026,15 @@ static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev)
|
||||
uint32_t pincfg;
|
||||
int i;
|
||||
|
||||
pwminfo("TIM%u\n", priv->timid);
|
||||
if (priv->timtype == TIMTYPE_LOWPOWER)
|
||||
{
|
||||
pwminfo("LPTIM%u\n", priv->timid);
|
||||
}
|
||||
else
|
||||
{
|
||||
pwminfo("TIM%u\n", priv->timid);
|
||||
}
|
||||
|
||||
stm32l4pwm_dumpregs(priv, "Initially");
|
||||
|
||||
/* Enable APB1/2 clocking for timer. */
|
||||
@ -1730,7 +2053,6 @@ static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev)
|
||||
stm32l4_configgpio(pincfg);
|
||||
}
|
||||
|
||||
|
||||
/* Enable complementary channel if available */
|
||||
|
||||
pincfg = priv->channels[i].npincfg;
|
||||
@ -1804,7 +2126,6 @@ static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
|
||||
|
||||
stm32l4_configgpio(pincfg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -1852,7 +2173,14 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
|
||||
|
||||
/* Start the time */
|
||||
|
||||
return stm32l4pwm_timer(priv, info);
|
||||
if (priv->timtype == TIMTYPE_LOWPOWER)
|
||||
{
|
||||
return stm32l4pwm_lptimer(priv, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
return stm32l4pwm_timer(priv, info);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
|
||||
@ -1861,7 +2189,6 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
|
||||
int ret = OK;
|
||||
FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
|
||||
|
||||
#ifndef CONFIG_PWM_PULSECOUNT
|
||||
/* if frequency has not changed we just update duty */
|
||||
|
||||
if (info->frequency == priv->frequency)
|
||||
@ -1875,27 +2202,32 @@ 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,
|
||||
ret = stm32l4pwm_update_duty(priv, info->channels[i].channel,
|
||||
info->channels[i].duty);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
ret = stm32l4pwm_update_duty(priv,priv->channels[0].channel,info->duty);
|
||||
ret = stm32l4pwm_update_duty(priv, priv->channels[0].channel, info->duty);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = stm32l4pwm_timer(priv, info);
|
||||
if (priv->timtype == TIMTYPE_LOWPOWER)
|
||||
{
|
||||
ret = stm32l4pwm_lptimer(priv, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = stm32l4pwm_timer(priv, info);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PWM_PULSECOUNT
|
||||
/* Save current frequency */
|
||||
|
||||
if (ret == OK)
|
||||
{
|
||||
priv->frequency = info->frequency;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1929,7 +2261,14 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev)
|
||||
uint32_t regval;
|
||||
irqstate_t flags;
|
||||
|
||||
pwminfo("TIM%u\n", priv->timid);
|
||||
if (priv->timtype == TIMTYPE_LOWPOWER)
|
||||
{
|
||||
pwminfo("LPTIM%u\n", priv->timid);
|
||||
}
|
||||
else
|
||||
{
|
||||
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.
|
||||
@ -1948,58 +2287,79 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev)
|
||||
|
||||
/* Determine which timer to reset */
|
||||
|
||||
switch (priv->timid)
|
||||
if (priv->timtype != TIMTYPE_LOWPOWER)
|
||||
{
|
||||
switch (priv->timid)
|
||||
{
|
||||
#ifdef CONFIG_STM32L4_TIM1_PWM
|
||||
case 1:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB2RSTR_TIM1RST;
|
||||
break;
|
||||
case 1:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB2RSTR_TIM1RST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM2_PWM
|
||||
case 2:
|
||||
regaddr = STM32L4_RCC_APB1RSTR1;
|
||||
resetbit = RCC_APB1RSTR1_TIM2RST;
|
||||
break;
|
||||
case 2:
|
||||
regaddr = STM32L4_RCC_APB1RSTR1;
|
||||
resetbit = RCC_APB1RSTR1_TIM2RST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM3_PWM
|
||||
case 3:
|
||||
regaddr = STM32L4_RCC_APB1RSTR1;
|
||||
resetbit = RCC_APB1RSTR_TIM3RST;
|
||||
break;
|
||||
case 3:
|
||||
regaddr = STM32L4_RCC_APB1RSTR1;
|
||||
resetbit = RCC_APB1RSTR_TIM3RST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM4_PWM
|
||||
case 4:
|
||||
regaddr = STM32L4_RCC_APB1RSTR1;
|
||||
resetbit = RCC_APB1RSTR1_TIM4RST;
|
||||
break;
|
||||
case 4:
|
||||
regaddr = STM32L4_RCC_APB1RSTR1;
|
||||
resetbit = RCC_APB1RSTR1_TIM4RST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM5_PWM
|
||||
case 5:
|
||||
regaddr = STM32L4_RCC_APB1RSTR1;
|
||||
resetbit = RCC_APB1RSTR_TIM5RST;
|
||||
break;
|
||||
case 5:
|
||||
regaddr = STM32L4_RCC_APB1RSTR1;
|
||||
resetbit = RCC_APB1RSTR_TIM5RST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM8_PWM
|
||||
case 8:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB2RSTR_TIM8RST;
|
||||
break;
|
||||
case 8:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB2RSTR_TIM8RST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM16_PWM
|
||||
case 16:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB2RSTR_TIM16RST;
|
||||
break;
|
||||
case 16:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB2RSTR_TIM16RST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_TIM17_PWM
|
||||
case 17:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB2RSTR_TIM17RST;
|
||||
break;
|
||||
case 17:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB2RSTR_TIM17RST;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (priv->timid)
|
||||
{
|
||||
#ifdef CONFIG_STM32L4_LPTIM1_PWM
|
||||
case 1:
|
||||
regaddr = STM32L4_RCC_APB2RSTR;
|
||||
resetbit = RCC_APB1RSTR1_LPTIM1RST;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_STM32L4_LPTIM2_PWM
|
||||
case 2:
|
||||
regaddr = STM32L4_RCC_APB1RSTR2;
|
||||
resetbit = RCC_APB1RSTR2_LPTIM2RST;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the timer - stopping the output and putting the timer back
|
||||
@ -2153,4 +2513,49 @@ FAR struct pwm_lowerhalf_s *stm32l4_pwminitialize(int timer)
|
||||
return (FAR struct pwm_lowerhalf_s *)lower;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32l4_lp_pwminitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize one low-power timer for use with the upper_level PWM driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* timer - A number identifying the timer use. The number of valid timer
|
||||
* IDs varies with the STM32 MCU and MCU family but is somewhere in
|
||||
* the range of {1,..,2}.
|
||||
*
|
||||
* Returned Value:
|
||||
* 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_lp_pwminitialize(int timer)
|
||||
{
|
||||
FAR struct stm32l4_pwmtimer_s *lower;
|
||||
|
||||
pwminfo("LPTIM%u\n", timer);
|
||||
|
||||
switch (timer)
|
||||
{
|
||||
#ifdef CONFIG_STM32L4_LPTIM1_PWM
|
||||
case 1:
|
||||
lower = &g_pwmlp1dev;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_LPTIM2_PWM
|
||||
case 2:
|
||||
lower = &g_pwmlp2dev;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
pwmerr("ERROR: No such timer configured\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (FAR struct pwm_lowerhalf_s *)lower;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_STM32L4_TIMn_PWM, n = 1,...,17 */
|
||||
|
@ -55,11 +55,14 @@
|
||||
/************************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************************/
|
||||
|
||||
/* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_STM32L4_TIM1
|
||||
@ -97,14 +100,16 @@
|
||||
|
||||
/* Check if PWM support for any channel is enabled. */
|
||||
|
||||
#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) || \
|
||||
defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \
|
||||
defined(CONFIG_STM32L4_TIM17_PWM)
|
||||
#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) || \
|
||||
defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \
|
||||
defined(CONFIG_STM32L4_TIM17_PWM) || defined(CONFIG_STM32L4_LPTIM1_PWM) || \
|
||||
defined(CONFIG_STM32L4_LPTIM2_PWM)
|
||||
|
||||
#include <arch/board/board.h>
|
||||
#include "hardware/stm32l4_tim.h"
|
||||
#include "hardware/stm32l4_lptim.h"
|
||||
|
||||
#ifdef CONFIG_PWM_MULTICHAN
|
||||
|
||||
@ -677,6 +682,40 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* REVISIT: any other LPTIM implementations have more than one channel? */
|
||||
|
||||
#define CONFIG_STM32L4_LPTIM1_CHANNEL 1
|
||||
|
||||
#ifdef CONFIG_STM32L4_LPTIM1_PWM
|
||||
# if !defined(CONFIG_STM32L4_LPTIM1_CHANNEL)
|
||||
# error "CONFIG_STM32L4_LPTIM1_CHANNEL must be provided"
|
||||
# elif CONFIG_STM32L4_LPTIM1_CHANNEL == 1
|
||||
# define CONFIG_STM32L4_LPTIM1_CHANNEL1 1
|
||||
# define CONFIG_STM32L4_LPTIM1_CH1MODE CONFIG_STM32L4_LPTIM1_CHMODE
|
||||
# define PWM_LPTIM1_CH1CFG GPIO_LPTIM1_CH1OUT
|
||||
# define PWM_LPTIM1_CH1NCFG 0
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_LPTIM1_CHANNEL"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* REVISIT: any other LPTIM implementations have more than one channel? */
|
||||
|
||||
#define CONFIG_STM32L4_LPTIM2_CHANNEL 1
|
||||
|
||||
#ifdef CONFIG_STM32L4_LPTIM2_PWM
|
||||
# if !defined(CONFIG_STM32L4_LPTIM2_CHANNEL)
|
||||
# error "CONFIG_STM32L4_LPTIM2_CHANNEL must be provided"
|
||||
# elif CONFIG_STM32L4_LPTIM2_CHANNEL == 1
|
||||
# define CONFIG_STM32L4_LPTIM2_CHANNEL1 1
|
||||
# define CONFIG_STM32L4_LPTIM2_CH1MODE CONFIG_STM32L4_LPTIM2_CHMODE
|
||||
# define PWM_LPTIM2_CH1CFG GPIO_LPTIM2_CH1OUT
|
||||
# define PWM_LPTIM2_CH1NCFG 0
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_LPTIM2_CHANNEL"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define PWM_NCHANNELS 1
|
||||
|
||||
#endif
|
||||
@ -723,6 +762,25 @@ extern "C"
|
||||
|
||||
FAR struct pwm_lowerhalf_s *stm32l4_pwminitialize(int timer);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32l4_lp_pwminitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize one low-power timer for use with the upper_level PWM driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* timer - A number identifying the timer use. The number of valid timer
|
||||
* IDs varies with the STM32 MCU and MCU family but is somewhere in
|
||||
* the range of {1,..,2}.
|
||||
*
|
||||
* Returned Value:
|
||||
* 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_lp_pwminitialize(int timer);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
@ -261,6 +261,9 @@
|
||||
#define GPIO_TIM1_CH2OUT GPIO_TIM1_CH2OUT_1
|
||||
#define GPIO_TIM1_CH2NOUT GPIO_TIM1_CH2N_1
|
||||
|
||||
#define GPIO_LPTIM1_CH1OUT GPIO_LPTIM1_OUT_1
|
||||
#define GPIO_LPTIM2_CH1OUT GPIO_LPTIM2_OUT_2
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
@ -202,8 +202,9 @@
|
||||
* DFSDM
|
||||
*/
|
||||
|
||||
/* prescaler common to all PLL inputs; will be 1 (XXX source is implicitly
|
||||
as per comment above HSI) */
|
||||
/* Prescaler common to all PLL inputs; will be 1 (XXX source is implicitly
|
||||
* as per comment above HSI) .
|
||||
*/
|
||||
|
||||
#define STM32L4_PLLCFG_PLLM RCC_PLLCFG_PLLM(1)
|
||||
|
||||
@ -271,24 +272,26 @@
|
||||
/* APB1 clock (PCLK1) is HCLK/1 (80MHz) */
|
||||
|
||||
#define STM32L4_RCC_CFGR_PPRE1 RCC_CFGR_PPRE1_HCLK /* PCLK1 = HCLK / 1 */
|
||||
#define STM32L4_PCLK1_FREQUENCY (STM32L4_HCLK_FREQUENCY/1)
|
||||
#define STM32L4_PCLK1_FREQUENCY (STM32L4_HCLK_FREQUENCY / 1)
|
||||
|
||||
/* Timers driven from APB1 will be twice PCLK1 */
|
||||
|
||||
/* REVISIT : this can be configured */
|
||||
|
||||
#define STM32L4_APB1_TIM2_CLKIN (2*STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM3_CLKIN (2*STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM4_CLKIN (2*STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM5_CLKIN (2*STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM6_CLKIN (2*STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM7_CLKIN (2*STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM2_CLKIN (2 * STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM3_CLKIN (2 * STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM4_CLKIN (2 * STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM5_CLKIN (2 * STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM6_CLKIN (2 * STM32L4_PCLK1_FREQUENCY)
|
||||
#define STM32L4_APB1_TIM7_CLKIN (2 * STM32L4_PCLK1_FREQUENCY)
|
||||
|
||||
/* APB2 clock (PCLK2) is HCLK (80MHz) */
|
||||
|
||||
#define STM32L4_RCC_CFGR_PPRE2 RCC_CFGR_PPRE2_HCLK /* PCLK2 = HCLK / 1 */
|
||||
#define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY/1)
|
||||
#define STM32L4_PCLK2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 1)
|
||||
|
||||
/* Timers driven from APB2 will be twice PCLK2 */
|
||||
|
||||
/* REVISIT : this can be configured */
|
||||
|
||||
#define STM32L4_APB2_TIM1_CLKIN (2*STM32L4_PCLK2_FREQUENCY)
|
||||
@ -301,6 +304,7 @@
|
||||
* otherwise frequency is 2xAPBx.
|
||||
* Note: TIM1,8,15,16,17 are on APB2, others on APB1
|
||||
*/
|
||||
|
||||
/* REVISIT : this can be configured */
|
||||
|
||||
/* TODO SDMMC */
|
||||
@ -488,8 +492,8 @@
|
||||
#define BOARD_TIM15_FREQUENCY STM32L4_HCLK_FREQUENCY
|
||||
#define BOARD_TIM16_FREQUENCY STM32L4_HCLK_FREQUENCY
|
||||
#define BOARD_TIM17_FREQUENCY STM32L4_HCLK_FREQUENCY
|
||||
#define BOARD_LPTIM1_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define BOARD_LPTIM2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define STM32L4_LPTIM1_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
#define STM32L4_LPTIM2_FREQUENCY (STM32L4_HCLK_FREQUENCY / 2)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
@ -262,6 +263,43 @@ int stm32l4_pwm_setup(void)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_STM32L4_LPTIM1_PWM)
|
||||
pwm = stm32l4_lp_pwminitialize(1);
|
||||
if (!pwm)
|
||||
{
|
||||
aerr("ERROR: Failed to get the STM32L4 PWM lower half\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Register the PWM driver at "/dev/lppwm1" */
|
||||
|
||||
ret = pwm_register("/dev/lppwm1", pwm);
|
||||
if (ret < 0)
|
||||
{
|
||||
aerr("ERROR: pwm_register failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_STM32L4_LPTIM2_PWM)
|
||||
pwm = stm32l4_lp_pwminitialize(2);
|
||||
if (!pwm)
|
||||
{
|
||||
aerr("ERROR: Failed to get the STM32L4 PWM lower half\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Register the PWM driver at "/dev/lppwm2" */
|
||||
|
||||
ret = pwm_register("/dev/lppwm2", pwm);
|
||||
if (ret < 0)
|
||||
{
|
||||
aerr("ERROR: pwm_register failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now we are initialized */
|
||||
|
||||
initialized = true;
|
||||
|
Loading…
Reference in New Issue
Block a user