This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 5be057f0618b35acd8f5c4c19acafab639be17e3 Author: raiden00pl <[email protected]> AuthorDate: Sat Oct 24 13:25:29 2026 +0200 arch/arm/src/common/stm32: add STM32L4 compatible LPTIM API Add the timer operations of the STM32L4 LPTIM API to the common driver: setmode, setclock, setchannel, setclocksource, setpolarity, setcountmode and getperiod. init() resets the timer and fails for an instance in use, start() takes stm32_lptim_mode_t. Signed-off-by: raiden00pl <[email protected]> Assisted-by: Claude Code --- arch/arm/src/common/stm32/stm32_lptim.c | 982 +++++++++++++++++++++++--------- arch/arm/src/common/stm32/stm32_lptim.h | 96 +++- 2 files changed, 784 insertions(+), 294 deletions(-) diff --git a/arch/arm/src/common/stm32/stm32_lptim.c b/arch/arm/src/common/stm32/stm32_lptim.c index fcdf86a6a18..ac880b92deb 100644 --- a/arch/arm/src/common/stm32/stm32_lptim.c +++ b/arch/arm/src/common/stm32/stm32_lptim.c @@ -28,218 +28,651 @@ #include <nuttx/arch.h> #include <nuttx/irq.h> -#include <sys/types.h> -#include <stdint.h> +#include <sys/param.h> + #include <stdbool.h> +#include <stdint.h> #include <assert.h> #include <errno.h> -#include <nuttx/debug.h> #include <arch/board/board.h> -#include "chip.h" #include "arm_internal.h" -#include "stm32_rcc.h" +#include "chip.h" +#include "stm32.h" #include "stm32_lptim.h" #include "stm32_lptim_clk.h" -#if defined(CONFIG_STM32_LPTIM1) || defined(CONFIG_STM32_LPTIM2) || \ - defined(CONFIG_STM32_LPTIM3) || defined(CONFIG_STM32_LPTIM4) || \ - defined(CONFIG_STM32_LPTIM5) +#if defined(CONFIG_STM32_LPTIM1) || \ + defined(CONFIG_STM32_LPTIM2) || \ + defined(CONFIG_STM32_LPTIM3) || \ + defined(CONFIG_STM32_LPTIM4) || \ + defined(CONFIG_STM32_LPTIM5) || \ + defined(CONFIG_STM32_LPTIM6) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* LPTIM kernel clock frequency, optionally provided by board.h. It is + * needed only by setclock(). + */ + +#ifdef STM32_LPTIM1_CLKIN +# define LPTIM1_CLKIN STM32_LPTIM1_CLKIN +#else +# define LPTIM1_CLKIN 0 +#endif +#ifdef STM32_LPTIM2_CLKIN +# define LPTIM2_CLKIN STM32_LPTIM2_CLKIN +#else +# define LPTIM2_CLKIN 0 +#endif +#ifdef STM32_LPTIM3_CLKIN +# define LPTIM3_CLKIN STM32_LPTIM3_CLKIN +#else +# define LPTIM3_CLKIN 0 +#endif +#ifdef STM32_LPTIM4_CLKIN +# define LPTIM4_CLKIN STM32_LPTIM4_CLKIN +#else +# define LPTIM4_CLKIN 0 +#endif +#ifdef STM32_LPTIM5_CLKIN +# define LPTIM5_CLKIN STM32_LPTIM5_CLKIN +#else +# define LPTIM5_CLKIN 0 +#endif +#ifdef STM32_LPTIM6_CLKIN +# define LPTIM6_CLKIN STM32_LPTIM6_CLKIN +#else +# define LPTIM6_CLKIN 0 +#endif + +/* Output channel pins, GPIO_LPTIMn_CHmOUT from board.h (0: none) */ + +#define LPTIM_NCHANNELS 4 + +#ifdef GPIO_LPTIM1_CH1OUT +# define LPTIM1_CH1OUT GPIO_LPTIM1_CH1OUT +#else +# define LPTIM1_CH1OUT 0 +#endif +#ifdef GPIO_LPTIM1_CH2OUT +# define LPTIM1_CH2OUT GPIO_LPTIM1_CH2OUT +#else +# define LPTIM1_CH2OUT 0 +#endif +#ifdef GPIO_LPTIM1_CH3OUT +# define LPTIM1_CH3OUT GPIO_LPTIM1_CH3OUT +#else +# define LPTIM1_CH3OUT 0 +#endif +#ifdef GPIO_LPTIM1_CH4OUT +# define LPTIM1_CH4OUT GPIO_LPTIM1_CH4OUT +#else +# define LPTIM1_CH4OUT 0 +#endif +#ifdef GPIO_LPTIM2_CH1OUT +# define LPTIM2_CH1OUT GPIO_LPTIM2_CH1OUT +#else +# define LPTIM2_CH1OUT 0 +#endif +#ifdef GPIO_LPTIM2_CH2OUT +# define LPTIM2_CH2OUT GPIO_LPTIM2_CH2OUT +#else +# define LPTIM2_CH2OUT 0 +#endif +#ifdef GPIO_LPTIM2_CH3OUT +# define LPTIM2_CH3OUT GPIO_LPTIM2_CH3OUT +#else +# define LPTIM2_CH3OUT 0 +#endif +#ifdef GPIO_LPTIM2_CH4OUT +# define LPTIM2_CH4OUT GPIO_LPTIM2_CH4OUT +#else +# define LPTIM2_CH4OUT 0 +#endif +#ifdef GPIO_LPTIM3_CH1OUT +# define LPTIM3_CH1OUT GPIO_LPTIM3_CH1OUT +#else +# define LPTIM3_CH1OUT 0 +#endif +#ifdef GPIO_LPTIM3_CH2OUT +# define LPTIM3_CH2OUT GPIO_LPTIM3_CH2OUT +#else +# define LPTIM3_CH2OUT 0 +#endif +#ifdef GPIO_LPTIM3_CH3OUT +# define LPTIM3_CH3OUT GPIO_LPTIM3_CH3OUT +#else +# define LPTIM3_CH3OUT 0 +#endif +#ifdef GPIO_LPTIM3_CH4OUT +# define LPTIM3_CH4OUT GPIO_LPTIM3_CH4OUT +#else +# define LPTIM3_CH4OUT 0 +#endif +#ifdef GPIO_LPTIM4_CH1OUT +# define LPTIM4_CH1OUT GPIO_LPTIM4_CH1OUT +#else +# define LPTIM4_CH1OUT 0 +#endif +#ifdef GPIO_LPTIM4_CH2OUT +# define LPTIM4_CH2OUT GPIO_LPTIM4_CH2OUT +#else +# define LPTIM4_CH2OUT 0 +#endif +#ifdef GPIO_LPTIM4_CH3OUT +# define LPTIM4_CH3OUT GPIO_LPTIM4_CH3OUT +#else +# define LPTIM4_CH3OUT 0 +#endif +#ifdef GPIO_LPTIM4_CH4OUT +# define LPTIM4_CH4OUT GPIO_LPTIM4_CH4OUT +#else +# define LPTIM4_CH4OUT 0 +#endif +#ifdef GPIO_LPTIM5_CH1OUT +# define LPTIM5_CH1OUT GPIO_LPTIM5_CH1OUT +#else +# define LPTIM5_CH1OUT 0 +#endif +#ifdef GPIO_LPTIM5_CH2OUT +# define LPTIM5_CH2OUT GPIO_LPTIM5_CH2OUT +#else +# define LPTIM5_CH2OUT 0 +#endif +#ifdef GPIO_LPTIM5_CH3OUT +# define LPTIM5_CH3OUT GPIO_LPTIM5_CH3OUT +#else +# define LPTIM5_CH3OUT 0 +#endif +#ifdef GPIO_LPTIM5_CH4OUT +# define LPTIM5_CH4OUT GPIO_LPTIM5_CH4OUT +#else +# define LPTIM5_CH4OUT 0 +#endif +#ifdef GPIO_LPTIM6_CH1OUT +# define LPTIM6_CH1OUT GPIO_LPTIM6_CH1OUT +#else +# define LPTIM6_CH1OUT 0 +#endif +#ifdef GPIO_LPTIM6_CH2OUT +# define LPTIM6_CH2OUT GPIO_LPTIM6_CH2OUT +#else +# define LPTIM6_CH2OUT 0 +#endif +#ifdef GPIO_LPTIM6_CH3OUT +# define LPTIM6_CH3OUT GPIO_LPTIM6_CH3OUT +#else +# define LPTIM6_CH3OUT 0 +#endif +#ifdef GPIO_LPTIM6_CH4OUT +# define LPTIM6_CH4OUT GPIO_LPTIM6_CH4OUT +#else +# define LPTIM6_CH4OUT 0 +#endif + +/* Largest PRESC field value (division by 128) */ + +#define LPTIM_PRESC_MAX 7 /**************************************************************************** - * Private Function prototypes + * Private Types ****************************************************************************/ -/* Low-power timer methods */ +struct stm32_lptim_priv_s +{ + const struct stm32_lptim_ops_s *ops; + bool inuse; /* Returned by stm32_lptim_init() */ + uint32_t base; /* LPTIMn base address */ + int irq; /* LPTIMn interrupt */ + uint32_t freq; /* LPTIMn kernel clock frequency */ + uint32_t enreg; /* RCC clock enable register */ + uint32_t enbit; /* RCC clock enable bit */ + uint32_t rstreg; /* RCC reset register */ + uint32_t rstbit; /* RCC reset bit */ + uint32_t pins[LPTIM_NCHANNELS]; /* Output channel pin configurations */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +static int stm32_lptim_setmode(struct stm32_lptim_dev_s *dev, + stm32_lptim_mode_t mode); +static int stm32_lptim_setclock(struct stm32_lptim_dev_s *dev, + uint32_t freq); +static int stm32_lptim_setchannel(struct stm32_lptim_dev_s *dev, + stm32_lptim_channel_t channel, + int enable); +static int stm32_lptim_setclocksource(struct stm32_lptim_dev_s *dev, + stm32_lptim_clksrc_t clksrc); +static int stm32_lptim_setpolarity(struct stm32_lptim_dev_s *dev, + stm32_lptim_clkpol_t polarity); +static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev); +static int stm32_lptim_setcountmode(struct stm32_lptim_dev_s *dev, + stm32_lptim_cntmode_t cntmode); +static void stm32_lptim_setperiod(struct stm32_lptim_dev_s *dev, + uint32_t period); +static uint32_t stm32_lptim_getperiod(struct stm32_lptim_dev_s *dev); static void stm32_lptim_setcfgr(struct stm32_lptim_dev_s *dev, uint32_t regval); -static void stm32_lptim_setperiod(struct stm32_lptim_dev_s *dev, - uint32_t period); static void stm32_lptim_setcompare(struct stm32_lptim_dev_s *dev, - uint32_t cmp); -static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev); -static int stm32_lptim_setinput(struct stm32_lptim_dev_s *dev, + uint32_t cmp); +static int stm32_lptim_setinput(struct stm32_lptim_dev_s *dev, uint32_t input, uint32_t mux); static void stm32_lptim_enable(struct stm32_lptim_dev_s *dev, bool on); static void stm32_lptim_start(struct stm32_lptim_dev_s *dev, - stm32_lptim_start_mode_t mode); + stm32_lptim_mode_t mode); static void stm32_lptim_resetcounter(struct stm32_lptim_dev_s *dev); -static void stm32_lptim_enablerar(struct stm32_lptim_dev_s *dev, - bool on); - -static int stm32_lptim_setisr(struct stm32_lptim_dev_s *dev, - xcpt_t handler, void *arg, int source); +static void stm32_lptim_enablerar(struct stm32_lptim_dev_s *dev, bool on); +static int stm32_lptim_setisr(struct stm32_lptim_dev_s *dev, + xcpt_t handler, void *arg, int source); static void stm32_lptim_enableint(struct stm32_lptim_dev_s *dev, int source); static void stm32_lptim_disableint(struct stm32_lptim_dev_s *dev, - int source); -static void stm32_lptim_ackint(struct stm32_lptim_dev_s *dev, - int source); - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ + int source); +static void stm32_lptim_ackint(struct stm32_lptim_dev_s *dev, int source); /**************************************************************************** * Private Data ****************************************************************************/ -static const struct stm32_lptim_ops_s stm32_lptim_ops = -{ - .setcfgr = &stm32_lptim_setcfgr, - .setperiod = &stm32_lptim_setperiod, - .setcompare = &stm32_lptim_setcompare, - .getcounter = &stm32_lptim_getcounter, - .setinput = &stm32_lptim_setinput, - .enable = &stm32_lptim_enable, - .start = &stm32_lptim_start, - .resetcounter = &stm32_lptim_resetcounter, - .enablerar = &stm32_lptim_enablerar, - .setisr = &stm32_lptim_setisr, - .enableint = &stm32_lptim_enableint, - .disableint = &stm32_lptim_disableint, - .ackint = &stm32_lptim_ackint +static const struct stm32_lptim_ops_s g_lptim_ops = +{ + .setmode = stm32_lptim_setmode, + .setclock = stm32_lptim_setclock, + .setchannel = stm32_lptim_setchannel, + .setclocksource = stm32_lptim_setclocksource, + .setpolarity = stm32_lptim_setpolarity, + .getcounter = stm32_lptim_getcounter, + .setcountmode = stm32_lptim_setcountmode, + .setperiod = stm32_lptim_setperiod, + .getperiod = stm32_lptim_getperiod, + .setcfgr = stm32_lptim_setcfgr, + .setcompare = stm32_lptim_setcompare, + .setinput = stm32_lptim_setinput, + .enable = stm32_lptim_enable, + .start = stm32_lptim_start, + .resetcounter = stm32_lptim_resetcounter, + .enablerar = stm32_lptim_enablerar, + .setisr = stm32_lptim_setisr, + .enableint = stm32_lptim_enableint, + .disableint = stm32_lptim_disableint, + .ackint = stm32_lptim_ackint, }; #ifdef CONFIG_STM32_LPTIM1 -struct stm32_lptim_dev_s stm32_lptim1_priv = +static struct stm32_lptim_priv_s g_lptim1 = { - .ops = &stm32_lptim_ops, + .ops = &g_lptim_ops, .base = STM32_LPTIM1_BASE, + .irq = STM32_IRQ_LPTIM1, + .freq = LPTIM1_CLKIN, + .enreg = STM32_RCC_LPTIM1_EN_REG, + .enbit = STM32_RCC_LPTIM1_EN, + .rstreg = STM32_RCC_LPTIM1_RST_REG, + .rstbit = STM32_RCC_LPTIM1_RST, + .pins = + { + LPTIM1_CH1OUT, LPTIM1_CH2OUT, LPTIM1_CH3OUT, LPTIM1_CH4OUT + }, }; #endif + #ifdef CONFIG_STM32_LPTIM2 -struct stm32_lptim_dev_s stm32_lptim2_priv = +static struct stm32_lptim_priv_s g_lptim2 = { - .ops = &stm32_lptim_ops, + .ops = &g_lptim_ops, .base = STM32_LPTIM2_BASE, + .irq = STM32_IRQ_LPTIM2, + .freq = LPTIM2_CLKIN, + .enreg = STM32_RCC_LPTIM2_EN_REG, + .enbit = STM32_RCC_LPTIM2_EN, + .rstreg = STM32_RCC_LPTIM2_RST_REG, + .rstbit = STM32_RCC_LPTIM2_RST, + .pins = + { + LPTIM2_CH1OUT, LPTIM2_CH2OUT, LPTIM2_CH3OUT, LPTIM2_CH4OUT + }, }; #endif + #ifdef CONFIG_STM32_LPTIM3 -struct stm32_lptim_dev_s stm32_lptim3_priv = +static struct stm32_lptim_priv_s g_lptim3 = { - .ops = &stm32_lptim_ops, + .ops = &g_lptim_ops, .base = STM32_LPTIM3_BASE, + .irq = STM32_IRQ_LPTIM3, + .freq = LPTIM3_CLKIN, + .enreg = STM32_RCC_LPTIM3_EN_REG, + .enbit = STM32_RCC_LPTIM3_EN, + .rstreg = STM32_RCC_LPTIM3_RST_REG, + .rstbit = STM32_RCC_LPTIM3_RST, + .pins = + { + LPTIM3_CH1OUT, LPTIM3_CH2OUT, LPTIM3_CH3OUT, LPTIM3_CH4OUT + }, }; #endif + #ifdef CONFIG_STM32_LPTIM4 -struct stm32_lptim_dev_s stm32_lptim4_priv = +static struct stm32_lptim_priv_s g_lptim4 = { - .ops = &stm32_lptim_ops, + .ops = &g_lptim_ops, .base = STM32_LPTIM4_BASE, + .irq = STM32_IRQ_LPTIM4, + .freq = LPTIM4_CLKIN, + .enreg = STM32_RCC_LPTIM4_EN_REG, + .enbit = STM32_RCC_LPTIM4_EN, + .rstreg = STM32_RCC_LPTIM4_RST_REG, + .rstbit = STM32_RCC_LPTIM4_RST, + .pins = + { + LPTIM4_CH1OUT, LPTIM4_CH2OUT, LPTIM4_CH3OUT, LPTIM4_CH4OUT + }, }; #endif + #ifdef CONFIG_STM32_LPTIM5 -struct stm32_lptim_dev_s stm32_lptim5_priv = +static struct stm32_lptim_priv_s g_lptim5 = { - .ops = &stm32_lptim_ops, + .ops = &g_lptim_ops, .base = STM32_LPTIM5_BASE, + .irq = STM32_IRQ_LPTIM5, + .freq = LPTIM5_CLKIN, + .enreg = STM32_RCC_LPTIM5_EN_REG, + .enbit = STM32_RCC_LPTIM5_EN, + .rstreg = STM32_RCC_LPTIM5_RST_REG, + .rstbit = STM32_RCC_LPTIM5_RST, + .pins = + { + LPTIM5_CH1OUT, LPTIM5_CH2OUT, LPTIM5_CH3OUT, LPTIM5_CH4OUT + }, +}; +#endif + +#ifdef CONFIG_STM32_LPTIM6 +static struct stm32_lptim_priv_s g_lptim6 = +{ + .ops = &g_lptim_ops, + .base = STM32_LPTIM6_BASE, + .irq = STM32_IRQ_LPTIM6, + .freq = LPTIM6_CLKIN, + .enreg = STM32_RCC_LPTIM6_EN_REG, + .enbit = STM32_RCC_LPTIM6_EN, + .rstreg = STM32_RCC_LPTIM6_RST_REG, + .rstbit = STM32_RCC_LPTIM6_RST, + .pins = + { + LPTIM6_CH1OUT, LPTIM6_CH2OUT, LPTIM6_CH3OUT, LPTIM6_CH4OUT + }, }; #endif +/* Instances indexed by LPTIM number - 1 */ + +static struct stm32_lptim_priv_s * const g_lptim[] = +{ +#ifdef CONFIG_STM32_LPTIM1 + [0] = &g_lptim1, +#endif +#ifdef CONFIG_STM32_LPTIM2 + [1] = &g_lptim2, +#endif +#ifdef CONFIG_STM32_LPTIM3 + [2] = &g_lptim3, +#endif +#ifdef CONFIG_STM32_LPTIM4 + [3] = &g_lptim4, +#endif +#ifdef CONFIG_STM32_LPTIM5 + [4] = &g_lptim5, +#endif +#ifdef CONFIG_STM32_LPTIM6 + [5] = &g_lptim6, +#endif +}; + /**************************************************************************** * Private Functions ****************************************************************************/ -/* Get a 32-bit register value by offset. - */ +/**************************************************************************** + * Name: stm32_getreg32 / stm32_putreg32 / stm32_modifyreg32 + ****************************************************************************/ static inline uint32_t stm32_getreg32(struct stm32_lptim_dev_s *dev, uint8_t offset) { - return getreg32(dev->base + offset); + return getreg32(((struct stm32_lptim_priv_s *)dev)->base + offset); } -/* Put a 32-bit register value by offset. - */ - static inline void stm32_putreg32(struct stm32_lptim_dev_s *dev, uint8_t offset, uint32_t value) { - putreg32(value, dev->base + offset); + putreg32(value, ((struct stm32_lptim_priv_s *)dev)->base + offset); } -static void stm32_lptim_setcfgr(struct stm32_lptim_dev_s *dev, - uint32_t regval) +static inline void stm32_modifyreg32(struct stm32_lptim_dev_s *dev, + uint8_t offset, uint32_t clearbits, + uint32_t setbits) { - stm32_putreg32(dev, STM32_LPTIM_CFGR_OFFSET, regval); + modifyreg32(((struct stm32_lptim_priv_s *)dev)->base + offset, + clearbits, setbits); } -static void stm32_lptim_setperiod(struct stm32_lptim_dev_s *dev, - uint32_t period) -{ #ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2 - uint32_t timeout; +/**************************************************************************** + * Name: stm32_lptim_writesync + * + * Description: + * Write ARR or CMP and, when the timer is enabled, wait until the write + * to the register in the LPTIM kernel clock domain is complete. + * + ****************************************************************************/ - /* For STM32H5: Clear ARROK flag BEFORE writing ARR when timer is enabled - * This ensures we wait for the new value to be loaded - */ +static void stm32_lptim_writesync(struct stm32_lptim_dev_s *dev, + uint8_t offset, uint32_t value, + uint32_t okflag) +{ + bool enabled = (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & + LPTIM_CR_ENABLE) != 0; + uint32_t timeout; - if (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & LPTIM_CR_ENABLE) + if (enabled) { - stm32_putreg32(dev, STM32_LPTIM_ICR_OFFSET, LPTIM_ISR_ARROK); + stm32_putreg32(dev, STM32_LPTIM_ICR_OFFSET, okflag); } -#endif - stm32_putreg32(dev, STM32_LPTIM_ARR_OFFSET, period); - -#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2 - /* Wait for ARROK flag when timer is enabled */ + stm32_putreg32(dev, offset, value); - if (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & LPTIM_CR_ENABLE) + if (enabled) { timeout = 10000; - while (!(stm32_getreg32(dev, STM32_LPTIM_ISR_OFFSET) & LPTIM_ISR_ARROK) - && timeout > 0) + while (!(stm32_getreg32(dev, STM32_LPTIM_ISR_OFFSET) & okflag) && + timeout > 0) { timeout--; } } +} #endif + +/**************************************************************************** + * Name: stm32_lptim_setmode + * + * Description: + * Disable the timer, or enable it and start counting once or + * continuously. + * + ****************************************************************************/ + +static int stm32_lptim_setmode(struct stm32_lptim_dev_s *dev, + stm32_lptim_mode_t mode) +{ + DEBUGASSERT(dev != NULL); + + mode &= STM32_LPTIM_MODE_MASK; + if (mode == STM32_LPTIM_MODE_DISABLED) + { + stm32_lptim_enable(dev, false); + } + else if (mode == STM32_LPTIM_MODE_SINGLE || + mode == STM32_LPTIM_MODE_CONTINUOUS) + { + stm32_lptim_enable(dev, true); + stm32_lptim_start(dev, mode); + } + else + { + return -EINVAL; + } + + return OK; } -static void stm32_lptim_setcompare(struct stm32_lptim_dev_s *dev, - uint32_t cmp) +/**************************************************************************** + * Name: stm32_lptim_setclock + * + * Description: + * Set the counter clock to the kernel clock divided by the largest power + * of two (up to 128) whose result is not above freq, and return the + * resulting frequency. freq == 0 stops the LPTIM clock. Requires + * STM32_LPTIMn_CLKIN in board.h. + * + ****************************************************************************/ + +static int stm32_lptim_setclock(struct stm32_lptim_dev_s *dev, + uint32_t freq) { -#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2 - uint32_t timeout; + struct stm32_lptim_priv_s *priv = (struct stm32_lptim_priv_s *)dev; + uint32_t presc; - /* For STM32H5: Clear CMPOK flag BEFORE writing CMP when timer is enabled */ + DEBUGASSERT(dev != NULL); - if (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & LPTIM_CR_ENABLE) + if (freq == 0) { - stm32_putreg32(dev, STM32_LPTIM_ICR_OFFSET, LPTIM_ISR_CMPOK); + modifyreg32(priv->enreg, priv->enbit, 0); + return 0; } -#endif - stm32_putreg32(dev, STM32_LPTIM_CMP_OFFSET, cmp); + if (priv->freq == 0) + { + return -EINVAL; + } -#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2 - /* Wait for CMPOK flag when timer is enabled */ + presc = 0; + while (presc < LPTIM_PRESC_MAX && (priv->freq >> presc) > freq) + { + presc++; + } + + modifyreg32(priv->enreg, 0, priv->enbit); + stm32_modifyreg32(dev, STM32_LPTIM_CFGR_OFFSET, LPTIM_CFGR_PRESC_MASK, + presc << LPTIM_CFGR_PRESC_SHIFT); - if (stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET) & LPTIM_CR_ENABLE) + return priv->freq >> presc; +} + +/**************************************************************************** + * Name: stm32_lptim_setchannel + * + * Description: + * Configure (enable != 0) or release the pin of an output channel. + * + ****************************************************************************/ + +static int stm32_lptim_setchannel(struct stm32_lptim_dev_s *dev, + stm32_lptim_channel_t channel, + int enable) +{ + struct stm32_lptim_priv_s *priv = (struct stm32_lptim_priv_s *)dev; + uint32_t pin; + + DEBUGASSERT(dev != NULL); + + channel &= STM32_LPTIM_CH_MASK; + if (channel < 1 || channel > LPTIM_NCHANNELS) { - timeout = 10000; - while (!(stm32_getreg32(dev, STM32_LPTIM_ISR_OFFSET) & LPTIM_ISR_CMPOK) - && timeout > 0) - { - timeout--; - } + return -EINVAL; } -#endif + + pin = priv->pins[channel - 1]; + if (pin == 0) + { + return -EINVAL; + } + + if (enable) + { + stm32_configgpio(pin); + } + else + { + stm32_unconfiggpio(pin); + } + + return OK; } -static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev) +/**************************************************************************** + * Name: stm32_lptim_setclocksource + * + * Description: + * Count the external clock on input 1 (STM32_LPTIM_CLK_EXT) or the + * kernel clock selected in RCC (any other value). + * + ****************************************************************************/ + +static int stm32_lptim_setclocksource(struct stm32_lptim_dev_s *dev, + stm32_lptim_clksrc_t clksrc) { - /* For a reliable LPTIM_CNT register read access, two consecutive - * read accesses must be performed and compared - */ + DEBUGASSERT(dev != NULL); + + stm32_modifyreg32(dev, STM32_LPTIM_CFGR_OFFSET, LPTIM_CFGR_CKSEL, + clksrc == STM32_LPTIM_CLK_EXT ? LPTIM_CFGR_CKSEL : 0); + return OK; +} + +/**************************************************************************** + * Name: stm32_lptim_setpolarity + ****************************************************************************/ + +static int stm32_lptim_setpolarity(struct stm32_lptim_dev_s *dev, + stm32_lptim_clkpol_t polarity) +{ + DEBUGASSERT(dev != NULL); + + if (polarity > STM32_LPTIM_CLKPOL_BOTH) + { + return -EINVAL; + } + + /* The enumeration values are the CKPOL field values */ + stm32_modifyreg32(dev, STM32_LPTIM_CFGR_OFFSET, LPTIM_CFGR_CKPOL_MASK, + (uint32_t)polarity << LPTIM_CFGR_CKPOL_SHIFT); + return OK; +} + +/**************************************************************************** + * Name: stm32_lptim_getcounter + ****************************************************************************/ + +static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev) +{ uint32_t cnt1; uint32_t cnt2; + DEBUGASSERT(dev != NULL); + + /* For a reliable LPTIM_CNT register read access, two consecutive + * read accesses must be performed and compared + */ + cnt2 = stm32_getreg32(dev, STM32_LPTIM_CNT_OFFSET); do @@ -252,174 +685,218 @@ static uint32_t stm32_lptim_getcounter(struct stm32_lptim_dev_s *dev) return cnt1; } +/**************************************************************************** + * Name: stm32_lptim_setcountmode + * + * Description: + * Increment the counter on each counter clock pulse or on each valid + * pulse on input 1. + * + ****************************************************************************/ + +static int stm32_lptim_setcountmode(struct stm32_lptim_dev_s *dev, + stm32_lptim_cntmode_t cntmode) +{ + DEBUGASSERT(dev != NULL); + + if (cntmode != STM32_LPTIM_COUNT_CLOCK && + cntmode != STM32_LPTIM_COUNT_EXTTRIG) + { + return -EINVAL; + } + + stm32_modifyreg32(dev, STM32_LPTIM_CFGR_OFFSET, LPTIM_CFGR_COUNTMODE, + cntmode == STM32_LPTIM_COUNT_EXTTRIG ? + LPTIM_CFGR_COUNTMODE : 0); + return OK; +} + +/**************************************************************************** + * Name: stm32_lptim_setperiod / stm32_lptim_getperiod + ****************************************************************************/ + +static void stm32_lptim_setperiod(struct stm32_lptim_dev_s *dev, + uint32_t period) +{ + DEBUGASSERT(dev != NULL); + +#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2 + stm32_lptim_writesync(dev, STM32_LPTIM_ARR_OFFSET, period, + LPTIM_ISR_ARROK); +#else + stm32_putreg32(dev, STM32_LPTIM_ARR_OFFSET, period); +#endif +} + +static uint32_t stm32_lptim_getperiod(struct stm32_lptim_dev_s *dev) +{ + DEBUGASSERT(dev != NULL); + + return stm32_getreg32(dev, STM32_LPTIM_ARR_OFFSET); +} + +/**************************************************************************** + * Name: stm32_lptim_setcfgr + ****************************************************************************/ + +static void stm32_lptim_setcfgr(struct stm32_lptim_dev_s *dev, + uint32_t regval) +{ + stm32_putreg32(dev, STM32_LPTIM_CFGR_OFFSET, regval); +} + +/**************************************************************************** + * Name: stm32_lptim_setcompare + ****************************************************************************/ + +static void stm32_lptim_setcompare(struct stm32_lptim_dev_s *dev, + uint32_t cmp) +{ +#ifdef CONFIG_STM32_HAVE_IP_LPTIM_V2 + stm32_lptim_writesync(dev, STM32_LPTIM_CMP_OFFSET, cmp, LPTIM_ISR_CMPOK); +#else + stm32_putreg32(dev, STM32_LPTIM_CMP_OFFSET, cmp); +#endif +} + +/**************************************************************************** + * Name: stm32_lptim_setinput + * + * Description: + * Select the input 1 (input == 0) or input 2 (input != 0) multiplexer + * setting in CFGR2. The valid settings are instance specific. + * + ****************************************************************************/ + static int stm32_lptim_setinput(struct stm32_lptim_dev_s *dev, uint32_t input, uint32_t mux) { - switch (dev->base) + if (input == 0) { -#ifdef CONFIG_STM32_LPTIM1 - case STM32_LPTIM1_BASE: -#endif -#ifdef CONFIG_STM32_LPTIM2 - case STM32_LPTIM2_BASE: -#endif -#if defined(CONFIG_STM32_LPTIM1) || defined(CONFIG_STM32_LPTIM2) - if (input == 0) - { - modifyreg32(dev->base + STM32_LPTIM_CFGR2_OFFSET, - LPTIM_CFGR2_IN1SEL_MASK, mux); - } - else - { - modifyreg32(dev->base + STM32_LPTIM_CFGR2_OFFSET, + stm32_modifyreg32(dev, STM32_LPTIM_CFGR2_OFFSET, + LPTIM_CFGR2_IN1SEL_MASK, + mux << LPTIM_CFGR2_IN1SEL_SHIFT); + } + else + { + stm32_modifyreg32(dev, STM32_LPTIM_CFGR2_OFFSET, LPTIM_CFGR2_IN2SEL_MASK, mux << LPTIM_CFGR2_IN2SEL_SHIFT); - } - break; -#endif -#ifdef CONFIG_STM32_LPTIM3 - case STM32_LPTIM3_BASE: - modifyreg32(dev->base + STM32_LPTIM_CFGR2_OFFSET, - LPTIM_CFGR2_IN1SEL_MASK, mux); - break; -#endif - default: - return -EINVAL; } return OK; } +/**************************************************************************** + * Name: stm32_lptim_enable + ****************************************************************************/ + static void stm32_lptim_enable(struct stm32_lptim_dev_s *dev, bool on) { - uint32_t val = stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET); - if (on) { - val |= LPTIM_CR_ENABLE; + stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_ENABLE); } else { - val &= ~LPTIM_CR_ENABLE; + stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, LPTIM_CR_ENABLE, 0); } - - stm32_putreg32(dev, STM32_LPTIM_CR_OFFSET, val); } +/**************************************************************************** + * Name: stm32_lptim_start + ****************************************************************************/ + static void stm32_lptim_start(struct stm32_lptim_dev_s *dev, - stm32_lptim_start_mode_t mode) + stm32_lptim_mode_t mode) { - uint32_t val = stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET); - - switch (mode) + switch (mode & STM32_LPTIM_MODE_MASK) { case STM32_LPTIM_MODE_CONTINUOUS: - val |= LPTIM_CR_CNTSTRT; + stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_CNTSTRT); break; + case STM32_LPTIM_MODE_SINGLE: - val |= LPTIM_CR_SNGSTRT; + stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_SNGSTRT); break; - } - stm32_putreg32(dev, STM32_LPTIM_CR_OFFSET, val); + default: + break; + } } +/**************************************************************************** + * Name: stm32_lptim_resetcounter + ****************************************************************************/ + static void stm32_lptim_resetcounter(struct stm32_lptim_dev_s *dev) { - uint32_t val = stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET); - - val |= LPTIM_CR_COUNTRST; - stm32_putreg32(dev, STM32_LPTIM_CR_OFFSET, val); + stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_COUNTRST); } +/**************************************************************************** + * Name: stm32_lptim_enablerar + ****************************************************************************/ + static void stm32_lptim_enablerar(struct stm32_lptim_dev_s *dev, bool on) { - uint32_t val = stm32_getreg32(dev, STM32_LPTIM_CR_OFFSET); - if (on) { - val |= LPTIM_CR_RSTARE; + stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, 0, LPTIM_CR_RSTARE); } else { - val &= ~LPTIM_CR_RSTARE; + stm32_modifyreg32(dev, STM32_LPTIM_CR_OFFSET, LPTIM_CR_RSTARE, 0); } - - stm32_putreg32(dev, STM32_LPTIM_CR_OFFSET, val); } +/**************************************************************************** + * Name: stm32_lptim_setisr + ****************************************************************************/ + static int stm32_lptim_setisr(struct stm32_lptim_dev_s *dev, xcpt_t handler, void *arg, int source) { - int vectorno; + int irq; DEBUGASSERT(dev != NULL); DEBUGASSERT(source == 0); - switch (dev->base) - { -#ifdef CONFIG_STM32_LPTIM1 - case STM32_LPTIM1_BASE: - vectorno = STM32_IRQ_LPTIM1; - break; -#endif -#ifdef CONFIG_STM32_LPTIM2 - case STM32_LPTIM2_BASE: - vectorno = STM32_IRQ_LPTIM2; - break; -#endif -#ifdef CONFIG_STM32_LPTIM3 - case STM32_LPTIM3_BASE: - vectorno = STM32_IRQ_LPTIM3; - break; -#endif -#ifdef CONFIG_STM32_LPTIM4 - case STM32_LPTIM4_BASE: - vectorno = STM32_IRQ_LPTIM4; - break; -#endif -#ifdef CONFIG_STM32_LPTIM5 - case STM32_LPTIM5_BASE: - vectorno = STM32_IRQ_LPTIM5; - break; -#endif - - default: - return -EINVAL; - } + irq = ((struct stm32_lptim_priv_s *)dev)->irq; /* Disable interrupt when callback is removed */ if (!handler) { - up_disable_irq(vectorno); - irq_detach(vectorno); + up_disable_irq(irq); + irq_detach(irq); return OK; } /* Otherwise set callback and enable interrupt */ - irq_attach(vectorno, handler, arg); - up_enable_irq(vectorno); + irq_attach(irq, handler, arg); + up_enable_irq(irq); #ifdef CONFIG_ARCH_IRQPRIO /* Set the interrupt priority */ - up_prioritize_irq(vectorno, NVIC_SYSH_PRIORITY_DEFAULT); + up_prioritize_irq(irq, NVIC_SYSH_PRIORITY_DEFAULT); #endif return OK; } +/**************************************************************************** + * Name: stm32_lptim_enableint / stm32_lptim_disableint / stm32_lptim_ackint + ****************************************************************************/ + static void stm32_lptim_enableint(struct stm32_lptim_dev_s *dev, int source) { DEBUGASSERT(dev != NULL); - uint32_t val = stm32_getreg32(dev, STM32_LPTIM_IER_OFFSET); - - val |= source; - stm32_putreg32(dev, STM32_LPTIM_IER_OFFSET, val); + stm32_modifyreg32(dev, STM32_LPTIM_IER_OFFSET, 0, source); } static void stm32_lptim_disableint(struct stm32_lptim_dev_s *dev, @@ -427,10 +904,7 @@ static void stm32_lptim_disableint(struct stm32_lptim_dev_s *dev, { DEBUGASSERT(dev != NULL); - uint32_t val = stm32_getreg32(dev, STM32_LPTIM_IER_OFFSET); - - val &= ~source; - stm32_putreg32(dev, STM32_LPTIM_IER_OFFSET, val); + stm32_modifyreg32(dev, STM32_LPTIM_IER_OFFSET, source, 0); } static void stm32_lptim_ackint(struct stm32_lptim_dev_s *dev, int source) @@ -442,100 +916,46 @@ static void stm32_lptim_ackint(struct stm32_lptim_dev_s *dev, int source) * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: stm32_lptim_init + ****************************************************************************/ + struct stm32_lptim_dev_s *stm32_lptim_init(int lptimer) { - struct stm32_lptim_dev_s *dev = NULL; + struct stm32_lptim_priv_s *priv; - /* Get structure and enable power */ + if (lptimer < 1 || lptimer > (int)nitems(g_lptim)) + { + return NULL; + } - switch (lptimer) + priv = g_lptim[lptimer - 1]; + if (priv == NULL || priv->inuse) { -#if defined(CONFIG_STM32_LPTIM1) && defined(STM32_RCC_LPTIM1_EN_REG) - case 1: - dev = &stm32_lptim1_priv; - modifyreg32(STM32_RCC_LPTIM1_EN_REG, 0, STM32_RCC_LPTIM1_EN); - break; -#endif -#if defined(CONFIG_STM32_LPTIM2) && defined(STM32_RCC_LPTIM2_EN_REG) - case 2: - dev = &stm32_lptim2_priv; - modifyreg32(STM32_RCC_LPTIM2_EN_REG, 0, STM32_RCC_LPTIM2_EN); - break; -#endif -#if defined(CONFIG_STM32_LPTIM3) && defined(STM32_RCC_LPTIM3_EN_REG) - case 3: - dev = &stm32_lptim3_priv; - modifyreg32(STM32_RCC_LPTIM3_EN_REG, 0, STM32_RCC_LPTIM3_EN); - break; -#endif -#if defined(CONFIG_STM32_LPTIM4) && defined(STM32_RCC_LPTIM4_EN_REG) - case 4: - dev = &stm32_lptim4_priv; - modifyreg32(STM32_RCC_LPTIM4_EN_REG, 0, STM32_RCC_LPTIM4_EN); - break; -#endif -#if defined(CONFIG_STM32_LPTIM5) && defined(STM32_RCC_LPTIM5_EN_REG) - case 5: - dev = &stm32_lptim5_priv; - modifyreg32(STM32_RCC_LPTIM5_EN_REG, 0, STM32_RCC_LPTIM5_EN); - break; -#endif -#if defined(CONFIG_STM32_LPTIM6) && defined(STM32_RCC_LPTIM6_EN_REG) - case 6: - dev = &stm32_lptim6_priv; - modifyreg32(STM32_RCC_LPTIM6_EN_REG, 0, STM32_RCC_LPTIM6_EN); - break; -#endif - default: - return NULL; + return NULL; } - return dev; + modifyreg32(priv->enreg, 0, priv->enbit); + modifyreg32(priv->rstreg, 0, priv->rstbit); + modifyreg32(priv->rstreg, priv->rstbit, 0); + + priv->inuse = true; + return (struct stm32_lptim_dev_s *)priv; } -int stm32_lptim_deinit(struct stm32_lptim_dev_s * dev) -{ - DEBUGASSERT(dev != NULL); +/**************************************************************************** + * Name: stm32_lptim_deinit + ****************************************************************************/ - /* Disable power */ +int stm32_lptim_deinit(struct stm32_lptim_dev_s *dev) +{ + struct stm32_lptim_priv_s *priv = (struct stm32_lptim_priv_s *)dev; - switch (dev->base) - { -#if defined(CONFIG_STM32_LPTIM1) && defined(STM32_RCC_LPTIM1_EN_REG) - case STM32_LPTIM1_BASE: - modifyreg32(STM32_RCC_LPTIM1_EN_REG, STM32_RCC_LPTIM1_EN, 0); - break; -#endif -#if defined(CONFIG_STM32_LPTIM2) && defined(STM32_RCC_LPTIM2_EN_REG) - case STM32_LPTIM2_BASE: - modifyreg32(STM32_RCC_LPTIM2_EN_REG, STM32_RCC_LPTIM2_EN, 0); - break; -#endif -#if defined(CONFIG_STM32_LPTIM3) && defined(STM32_RCC_LPTIM3_EN_REG) - case STM32_LPTIM3_BASE: - modifyreg32(STM32_RCC_LPTIM3_EN_REG, STM32_RCC_LPTIM3_EN, 0); - break; -#endif -#if defined(CONFIG_STM32_LPTIM4) && defined(STM32_RCC_LPTIM4_EN_REG) - case STM32_LPTIM4_BASE: - modifyreg32(STM32_RCC_LPTIM4_EN_REG, STM32_RCC_LPTIM4_EN, 0); - break; -#endif -#if defined(CONFIG_STM32_LPTIM5) && defined(STM32_RCC_LPTIM5_EN_REG) - case STM32_LPTIM5_BASE: - modifyreg32(STM32_RCC_LPTIM5_EN_REG, STM32_RCC_LPTIM5_EN, 0); - break; -#endif -#if defined(CONFIG_STM32_LPTIM6) && defined(STM32_RCC_LPTIM6_EN_REG) - case STM32_LPTIM6_BASE: - modifyreg32(STM32_RCC_LPTIM6_EN_REG, STM32_RCC_LPTIM6_EN, 0); - break; -#endif - default: - return -EINVAL; - } + DEBUGASSERT(dev != NULL); + modifyreg32(priv->enreg, priv->enbit, 0); + priv->inuse = false; return OK; } -#endif /* defined(CONFIG_STM32_LPTIM1 || ... || CONFIG_STM32_LPTIM5) */ +#endif /* CONFIG_STM32_LPTIM1 || ... || CONFIG_STM32_LPTIM6 */ diff --git a/arch/arm/src/common/stm32/stm32_lptim.h b/arch/arm/src/common/stm32/stm32_lptim.h index 3ed2a3b736a..1afe37be7f6 100644 --- a/arch/arm/src/common/stm32/stm32_lptim.h +++ b/arch/arm/src/common/stm32/stm32_lptim.h @@ -28,6 +28,10 @@ ****************************************************************************/ #include <nuttx/config.h> +#include <nuttx/irq.h> + +#include <stdbool.h> +#include <stdint.h> #include "chip.h" #include "hardware/stm32_lptim.h" @@ -36,6 +40,27 @@ * Pre-processor Definitions ****************************************************************************/ +#define STM32_LPTIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode)) +#define STM32_LPTIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq)) +#define STM32_LPTIM_SETCHANNEL(d,ch,en) ((d)->ops->setchannel(d,ch,en)) +#define STM32_LPTIM_SETCLOCKSOURCE(d,s) ((d)->ops->setclocksource(d,s)) +#define STM32_LPTIM_SETPOLARITY(d,p) ((d)->ops->setpolarity(d,p)) +#define STM32_LPTIM_GETCOUNTER(d) ((d)->ops->getcounter(d)) +#define STM32_LPTIM_SETCOUNTMODE(d,m) ((d)->ops->setcountmode(d,m)) +#define STM32_LPTIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period)) +#define STM32_LPTIM_GETPERIOD(d) ((d)->ops->getperiod(d)) +#define STM32_LPTIM_SETCFGR(d,regval) ((d)->ops->setcfgr(d,regval)) +#define STM32_LPTIM_SETCOMPARE(d,cmp) ((d)->ops->setcompare(d,cmp)) +#define STM32_LPTIM_SETINPUT(d,in,mux) ((d)->ops->setinput(d,in,mux)) +#define STM32_LPTIM_ENABLE(d,on) ((d)->ops->enable(d,on)) +#define STM32_LPTIM_START(d,mode) ((d)->ops->start(d,mode)) +#define STM32_LPTIM_RESETCOUNTER(d) ((d)->ops->resetcounter(d)) +#define STM32_LPTIM_ENABLERAR(d,on) ((d)->ops->enablerar(d,on)) +#define STM32_LPTIM_SETISR(d,hnd,arg,s) ((d)->ops->setisr(d,hnd,arg,s)) +#define STM32_LPTIM_ENABLEINT(d,s) ((d)->ops->enableint(d,s)) +#define STM32_LPTIM_DISABLEINT(d,s) ((d)->ops->disableint(d,s)) +#define STM32_LPTIM_ACKINT(d,s) ((d)->ops->ackint(d,s)) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -49,31 +74,76 @@ extern "C" typedef enum { - STM32_LPTIM_MODE_CONTINUOUS = 0x00, - STM32_LPTIM_MODE_SINGLE = 0x01 -} stm32_lptim_start_mode_t; + STM32_LPTIM_MODE_UNUSED = -1, + STM32_LPTIM_MODE_DISABLED = 0, + STM32_LPTIM_MODE_SINGLE = 1, + STM32_LPTIM_MODE_CONTINUOUS = 2, + STM32_LPTIM_MODE_MASK = 15 +} stm32_lptim_mode_t; + +/* Counter clock: STM32_LPTIM_CLK_EXT is the LPTIM input 1, all other + * values select the kernel clock chosen in RCC. + */ + +typedef enum +{ + STM32_LPTIM_CLK_PCLK = 0, + STM32_LPTIM_CLK_LSI = 1, + STM32_LPTIM_CLK_HSI = 2, + STM32_LPTIM_CLK_LSE = 3, + STM32_LPTIM_CLK_EXT = 4 +} stm32_lptim_clksrc_t; -/* LPTIM Device Structure */ +typedef enum +{ + STM32_LPTIM_COUNT_CLOCK = 0, + STM32_LPTIM_COUNT_EXTTRIG = 1 +} stm32_lptim_cntmode_t; + +typedef enum +{ + STM32_LPTIM_CLKPOL_RISING = 0, + STM32_LPTIM_CLKPOL_FALLING = 1, + STM32_LPTIM_CLKPOL_BOTH = 2 +} stm32_lptim_clkpol_t; + +typedef enum +{ + STM32_LPTIM_CH_DISABLED = 0, + STM32_LPTIM_CH_CHINVALID = 0, + STM32_LPTIM_CH_CH1 = 1, + STM32_LPTIM_CH_CH2 = 2, + STM32_LPTIM_CH_CH3 = 3, + STM32_LPTIM_CH_MASK = 15 +} stm32_lptim_channel_t; struct stm32_lptim_dev_s { - const struct stm32_lptim_ops_s *ops; - uint32_t base; + const struct stm32_lptim_ops_s *ops; }; -/* LPTIM Operations */ - struct stm32_lptim_ops_s { - void (*setcfgr)(struct stm32_lptim_dev_s *dev, uint32_t regval); + int (*setmode)(struct stm32_lptim_dev_s *dev, + stm32_lptim_mode_t mode); + int (*setclock)(struct stm32_lptim_dev_s *dev, uint32_t freq); + int (*setchannel)(struct stm32_lptim_dev_s *dev, + stm32_lptim_channel_t channel, int enable); + int (*setclocksource)(struct stm32_lptim_dev_s *dev, + stm32_lptim_clksrc_t clksrc); + int (*setpolarity)(struct stm32_lptim_dev_s *dev, + stm32_lptim_clkpol_t polarity); + uint32_t (*getcounter)(struct stm32_lptim_dev_s *dev); + int (*setcountmode)(struct stm32_lptim_dev_s *dev, + stm32_lptim_cntmode_t cntmode); void (*setperiod)(struct stm32_lptim_dev_s *dev, uint32_t period); + uint32_t (*getperiod)(struct stm32_lptim_dev_s *dev); + void (*setcfgr)(struct stm32_lptim_dev_s *dev, uint32_t regval); void (*setcompare)(struct stm32_lptim_dev_s *dev, uint32_t cmp); - uint32_t (*getcounter)(struct stm32_lptim_dev_s *dev); int (*setinput)(struct stm32_lptim_dev_s *dev, uint32_t input, uint32_t mux); void (*enable)(struct stm32_lptim_dev_s *dev, bool on); - void (*start)(struct stm32_lptim_dev_s *dev, - stm32_lptim_start_mode_t mode); + void (*start)(struct stm32_lptim_dev_s *dev, stm32_lptim_mode_t mode); void (*resetcounter)(struct stm32_lptim_dev_s *dev); void (*enablerar)(struct stm32_lptim_dev_s *dev, bool on); @@ -90,7 +160,7 @@ struct stm32_lptim_ops_s * Public Function Prototypes ****************************************************************************/ -/* Power-up low power timer and get its structure */ +/* Power-up and reset low power timer and get its structure */ struct stm32_lptim_dev_s *stm32_lptim_init(int lptimer);
